{ "info": { "author": "Gary M. Josack", "author_email": "gary@byoteki.com", "bugtrack_url": null, "classifiers": [ "Programming Language :: Python", "Topic :: Software Development", "Topic :: Software Development :: Libraries", "Topic :: Software Development :: Libraries :: Python Modules" ], "description": "gsh\n===\n\nDescription\n~~~~~~~~~~~\n\nGSH is a pluggable version of DSH (Distributed Shell) written in Python.\nBoth a module and a command-line tool for running a shell command over\nmultiple machines are included. GSH can be extended by adding new host\nloaders as well as hooking into various stages of the runtime.\n\nWhile I plan to keep the api stable for the command line, the module's\ninterface and plugin interfaces are still potentially evolving and I\ncan't guarantee all changes will be backwards compatible at this time.\n\nInstallation\n~~~~~~~~~~~~\n\nNew versions will be updated to PyPI pretty regularly so it should be as\neasy as:\n\n::\n\n pip install gsh\n\nOn Debian/Ubuntu systems you will need the \"python-dev\" and \"libevent-dev\"\npackages installed.\n\nExamples\n~~~~~~~~\n\n::\n\n # Run uptime across all nginx machines\n gsh -g nginx uptime\n\n # Restart nginx serially\n gsh -wg nginx sudo /etc/init.d/nginx restart\n\n # Run w across three manual machines.\n gsh -m host1,host2 -m host3 w\n\nConfiguration\n~~~~~~~~~~~~~\n\nMany of the default configuration options can be overridden with a\nconfiguration file. Configuration is currently specified as a YAML\ndocument. The following is what the default configuration would look\nlike:\n\n::\n\n forklimit: 64\n print_machines: true\n print_output: true\n show_percent: false\n concurrent: true\n timeout: null\n plugin_dirs: []\n hooks: []\n executor: \"ssh\"\n\nConfiguration files are read from the following locations, being\noverridden in the order they are read:\n\n- */etc/gsh/gsh.yaml*\n- *~/.gsh/gsh.yaml*\n\nGroup Files\n~~~~~~~~~~~\n\nOne of the default host loaders (-g) allows you to specify group files\nby name. Group files contain a newline delimited list of hosts with an\noptional user@ specified. This loader will search for these files in the\nfollowing locations\n\n- *~/.gsh/group*\n- *~/.dsh/group*\n- */etc/gsh/group*\n- */etc/dsh/group*\n\nThe first group file found will win. The loader will not continue\nsearching through all paths. An example group that might be accessed\nwhen a user types the command **gsh -g test\\_hosts uptime** would be:\n\n*/etc/gsh/group/test\\_hosts*\n``bash test_host1.example.com test_host2.example.com # Users can be specified. Also comments are ignored. roleaccount@test_host2.example.com``\n\nThis same file format is usable for the file (-f) loader, though you\nmust specify the full path. This loader is more suited to operating over\nad hoc built lists of machines.\n\nPlugins\n~~~~~~~\n\nPlugins are the main reason I set out to create GSH. At my last job we\ncreated DSH replacement that specifically worked with our machine\ndatabase. Now I'm faced with that same decision for querying our machine\ndatabase directly. In addition to just host loaders, I also want to be\nable to log the commands. This is where hooks come in.\n\nLoaders\n'''''''\n\nLoaders are plugins that allow you to build host lists from arbitrary\narguments. They should be stored in a specified plugin\\_dirs location or\nthe default location of */etc/gsh/plugins/loaders*. The base class,\n*BaseHostLoader* in *gsh.plugin*, as well as the builtin plugins located\nin *gsh/plugins/loaders* in the package itself, are the best way to go\nabout learning how to add new loaders.\n\nAs an example, I currently use a machine database that provides a nice\nset arithmetic syntax. The following example shows how easy it is to add\nthis to GSH:\n\n::\n\n from mdbset import mdbset\n\n class MdbSetLoader(BaseHostLoader):\n opt_short = \"-q\"\n\n def __call__(self, *args):\n return mdbset(*args)\n\nNow we can simply do the following to get a list of all nginx boxes that\naren't serving mobile using:\n\n::\n\n gsh -q \"nginx -nginx-mobile\"\n\nWhile the code for the loader does wave over error handling, it really\nis that simple to extend GSH to provide additional host loading\nmechanics.\n\nHooks\n'''''\n\nThe initial concept for hooks came when I wanted to log the various\naspects of DSH to my real-time event logging framework. This was\ndifficult with DSH as I had to parse various aspects of out the output\nand not all data was easily exposed.\n\nAs with loaders, they should be stored in a specified plugin\\_dirs\nlocation or the default location of */etc/gsh/plugins/hooks*. The base\nclass, *BaseExecutionHook* in *gsh.plugin*, as well as the builtin\nplugins located in *gsh/plugins/hooks* in the package itself, are the\nbest way to go about learning how to add new hooks.\n\nExecutors\n'''''''''\n\nExecutors allow you to change out how your commands are executed. The\ndefault execution system is to send your command over ssh, which should\nbe sufficient for most people.\n\nExecutors were added to support logging into machines with a password or\nfor certain network devices which require commands to be sent over an\ninteractive shell.\n\nAs with loaders, they should be stored in a specified plugin\\_dirs\nlocation or the default location of */etc/gsh/plugins/executors*. The\nbase class, *BaseExecutor* in *gsh.plugin*, as well as the builtin\nplugins located in *gsh/plugins/executors* in the package itself, are\nthe best way to go about learning how to add new executors.\n\nRationale\n~~~~~~~~~\n\nOver the last several years DSH has been invaluable to my career as a\nSystem's Administrator, however it has a few shortcomings which have\ncome up over time. I've always wanted to extend DSH in various ways\nspecific to my environment and usually ended up with various wrapper\nscripts to load hosts from inventory databases.\n\nI specifically chose Python for this project as it is the language I use\nmost often and this allows me to use it as a module without shelling\nout. While benchmarks have shown GSH to be slower, the overhead seems to\nbe near constant. Considering the extensibililty, and that most of the\ntime spend is waiting on network I/O, I consider this a fair tradeoff.\n\nImprovements\n~~~~~~~~~~~~\n\nBesides the loaders and hooks mentioned in other sections, GSH provides\na few general benefits over DSH.\n\n**Specifying a loader option (-m/-g/etc) without a command will list the\nhosts.**\n\nMany times I'd like to just see which hosts are in a group. As I added\nnew host loaders for dynamically building host lists this became a more\ncommon desire. With DSH if you failed to specify a command it would just\nSSH to your machines and exit. GSH will print the list of machines that\nwould be be used in the absense of a command.\n\n**The fork limit (-F) can be specified as a percentage.**\n\nOften times you'll end up scripting rolling restarts of services over\nvarious groups of hosts. You might end up specifying a fork limit of 24\nforgetting one of your smaller web pools is smaller than that causing\nthem to all be restarted at once, causing an outage. Your options\npreviously were lowering the limit to the lowest common denominator or\nwriting annoying wrapper scripts. GSH allows you to specify the fork\nlimit as a percentage. e.g. gsh -g mobileweb -F 20% \"/etc/init.d/nginx\nrestart\"\n\n**ps output is cleaner / less forking madness.**\n\nWhile this may seem like a silly thing to list as an improvement, it has\nsufficiently improved my quality of life. In DSH you saw 3 forks for\neach host that you were connected to. This made it annoying to find\nwhich process you should be killing when it hung. It's also utilizing\nmore processes for no noticable benefit. An example of DSH output is as\nfollows:\n\n::\n\n bash\n \\_ dsh -Mcg test_hosts uptime\n \\_ dsh -Mcg test_host1 uptime\n | \\_ dsh -Mcg test_host1 uptime\n | \\_ rsh test_host1 uptime\n \\_ dsh -Mcg test_host2 uptime\n \\_ dsh -Mcg test_host2 uptime\n \\_ rsh test_host2 uptime\n\nThis is GSH output for comparison:\n\n::\n\n bash\n \\_ python gsh -g test_hosts uptime\n \\_ ssh test_host1 uptime\n \\_ ssh test_host2 uptime\n\n**Timeouts!**\n\nSpeaking of having to know which processes to kill when they've hung...\nGSH provides a timeout option. While setting your SSH connection timeout\nis nice, sometimes the command just hangs indefinitely and you want to\nget your shell back. The -t option of gsh will timeout long running\nprocesses after the specified allotment of time. Be careful with this\nthough as it will kill you command ungracefully (-9).\n\n**Concurrency improvements.**\n\nDSH had this weird issue where it couldn't do a fork limit of 1. It\nwould always have one more host than you has specified. This is a\nbehavior I did not replicate. A fork limit of 1 is now synonymous with\nserial execution mode. In addition to this change I have instituted a\ndefault fork limit of 64. DSH would gladly kill your machine by default\nby forking way too many processes. This limit can be overridden on the\ncommand line or in your personal or system configuration files, however\nno option exists to eliminate this limit.\n\nF.A.Q.\n~~~~~~\n\n**What the hell does GSH stand for?**\n\nGSH stand's for Gary's Shell. Mostly just because I didn't know what to\ncall it and it's close to DSH. Plus who doesn't want a piece of software\nnamed after themselves.\n\n**How do you pronounce GSH?**\n\nYou can either pronounce each character individually or some of us at\nwork have taken to calling it \"geesh.\" The G in geesh is pronounced like\nthe G in gum and not like a J.", "description_content_type": null, "docs_url": null, "download_url": "https://github.com/gmjosack/gsh/archive/master.tar.gz", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/gmjosack/gsh", "keywords": null, "license": "MIT", "maintainer": null, "maintainer_email": null, "name": "gsh", "package_url": "https://pypi.org/project/gsh/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/gsh/", "project_urls": { "Download": "https://github.com/gmjosack/gsh/archive/master.tar.gz", "Homepage": "https://github.com/gmjosack/gsh" }, "release_url": "https://pypi.org/project/gsh/0.12.4/", "requires_dist": null, "requires_python": null, "summary": "Pluggable Distributed SSH Command Executer.", "version": "0.12.4" }, "last_serial": 2034838, "releases": { "0.1": [], "0.10.1": [ { "comment_text": "", "digests": { "md5": "8876ada79afaadb87348370e2ad43790", "sha256": "de3bf5517a36408aef137082ef9fa695e19c73d9b7c6509babd00c9c5524a905" }, "downloads": -1, "filename": "gsh-0.10.1.tar.gz", "has_sig": false, "md5_digest": "8876ada79afaadb87348370e2ad43790", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 17634, "upload_time": "2014-01-09T08:26:27", "url": "https://files.pythonhosted.org/packages/1b/28/7e3d8e637130f510e40fdb69583399d03a1720b929ec6ef124ecb1087dec/gsh-0.10.1.tar.gz" } ], "0.10.2": [ { "comment_text": "", "digests": { "md5": "4d9fbc461b699f126d5c94a47f456965", "sha256": "d3d6da36eb5b16e1a050a0ebfa69e95aa7479977066615748a7334cbe5660d42" }, "downloads": -1, "filename": "gsh-0.10.2.tar.gz", "has_sig": false, "md5_digest": "4d9fbc461b699f126d5c94a47f456965", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 17706, "upload_time": "2014-01-10T06:26:20", "url": "https://files.pythonhosted.org/packages/d6/c6/18c5006d2f36c792109dae40d27564bfca44ed85dd223961217a5dcc37d6/gsh-0.10.2.tar.gz" } ], "0.11.1": [ { "comment_text": "", "digests": { "md5": "8a1ca77c6c9d2207d0c75952808314a0", "sha256": "6adde348cbb65b7469cfc4f270b74ed10b645ca43ebbc5fc4a6af82e6e647c3b" }, "downloads": -1, "filename": "gsh-0.11.1.tar.gz", "has_sig": false, "md5_digest": "8a1ca77c6c9d2207d0c75952808314a0", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 18658, "upload_time": "2014-01-13T21:58:17", "url": "https://files.pythonhosted.org/packages/d1/26/689dcd264c30d0b641e1a9b2c2bef39a1b5859a55b4f014ae3ef2eeed254/gsh-0.11.1.tar.gz" } ], "0.11.2": [ { "comment_text": "", "digests": { "md5": "e2e754613ce4ecd498aeca43a2e4384a", "sha256": "b271208e7ce245ef1c1d60e0f087c04c849708c633f96b6b70c76b1f2d94304d" }, "downloads": -1, "filename": "gsh-0.11.2.tar.gz", "has_sig": false, "md5_digest": "e2e754613ce4ecd498aeca43a2e4384a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 18645, "upload_time": "2014-01-13T22:32:59", "url": "https://files.pythonhosted.org/packages/35/e3/e10cf7f161c2089d11f5779f2c5982be023bb09b32e891ee0250a6a57913/gsh-0.11.2.tar.gz" } ], "0.11.3": [ { "comment_text": "", "digests": { "md5": "d7ffcb8c5adaa5a566f73892fa0ce3c9", "sha256": "d8ca05daf67c88d2172702bdf48cfeeabc07fcc95bd4a06f66d0755c1c7c0bf9" }, "downloads": -1, "filename": "gsh-0.11.3.tar.gz", "has_sig": false, "md5_digest": "d7ffcb8c5adaa5a566f73892fa0ce3c9", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 18673, "upload_time": "2014-01-21T22:39:53", "url": "https://files.pythonhosted.org/packages/6e/6e/6c825140bf2d18a2d54dcba39c2c2b8dd387cf5643b0cbbf42f94646f5d4/gsh-0.11.3.tar.gz" } ], "0.11.4": [ { "comment_text": "", "digests": { "md5": "d148ff36fb7fb9db0eb2604b605eb948", "sha256": "716811db51439451c9cd26263617eda08c1ceb0fda2f410114ad5769a25e0361" }, "downloads": -1, "filename": "gsh-0.11.4.tar.gz", "has_sig": false, "md5_digest": "d148ff36fb7fb9db0eb2604b605eb948", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 18848, "upload_time": "2014-02-13T01:17:54", "url": "https://files.pythonhosted.org/packages/89/0a/597c3cd403729bf7642e23ec03cdc73ef0ec879f59b07e76ed09c397d63e/gsh-0.11.4.tar.gz" } ], "0.11.5": [ { "comment_text": "", "digests": { "md5": "7d7132fb48d02231197967023025ce28", "sha256": "ca362adcdb44fedf0e34f0576557e3c38a8af3d99e81a01f5a7fc48a88ae9a99" }, "downloads": -1, "filename": "gsh-0.11.5.tar.gz", "has_sig": false, "md5_digest": "7d7132fb48d02231197967023025ce28", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 18888, "upload_time": "2014-03-04T22:45:17", "url": "https://files.pythonhosted.org/packages/47/94/de8754f8b93fc5823eee99f737f6c8199b279b14ef0300bbae915cb22ddf/gsh-0.11.5.tar.gz" } ], "0.11.6": [ { "comment_text": "", "digests": { "md5": "6b85b2faa06e94bdb6bf67b3b006c1d6", "sha256": "9d55fd9eb3f980b8eae488d697e77820694108f2ff09822ccbbf4d3a120b9260" }, "downloads": -1, "filename": "gsh-0.11.6.tar.gz", "has_sig": false, "md5_digest": "6b85b2faa06e94bdb6bf67b3b006c1d6", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 18895, "upload_time": "2014-04-04T23:36:58", "url": "https://files.pythonhosted.org/packages/d8/c2/de479a3f886fb8c0b227fce67809007de8cfbfc73c3e1fd86a587af4b8ee/gsh-0.11.6.tar.gz" } ], "0.12.1": [ { "comment_text": "", "digests": { "md5": "60cb826153e3fcc81716b58cabea677f", "sha256": "f9471347d4086fbd9022c0a19bb485c6922ccad04d4e48def9781b82bd23b813" }, "downloads": -1, "filename": "gsh-0.12.1.tar.gz", "has_sig": false, "md5_digest": "60cb826153e3fcc81716b58cabea677f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 19047, "upload_time": "2014-04-23T00:55:40", "url": "https://files.pythonhosted.org/packages/46/80/54684cb9ae5c21b9576aac44023a7fe9f0336def1470e288a12239cffa08/gsh-0.12.1.tar.gz" } ], "0.12.2": [ { "comment_text": "", "digests": { "md5": "e4affc407a1c98a448ff618406a4257a", "sha256": "1cb695dba9cc4bc91e5470f4ff635609b211ee05e9173cbec81a0e85eb60a931" }, "downloads": -1, "filename": "gsh-0.12.2.tar.gz", "has_sig": false, "md5_digest": "e4affc407a1c98a448ff618406a4257a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 19055, "upload_time": "2014-04-23T02:48:16", "url": "https://files.pythonhosted.org/packages/15/73/eae453f32bf5366efac6cf91d22d2c09a5888836e351c4892d171c09e94b/gsh-0.12.2.tar.gz" } ], "0.12.3": [ { "comment_text": "", "digests": { "md5": "d79100953e003aad1203925bea50b717", "sha256": "3de4b42e4475d070649695a615a94c598f8922effa84bd9469ca57477e66552d" }, "downloads": -1, "filename": "gsh-0.12.3.tar.gz", "has_sig": false, "md5_digest": "d79100953e003aad1203925bea50b717", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 19068, "upload_time": "2015-04-21T07:01:29", "url": "https://files.pythonhosted.org/packages/f8/6b/e531296042eb45eefd18f8b7db6b2c66d4246ba10062ca3e5e8c9c0ebf76/gsh-0.12.3.tar.gz" } ], "0.12.4": [ { "comment_text": "", "digests": { "md5": "ae73f1b657b33515ad99c3d9e97fbabb", "sha256": "22e3fbcb4b1ec7295849735bce4c9a6127808bb79ed3a1639c329824f0570627" }, "downloads": -1, "filename": "gsh-0.12.4.tar.gz", "has_sig": false, "md5_digest": "ae73f1b657b33515ad99c3d9e97fbabb", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 19291, "upload_time": "2016-03-29T22:28:27", "url": "https://files.pythonhosted.org/packages/ff/31/d4f61642804144c001572b79ad45fe15b52bc41ff9edd0cae2a80f65ee59/gsh-0.12.4.tar.gz" } ], "0.2": [ { "comment_text": "", "digests": { "md5": "133211934de5b208b11afb8b7a9a270a", "sha256": "e55520f4e32de7feb71ea1330666d9190d8fd5a71394cdc6feb234ba323fa5f9" }, "downloads": -1, "filename": "gsh-0.2.tar.gz", "has_sig": false, "md5_digest": "133211934de5b208b11afb8b7a9a270a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6678, "upload_time": "2013-10-11T04:50:19", "url": "https://files.pythonhosted.org/packages/6b/ff/cb51fddd454cdc30553ae94d46e0107b3e5bcd28e42ff11d95ef06e96d44/gsh-0.2.tar.gz" } ], "0.3": [ { "comment_text": "", "digests": { "md5": "57e6714b019a1defc85d123e8ba47a16", "sha256": "b3cada37e26d0136dd7bde7091d97ad7062cf9c77d1c7b79c1a090ffd236b46f" }, "downloads": -1, "filename": "gsh-0.3.tar.gz", "has_sig": false, "md5_digest": "57e6714b019a1defc85d123e8ba47a16", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7358, "upload_time": "2013-10-11T23:17:21", "url": "https://files.pythonhosted.org/packages/66/94/c476daf78e7b101b03e645609c59887f22e9e87f9c686a92f2789a3731f5/gsh-0.3.tar.gz" } ], "0.4": [ { "comment_text": "", "digests": { "md5": "332081f5ca8ac0e869c5bdda743ae546", "sha256": "5b293cc65f50dcb43577fc8afde53c4991908d27d3417060f5612a6aac379096" }, "downloads": -1, "filename": "gsh-0.4.tar.gz", "has_sig": false, "md5_digest": "332081f5ca8ac0e869c5bdda743ae546", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13752, "upload_time": "2013-10-14T21:20:29", "url": "https://files.pythonhosted.org/packages/6e/a5/51091c83938f149ce3552dd3a6415cd18f1c667c2d11f96df97454482b1b/gsh-0.4.tar.gz" } ], "0.5": [ { "comment_text": "", "digests": { "md5": "7a8815c3aa1afe1aa110697c84ee6d91", "sha256": "32f281f0f55d56ed77a21baf707f036e6cab6bb797ed9211e3a8f0bb6385005f" }, "downloads": -1, "filename": "gsh-0.5.tar.gz", "has_sig": false, "md5_digest": "7a8815c3aa1afe1aa110697c84ee6d91", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13926, "upload_time": "2013-10-22T05:07:12", "url": "https://files.pythonhosted.org/packages/6b/e9/6cb424b3169bf69b62020ffe21a3d3b206b8511275efe7f43657896abd06/gsh-0.5.tar.gz" } ], "0.6": [ { "comment_text": "", "digests": { "md5": "e687ae668e1de9db74f37b5a7a71aa42", "sha256": "dd2981c6432e0d234a0661e8a76e9b4af5757bf9352dadd1e239bcfbeb5e4839" }, "downloads": -1, "filename": "gsh-0.6.tar.gz", "has_sig": false, "md5_digest": "e687ae668e1de9db74f37b5a7a71aa42", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 14027, "upload_time": "2013-10-24T17:44:28", "url": "https://files.pythonhosted.org/packages/91/8a/854b42e2c767f40ffed81753b64191e403f68048f90bfe476519f58d6e0d/gsh-0.6.tar.gz" } ], "0.7": [ { "comment_text": "", "digests": { "md5": "27c39c2c4658707923eae03e6402611a", "sha256": "5f41199f61ef5f75f7c3bf0722677e0fbe8201e713d1f56ef1667a5d80491e18" }, "downloads": -1, "filename": "gsh-0.7.tar.gz", "has_sig": false, "md5_digest": "27c39c2c4658707923eae03e6402611a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 14157, "upload_time": "2013-10-25T07:06:22", "url": "https://files.pythonhosted.org/packages/40/94/38028fde88bec096bc944545bb26f53dd869dc9fcc259d2a9d414d7790fa/gsh-0.7.tar.gz" } ], "0.7.2": [ { "comment_text": "", "digests": { "md5": "2c31985173ce60bf25a5d31bb3309bae", "sha256": "73dd3d2a32cd990e4acacc4e2c7e7cc796c039f94b609c32fc9b8cee466d9a5b" }, "downloads": -1, "filename": "gsh-0.7.2.tar.gz", "has_sig": false, "md5_digest": "2c31985173ce60bf25a5d31bb3309bae", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 14166, "upload_time": "2013-11-01T01:06:02", "url": "https://files.pythonhosted.org/packages/06/ce/585df127c3a6991ceefbe8d9ac742bcf533e4237ec7ffc78c3d0d7a3a1d6/gsh-0.7.2.tar.gz" } ], "0.8.1": [ { "comment_text": "", "digests": { "md5": "9b6d51a51b92f580033e3ecd0473aa28", "sha256": "012fab285c1eca3e597678bd0122485b3c1be04410eabc892f9a92e6af03d522" }, "downloads": -1, "filename": "gsh-0.8.1.tar.gz", "has_sig": false, "md5_digest": "9b6d51a51b92f580033e3ecd0473aa28", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 14394, "upload_time": "2013-11-03T01:54:06", "url": "https://files.pythonhosted.org/packages/62/c6/0b69bf92084b9e9c872619f0aa0c8f673d348517b2fda503ccd0df9c1caf/gsh-0.8.1.tar.gz" } ], "0.8.2": [ { "comment_text": "", "digests": { "md5": "2d21dcb0cebce8fde2f08c16f8918c6b", "sha256": "6bdfa7cf39a323bdef7d48b79538649b82a5a9591ca6621ea4dc41a75a180eee" }, "downloads": -1, "filename": "gsh-0.8.2.tar.gz", "has_sig": false, "md5_digest": "2d21dcb0cebce8fde2f08c16f8918c6b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 14585, "upload_time": "2013-11-13T02:33:20", "url": "https://files.pythonhosted.org/packages/b1/17/b1283f5d37ebfbdf50c6e53c011bf9ce98cf2117536721513aa4399acd3d/gsh-0.8.2.tar.gz" } ], "0.9.1": [ { "comment_text": "", "digests": { "md5": "ac42eac2723a8b107ea95f5fff88a2ea", "sha256": "c19facf30f477af1fa1d79755f661ed776d7f9109a61271d5e469055e466c649" }, "downloads": -1, "filename": "gsh-0.9.1.tar.gz", "has_sig": false, "md5_digest": "ac42eac2723a8b107ea95f5fff88a2ea", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 16328, "upload_time": "2013-12-04T23:05:21", "url": "https://files.pythonhosted.org/packages/fa/35/0f79d0fca00bf9b71b0dbd6a94304b072e6c3de76c62f23129e56b427d6d/gsh-0.9.1.tar.gz" } ], "0.9.2": [ { "comment_text": "", "digests": { "md5": "4f20a81da162885036856e0da59b331d", "sha256": "2c1e8ef536fadb95b183ab9764266be2878ed97d47e2dc3f08bed6ac1eb10bbd" }, "downloads": -1, "filename": "gsh-0.9.2.tar.gz", "has_sig": false, "md5_digest": "4f20a81da162885036856e0da59b331d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 16336, "upload_time": "2013-12-30T18:54:43", "url": "https://files.pythonhosted.org/packages/cb/7f/09b5f6d03a80d78061aa5284876f8bd10575e33aafae5fe49aefa139bbbc/gsh-0.9.2.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "ae73f1b657b33515ad99c3d9e97fbabb", "sha256": "22e3fbcb4b1ec7295849735bce4c9a6127808bb79ed3a1639c329824f0570627" }, "downloads": -1, "filename": "gsh-0.12.4.tar.gz", "has_sig": false, "md5_digest": "ae73f1b657b33515ad99c3d9e97fbabb", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 19291, "upload_time": "2016-03-29T22:28:27", "url": "https://files.pythonhosted.org/packages/ff/31/d4f61642804144c001572b79ad45fe15b52bc41ff9edd0cae2a80f65ee59/gsh-0.12.4.tar.gz" } ] }