{ "info": { "author": "Pavel Gurkov", "author_email": "true.neu@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 3 - Alpha", "Environment :: Console", "Intended Audience :: Developers", "Intended Audience :: End Users/Desktop", "Intended Audience :: System Administrators", "License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)", "Programming Language :: Python", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.5", "Topic :: System :: Shells", "Topic :: System :: Systems Administration", "Topic :: Utilities" ], "description": "swiss-knife\n===========\n\nAn extendable utility with plugins for doing everything with\nself-defined hosts/hostgroups, utilizing API of your environment, with\nparallel ssh out of the box.\n\nDestroying all your databases at once has never been this simple!\n\n::\n\n swk pssh ^mysql 'sudo rm -rf /var/lib/mysql'\n\n(yeah, you really shouldn't do that in production environment. Unless\nyou're angry and desperate.)\n\nPlease update\n'''''''''''''\n\nIf you're using ``swk`` older than v0.0.4a13, please update to the\nlatest version. There's a whole lot of bugfixes every week, as\ndevelopment's in progress, thus I've included auto check for updates\nfunction. It runs once a day when you run swk, and outputs to stderr if\nnewer version is available. You can turn it off by setting\n'check\\_for\\_updates' to anything but 'yes' in **swk.ini** .\n\nWhat can it do?\n~~~~~~~~~~~~~~~\n\nThe basic idea is: you specify what to do (a command), a list of hosts\nor hostgroups to do that with, and additional arguments if needed\n(depends on what you want to do). You can easily define your own\ncommands through the plugin interface, as well as your own hostgroup\nparsers (usually they'll just ask some API in your environment about\nwhich hosts are included in provided hostgroup). Basic Foreman, Zabbix\nAPI and ssh functions are supported out of the box.\n\nPlease note that this is *not* ``fabric`` (though it uses ``paramiko``,\nboth are marvellous pieces of software), and this is *not* ``pssh`` (it\nuses its own way of parallelling ssh sessions, and its own output\nhandling). This utility is designed to work in small environments and\nperform ad-hoc operations, it's very easy to use (not harder than shell)\nand to configure, it has no learning curve, and it provides a way to\nexecute quick-and-dirty commands on a lot of hosts at hand. You may\nthink of it as of a version of ``ansible -a`` that requires very little\neffort to get usable in your infrastructure (writing parsers to get\nadvantage of tools dividing your hosts to hostgroups) or no effort at\nall if you happen to use Foreman, Zabbix or third-party host grouping\ntools.\n\nInstallation\n~~~~~~~~~~~~\n\n::\n\n pip install swk\n\nIf you need plugins for casp, Foreman or Zabbix, also run\n\n::\n\n pip install swk-casp\n pip install swk-foreman\n pip install swk-zabbix\n\nUpon first execution \\`swk\\`\\` will create **~/.swk** directory, where\nyou should find **swk.ini** configuration file, and that's used to store\nshell mode command history, program's log, various plugins' cache, etc.\n\nPlease note that you should use python3.3+ for shell mode to work.\nEverything else should work with python2.7.6+. You probably may have to\nupdate ``pip`` and ``setuptools``\n(``pip install --upgrade pip setuptools``). You also may have to do all\nof these with ``sudo``, or fall into your **virtualenv** if you use one.\n\nUsage\n~~~~~\n\nTypical usage looks like\n\n``swk pssh \"%hostgroup1[ [-]^hostgroup2 .. host1 [-]host2]\" uptime``\n\nwhich executes uptime on all the hosts over ssh in parallel fashion.\n\n``%``, ``^`` and other non-alphabetical characters are treated as\nhostgroup modifiers which indicate which parser should expand a given\nhostgroup into a host list. hyphen (``-``) in front of hostgroup or a\nhost means that hostgroup or host will be excluded from resulting list.\nA host may be a simple regex (no \\* quantificator or anychar (.), no\nlookahead/lookbehinds), ``swk`` will generate strings that match it and\nuse it as hosts. If you're excluding hosts that aren't included yet,\nnothing happens. Hostlist is expanded from left to right. Example:\n\n``swk pssh \"^g1 -host[1234]\" echo Yay``\n\nwill execute ``echo Yay`` in parallel fashion on each host that's in\nzabbix hostgroup ``g1`` except hosts ``host1``, ``host2``, ``host3`` and\n``host4``.\n\nAvailable and bundled plugins\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nFrom the box, swk supports: - running commands over ssh (``ssh`` and\n``pssh`` commands), copying files over ssh to multiple hosts (``dist``\ncommand, recursive and without preserving times by default), copying\nfiles from multiple hosts over ssh (``gather``) - and just displaying\nresults of hostlist expansion (``dr`` for 'dry-run')\n\nBy installing additional packages named ``swk-``, you also\nget - expanding **zabbix** hostgroups (``^`` modifier), listing, adding\nand removing maintenance periods in Zabbix (``lsmntnce``, ``addmntnce``\nand ``rmmntnce`` commands) - expanding **casp** hostgroups (``%``\nmodifier), special ``ALL`` hostgroup expanding to all the hosts -\ngetting and setting hosts environments in **Foreman** (``getenv`` and\n``setenv`` commands), getting, adding and removing classes linked to\nhosts and hostgroups (``getcls``, ``addcls``, ``rmcls``, ``getgcls``,\n``addgcls``, ``rmgcls`` respectively), searching hosts and hostgroups\nbased on given criteria (``srch`` and ``srchg``), listing available\nclasses (``lscls``) and describing hosts (``desc``).\n\nTo install them, please refer to `Installation <#Installation>`__\nsection above. Also, please read `Usage notes <#usage-notes>`__ below\nbefore using.\n\nDon't forget to make changes to your **swk.ini** before using plugins\n(credentials/urls and such).\n\nHopefully, there are more plugins coming.\n\nExamples\n~~~~~~~~\n\nImagine that you need to grep all your frontend nginx logs for string\n'/api/do\\_something'. Your frontend hostnames are ``frontend00``,\n``frontend01``, ..., ``frontend99``. You could use something like\n\n``swk pssh frontend[0-9][0-9] grep '/api/do_something' /var/log/nginx/access.log``\n\nYou can interrupt the command execution at any moment with Ctrl-C.\n\nSuppose your servers are named a bit more sophisticated, like\n``frontend01``, ``frontend02``, ..., ``frontend25``. This command would\ndo the trick (note the quotes around host expression):\n\n``swk pssh 'frontend([0-1][0-9]|2[0-5]) -frontend00' grep '/api/do_something' /var/log/nginx/access.log``\n\nYou can always verify if you did the host expression right:\n\n``swk dr 'frontend([0-1][0-9]|2[0-5]) -frontend00'``\n\nOutput:\n\n::\n\n frontend01\n frontend02\n <...skipped...>\n frontend24\n frontend25\n\nSuppose you also have servers ``backend01``, ``backend02``, ...,\n``backend10``, and you want to run ``uptime`` on both frontends and\nbackends. Try this one:\n\n``swk pssh 'frontend([0-1][0-9]|2[0-5]) -frontend00 backend(0[1-9]|10)' uptime``\n\nNow imagine you have to execute a certain script named ``test.sh`` on\nthose 25 frontends locally. First, copy it to target hosts:\n\n``swk dist 'frontend([0-1][0-9]|2[0-5]) -frontend00' ./my_scripts/test.sh /usr/share/``\n\nand then execute it:\n\n``swk pssh 'frontend([0-1][0-9]|2[0-5]) -frontend00' /usr/share/test.sh``\n\nImagine you need to do something with nginx logs locally on your\ncomputer (say, a simple statistics calculation). You can gather all the\nlogs to your machine with one command:\n\n``swk gather 'frontend([0-1][0-9]|2[0-5]) -frontend00' /var/log/nginx/access.log ./nginx-logs-from-production``\n\nThis will create 'nginx-logs-from-production' directory in your current\nworking directory, and copy over all the access.log files, appending a\nsuffix so you can tell from which host each log has been copied.\n\nSay you have a Zabbix installation in your environment, and all the\nfrontends are in 'frontend' hostgroup. You can do the same as above\nusing zabbix hostgroup expansion (note that ``zabbix`` module is\ndisabled by default. More on that in `Available\nplugins <#available-and-bundled-plugins>`__ section above)\n\n``swk gather ^frontend /var/log/nginx/access.log ./nginx-logs-from-production``\n\nYou probably already have some cli tools for finding hosts falling under\nsome search criteria. Suppose you have a tool that's called\n``my_awesome_tool`` which returns some hostnames on call, like this:\n\n::\n\n $ my_awesome_tool\n host1\n host2\n host3\n\nIf you want to use your tools as a source for hostlists for ``swk``, you\ncan achieve this in two ways:\n\n::\n\n swk pssh \"`my_awesome_tool`\" uptime\n\nor\n\n::\n\n my_awesome_tool | swk pssh - uptime\n\nwhere ``-`` instead of host expression indicates that ``swk`` reads from\nstdin.\n\nImagine that you have Foreman installation and you need to set all the\nfrontends' environments to 'development' (note that you still use ^\nhere, so host expansion mechanism works with Zabbix hostgroups)\n\n``swk setenv ^frontend development``\n\n...or add to frontend Foreman hostgroup your brand new\n``nginx::verbose_access_logs`` Puppet class\n\n``swk addgcls frontend nginx::verbose_access_logs``\n\nNote: if you have several Foreman hostgroups named the same, but\ndifferent hierarchically (for example, ``debian/mysql`` and ``mysql``),\n``getgcls``, ``addgcls`` and ``rmgcls`` will work with the first group\nreturned by Foreman API.\n\nYou can also get description on an existing host:\n\n::\n\n swk desc myhost\n\nOutput:\n\n::\n\n [myhost.example_domain.com]:\n Hostgroup: mysql\n OS: Debian 7.9\n IP: 192.168.1.1\n Resource: myhypervisor\n Env: production\n Comment: my favorite host!\n\nOr search hosts by a given criteria (Foreman doesn't support everything\nfor a search criterias). There are several short keywords for\nconvenience now: ``hg`` for hostgroup, ``cls`` for class, ``env`` for\nenvironment and ``os`` for OS family (Debian, RedHat etc). Specifying\nseveral implies AND logic:\n\n::\n\n swk srch cls=my_awesome_puppet_class\n\nOutput:\n\n::\n\n myhost\n\nThis way you can combine ``swk`` invocations in something really fun\nlike\n\n::\n\n swk pssh \"`swk srch cls=my_awesome_puppet_class`\" reboot\n\nRemember to use and escape quotes when needed!\n\n``swk pssh ^mysql mysql -e 'show variables like \"read_only\"'`` won't\nwork (due to shell quote processing, it represents\n``mysql -e show variables like \"read only\"``), but\n\n``swk pssh ^mysql \"mysql -e 'show variables like \\\"read_only\\\"'\"`` will.\n\nYou can get more info on available parsers, commands and arguments by\nrunning ``swk -h`` .\n\nIf you need to change your default SSH user, parallel processes count,\nAPI credentials or such, take a look at **swk.ini** file located at\n**~/.swk** .\n\nShell mode\n''''''''''\n\nIf you run ``swk`` without any arguments, it starts in shell mode. Like\nthis:\n\n::\n\n trueneu$ swk\n swk>\n\nYou can do absolutely all the same like in command line mode, but in\nshell mode you don't need to think about quote escaping in tricky\ncommands, because the arguments are treated literally even if not\nquoted.\n\nFor example, that ugly mysql example above would look like this in shell\nmode:\n\n::\n\n swk> pssh ^mysql mysql -e 'show variables like \"read_only\"'\n\nAdditionally, you may call any system utility from inside ``swk`` shell\nvia ``sys`` command or even omit ``sys``:\n\n::\n\n swk> pssh ^mysql mysql -e 'show variables like \"%format%\"' | grep innodb\n\nIt also supports history through ``hist`` command, etc. To get help on\nany command, issue ``help `` or ``help`` without arguments to\nget an overview.\n\nPlease note that shell mode doesn't support backticks yet, so if you\nneed to feed a hostlist to ``swk`` from somewhere, you should use stdin\napproach:\n\n::\n\n swk> srch cls=my_awesome_class | pssh - reboot\n\nDetails\n~~~~~~~\n\nCommands, hostgroup modifiers and parsers code are defined through swk\nplugins. They can be connected to the main program in three ways: being\nincluded in main package under **swk/plugins** dir, having a defined\n**swk\\_plugin** entry point in their setup.py and installed or just\nbeing put in one of **plugins\\_directories** dir from **swk.ini** file.\n\nYou can find some working plugins there mentioned above, as well as\ndummy examples in **swk\\_plugins\\_examples** . Further help can be found\nin **swk.classes**, which you MUST import when defining your own command\nand/or parser modules.\n\nFor example, if you use Nagios in your environment, you can create a\nparser that will expand a Nagios hostgroup into a hostlist, or a command\nthat will take a Nagios hostgroup and do something with it using Nagios\nAPI (say, downtime it or something). Information that's used for modules\nto work (such as authentication information for various APIs) may (and\nshould) be stored in config named **swk.ini**.\n\nShell mode parsing details\n''''''''''''''''''''''''''\n\nWhen in shell mode, every argument starting with the third *to the end\nof the line* is passed literally even if not quoted, backslashes being\nescaped, and then it's shlexed down to a list respectful to quotes. It\nsounds a little bit confusing at first, but it has its benefits. You do\nnot need to escape backslash character, and you don't need the outer\nlevel of quoting when ssh\\`ing this way.\n\nPlease note that these rules work only for ``swk`` commands. Everything\nelse is passed as you'd expect.\n\nTrade-offs: - you may have to implement your own argument parsing in\ncommand plugins for them to work correctly (using a whitespace or\nsomething else as a delimiter). - you have to escape chaining/io\nredirection characters for those to be passed as arguments to commmand\ninstead of work locally. For example, ``ssh remote echo ABC > file``\ncreates ``file`` on local machine, but ``ssh remote echo ABC \\> file``\ndoes the same on remote.\n\nWhy did I do this and why you may need this?\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nI did it simply because there was no such instruments in my environment,\nand I needed them from time to time. As a side note, I hate GUIs and web\ninterfaces for everything that shouldn't be necessary visualized (like\nUML or statistic charts). And I just can't accept that I need to make 10\nmouse clicks to change a host's environment in Foreman when I know\nhostname and environment name exactly. So ``swiss-knife`` is a simple\ninstrument to make simple operations and its functionality can be\nextended rather easily.\n\nThere's a few possible reasons you'll find it useful: - You are a system\nadministrator. If you're not, it's doubtfully can be useful for you in\nany way - You hate clicking GUIs just like me, and your GUI\ninstrument(s) has an API you could use - There's no such an instrument\nin your environment: it's either de-centralized and/or you don't use\nconfiguration management software and its tools heavily - You'd like to\nglue altogether all the stuff you use in your environment to classify or\ngroup hosts and you know a little bit of python\n\nKnown issues and notes\n~~~~~~~~~~~~~~~~~~~~~~\n\nAs this is an alpha version under development, author wouldn't recommend\nto think of ``swk`` as of a reliable tool suitable for running\nimportant, potentially destructive tasks. i.e. restarting/reinstalling\nimportant services, ``sed``\\ ing mission critical configs, etc. Always\ndouble-check command's result on one host before applying it to whole\nproduction, use ``dr`` command.\n\nNo compatibility with future versions is guaranteed yet.\n\n``casp`` is a nice piece of software written by my former colleague Stan\nE. Putrya. It's not yet released to opensource, but I'm sure it will\neventually.\n\n``swk`` uses a small part of ``yolk3k`` package by Rob Cakebread\n(sources can be found on `github `__,\ndistribution on `pypi `__) to\nhandle self-update noticing mechanics. You can turn new version checking\noff by modifying **swk.ini** parameter 'check\\_for\\_updates' to anything\nbut 'yes'.\n\nIt should work on python2.7.6+, python3.3+.\n\nUsage notes\n \n\n- currently, host cannot start with non-alphanumerical character. This\n breaks using something like (host\\|hos)123 as a host expression as\n left bracket will be treated as a hostgroup modifier.\n- ssh module needs a running ssh-agent with private keys added, or\n private keys need to remain password free\n- username for ssh specified in **swk.ini** will override your current\n username and username from .ssh/config if present\n- Ctrl-C works poorly when pssh'ing (providing you unneeded tracebacks\n from multiprocessing)\n- interactive user input is NOT supported when running a command\n- if you have several Foreman hostgroups named the same, but different\n hierarchically (for example, ``debian/mysql`` and ``mysql``),\n ``getgcls``, ``addgcls`` and ``rmgcls`` will work with the first\n group returned by Foreman API.\n- using ``dist`` and ``gather`` commands has a little trick: if you\n want the name expansion to be done at the remote side instead of\n local by your shell when not in swk shell mode, quote it.\n- Foreman ``srch`` routines may work not as you expect, because ``swk``\n relies completely on Foreman's API. For example,\n ``swk srch cls!=myclass`` won't give neither any useful results nor\n error, but this is how API is designed. To check if your query really\n works, try it in the web interface first.\n\nDev notes\n \n\n- if a parser doesn't return any hosts, its job is considered failed\n and desired command doesn't start\n- all the information needed to run a command is added to class\n attributes, more info on that in **swk\\_classes**\n- all the information you've mentioned in config is also added to class\n attributes. Section must be named the same as the class that is being\n configured for this to work; **[Main]** section is for swk program\n- in order to be supported in update checker, your package should have\n a **version.py** file with ``__version__`` string determining package\n version.\n\nDependencies\n''''''''''''\n\n- for main program: `exrex `__\n `pypsi `__ configparser\n- for ssh plugin: `paramiko `__\n `scp `__\n- for swk-casp plugin:\n `requests `__\n- for swk-zabbix plugin:\n `pyzabbix `__\n- for swk-foreman plugin:\n `python-foreman `__\n\nContributions\n~~~~~~~~~~~~~\n\nPlease do! Don't forget to exclude sensitive details from ``swk.ini``,\nif any.\n\n(c) Pavel \"trueneu\" Gurkov, 2016", "description_content_type": null, "docs_url": null, "download_url": "https://github.com/trueneu/swiss-knife/archive/v0.0.4a18.zip", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/trueneu/swiss-knife", "keywords": "cli ssh pssh swiss-knife sysadmin zabbix foreman", "license": "GPLv3", "maintainer": null, "maintainer_email": null, "name": "swk", "package_url": "https://pypi.org/project/swk/", "platform": "Posix; MacOS X", "project_url": "https://pypi.org/project/swk/", "project_urls": { "Download": "https://github.com/trueneu/swiss-knife/archive/v0.0.4a18.zip", "Homepage": "https://github.com/trueneu/swiss-knife" }, "release_url": "https://pypi.org/project/swk/0.0.4a18/", "requires_dist": null, "requires_python": null, "summary": "Extendable command line utility for sysadmins", "version": "0.0.4a18" }, "last_serial": 2398973, "releases": { "0.0.4a10": [ { "comment_text": "", "digests": { "md5": "d53f49baacd141e983668ee44d341b88", "sha256": "ddb1b7c1f4476684364f3382fd2902f43db1c21a6e1705b7e5acb0bbfac6e34c" }, "downloads": -1, "filename": "swk-0.0.4a10.tar.gz", "has_sig": false, "md5_digest": "d53f49baacd141e983668ee44d341b88", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 20531, "upload_time": "2016-02-15T19:16:25", "url": "https://files.pythonhosted.org/packages/a2/1a/c018aa7d6a9100427ba163333ab09d14b82b0206708d0c34fa308ac8daa2/swk-0.0.4a10.tar.gz" } ], "0.0.4a11": [ { "comment_text": "", "digests": { "md5": "ce8637b32c1fe810299d643aca44b7bf", "sha256": "f6b5df5df515197a59b23e17bb698b553703311868d40c3fde2926ac497a3b78" }, "downloads": -1, "filename": "swk-0.0.4a11.tar.gz", "has_sig": false, "md5_digest": "ce8637b32c1fe810299d643aca44b7bf", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 20632, "upload_time": "2016-02-16T21:41:50", "url": "https://files.pythonhosted.org/packages/0d/e6/7a895eacda5339546efa06d6bb49dc76499419ec5ddd7f03e3c57ccd49ce/swk-0.0.4a11.tar.gz" } ], "0.0.4a12": [ { "comment_text": "", "digests": { "md5": "2707b1a4ed33fc3de9bfc3692f6a8e69", "sha256": "56ae07f501994b7753b6c72feffed03e8efe5793ca542dc7110e0e70426e0c75" }, "downloads": -1, "filename": "swk-0.0.4a12.tar.gz", "has_sig": false, "md5_digest": "2707b1a4ed33fc3de9bfc3692f6a8e69", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 28093, "upload_time": "2016-02-17T09:21:03", "url": "https://files.pythonhosted.org/packages/c2/b4/7bf758bab1c458867a5398cfb795acc983f66605211f8a90954422ff9d05/swk-0.0.4a12.tar.gz" } ], "0.0.4a13": [ { "comment_text": "", "digests": { "md5": "480a9406a9ecbc3ebbadc9c6e8683a13", "sha256": "2e219e67941e010b3340ad0615a384ac70aff7a53443369621792359952ae2fe" }, "downloads": -1, "filename": "swk-0.0.4a13.tar.gz", "has_sig": false, "md5_digest": "480a9406a9ecbc3ebbadc9c6e8683a13", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 31843, "upload_time": "2016-02-19T18:54:57", "url": "https://files.pythonhosted.org/packages/4b/78/ddeddb93cd1694ad2d41c4d67a3cdb9cbd005124d23cc34e4d44da83431b/swk-0.0.4a13.tar.gz" } ], "0.0.4a14": [ { "comment_text": "", "digests": { "md5": "83f71ec9c0aa94bc63ebdfbcdadd3bc6", "sha256": "26c417936597513f7f28aaa7dec08ae2d56fd61a28fb3ab63dbb0be3ce3c53cd" }, "downloads": -1, "filename": "swk-0.0.4a14.tar.gz", "has_sig": false, "md5_digest": "83f71ec9c0aa94bc63ebdfbcdadd3bc6", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 31846, "upload_time": "2016-02-19T20:40:50", "url": "https://files.pythonhosted.org/packages/3e/26/3497288d93b8a69132e73be035ce9ca2361a3a06601159e5cc8cb351ab15/swk-0.0.4a14.tar.gz" } ], "0.0.4a15": [ { "comment_text": "", "digests": { "md5": "d91b7bfc38613fe8872ab8ca65dd0632", "sha256": "48c4b3630dd2a66d5d7b2892c08ca6e4b6898ec0c81398f6ada45ed766a23ebc" }, "downloads": -1, "filename": "swk-0.0.4a15.tar.gz", "has_sig": false, "md5_digest": "d91b7bfc38613fe8872ab8ca65dd0632", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 32742, "upload_time": "2016-02-26T19:23:07", "url": "https://files.pythonhosted.org/packages/0b/dc/5240d22dafb3707b4e63133c9fb9efcfaded864b08561f42eaaf40228360/swk-0.0.4a15.tar.gz" } ], "0.0.4a16": [ { "comment_text": "", "digests": { "md5": "6c987159bc60dddd3aae425b1f9b171f", "sha256": "d8e7933fccd48880f3a384c63b1bc93f3325d7c345decdaa3f657881ab029337" }, "downloads": -1, "filename": "swk-0.0.4a16.tar.gz", "has_sig": false, "md5_digest": "6c987159bc60dddd3aae425b1f9b171f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 32737, "upload_time": "2016-02-26T19:28:53", "url": "https://files.pythonhosted.org/packages/ab/73/2028a30a741a08b4c64c33c4c6944483926a6797f35c1762126fdae17dbd/swk-0.0.4a16.tar.gz" } ], "0.0.4a17": [ { "comment_text": "", "digests": { "md5": "9cefcb6613a1e156c482abd65da22423", "sha256": "e7d6af1b4e0814cc2cebcb35c9c365efe90c9d26d47cfccefa779f826e793132" }, "downloads": -1, "filename": "swk-0.0.4a17.tar.gz", "has_sig": false, "md5_digest": "9cefcb6613a1e156c482abd65da22423", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 32730, "upload_time": "2016-02-29T16:39:51", "url": "https://files.pythonhosted.org/packages/65/f5/e8337097b1d96f87ef1f9acb41af4dbc569f22cbaca0da5b89918642b27e/swk-0.0.4a17.tar.gz" } ], "0.0.4a18": [ { "comment_text": "", "digests": { "md5": "26ca5e324da3c6bf0891a85010e6ca0a", "sha256": "b1cea4548c8d01ffec448604ff41743cfd6978e7b87d19cdb5ca4f33c9f03d21" }, "downloads": -1, "filename": "swk-0.0.4a18.tar.gz", "has_sig": false, "md5_digest": "26ca5e324da3c6bf0891a85010e6ca0a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 32753, "upload_time": "2016-03-03T20:36:37", "url": "https://files.pythonhosted.org/packages/a5/87/f1908a0a4b75b739f210a4116d05cbbda7b249cabc99ca3bfe9f45e93b6b/swk-0.0.4a18.tar.gz" } ], "0.0.4a9": [ { "comment_text": "", "digests": { "md5": "286eeb19b10176b378659b36c81c0009", "sha256": "2bcacd014cc998099aa4095075eb89d224861b533cba02e0dcacfb4ae26385b8" }, "downloads": -1, "filename": "swk-0.0.4a9.tar.gz", "has_sig": false, "md5_digest": "286eeb19b10176b378659b36c81c0009", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 20364, "upload_time": "2016-02-13T23:13:49", "url": "https://files.pythonhosted.org/packages/60/fd/5148688f2cf30dabc904a9644a7e0935907309b11bc9cf3ea500d6ef5ff7/swk-0.0.4a9.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "26ca5e324da3c6bf0891a85010e6ca0a", "sha256": "b1cea4548c8d01ffec448604ff41743cfd6978e7b87d19cdb5ca4f33c9f03d21" }, "downloads": -1, "filename": "swk-0.0.4a18.tar.gz", "has_sig": false, "md5_digest": "26ca5e324da3c6bf0891a85010e6ca0a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 32753, "upload_time": "2016-03-03T20:36:37", "url": "https://files.pythonhosted.org/packages/a5/87/f1908a0a4b75b739f210a4116d05cbbda7b249cabc99ca3bfe9f45e93b6b/swk-0.0.4a18.tar.gz" } ] }