{
"info": {
"author": "Jay Luker",
"author_email": "lbjay@reallywow.com",
"bugtrack_url": null,
"classifiers": [
"Development Status :: 3 - Alpha",
"Intended Audience :: Developers",
"License :: OSI Approved :: Apache Software License",
"Natural Language :: English",
"Programming Language :: Python",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3.6"
],
"description": ".. image:: https://travis-ci.org/harvard-dce/pyhorn.svg?branch=master\n :target: https://travis-ci.org/harvard-dce/pyhorn\n\n======\npyhorn\n======\n\npyhorn is a python client for accessing the RESTful API of the\n`Opencast Matterhorn `_\nvideo capture system. It provides a client interface, **MHClient**, that exposes methods\nfor accessing both raw and 'objectified' response data from the various Matterhorn\nREST API endpoints.\n\nThis software should be considered Alpha, therefore likely to change/break in the\nnear future.\n\nInstall\n-------\n.. code-block:: bash\n\n pip install pyhorn\n\nOverview\n--------\nData available from the REST endpoints is accessible through methods of the MHClient\nobject. In many cases the response data is encapsulated in additional classes to make\naccessing various attributes of the data possible using object notation. For instance,\ndata about Matterhorn workflows can be accessed using the ``client.workflows()``\nmethod. The return value will be a list of ``endpoints.workflow.Workflow`` objects.\nThe ``operations`` attribute of those objects will get you a list of\n``endpoints.workflow.WorkflowOperation`` objects. And so forth.\n\nCurrently there are only a handfull of endpoints wrapped in this way, and only a\nfew convenience classes and methods defined for each one. The idea is to continue\nadding more as I (or you) need them. Pull requests welcome!\n\nMHClient Method List\n--------------------\nIn the case of methods that accept a set of keyword arguments, the list of expected\nkwargs is mapped directly from the Matterhorn endpoint. In other words, if you\nwant to know what kwargs to use for ``MHClient.workflows()``, check the corresponding\nentry in the REST API docs at http://matterhorn.example.edu/docs.html?path=/workflow.\n\n* ``endpoints()`` - /info/components.json\n* ``me()`` - /info/me.json\n* ``workflows(**kwargs)`` - /workflow/instances.json\n* ``workflow(instance_id)`` - /workflow/instance/{id}.json\n* ``episodes(**kwargs)`` - /episode/episode.json\n* ``episode(episode_id)`` - /episode/episode.json\n* ``user_actions(**kwargs)`` - /usertracking/actions.json\n* ``agents()`` - /capture-admin/agents.json\n* ``agent(agent_name)`` - /capture-admin/agents/{agent_name}.json\n* ``hosts()`` - /services/hosts.json\n* ``job(job_id)`` - /services/job/{job_id}.json\n* ``search_episodes(**kwargs)`` - /search/episode.json\n* ``search_episode(episode_id)`` - /search/episode.json\n* ``statistics()`` - /services/statistics.json\n\nExample Usage\n-------------\nCreate the client interface...\n\n.. code-block:: python\n\n >>> from pyhorn import MHClient\n >>> client = MHClient('http://matterhorn.example.edu', 'user', 'passwd')\n\n\nUser/pass combo should be for your REST API user, typically the\n\"matterhorn_system_account\" user. It is possible to create and use a client\nobject without a user/pass combo (omit the constructor args), but requests\nwill only work for endpoints that do not require auth (e.g., episode search)\n\nThe default request timeout is 5 seconds. Pass `timeout=n` to the MHClient\nconstructor to use something else.\n\nGet a list of available endpoints...\n\n.. code-block:: python\n\n >>> client.endpoints()\n [{u'description': u'Capture Agent Admin REST Endpoint',\n u'docs': u'http://matterhorn.example.edu80/capture-admin/docs',\n u'path': u'/capture-admin',\n u'type': u'org.opencastproject.capture.admin',\n u'version': u'1.4.4',\n u'wadl': u'http://matterhorn.example.edu80/capture-admin/?_wadl&_type=xml'},\n {u'description': u'EpisodeService REST Endpoint',\n u'docs': u'http://matterhorn.example.edu80/episode/docs',\n u'path': u'/episode',\n u'type': u'org.opencastproject.episode',\n u'version': u'1.4.4',\n u'wadl': u'http://matterhorn.example.edu80/episode/?_wadl&_type=xml'},\n ...\n\nGet list of current workflow instances...\n\n.. code-block:: python\n\n >>> wfs = client.workflows()\n >>> for wf in wfs:\n print wf.id + \": \" + wf.state\n 1646: STOPPED\n 1649: STOPPED\n 1651: STOPPED\n 1655: STOPPED\n 4211: SUCCEEDED\n 14479: SUCCEEDED\n 14486: SUCCEEDED\n 441: STOPPED\n 445: STOPPED\n ...\n\n... or just the successful ones...\n\n.. code-block:: python\n\n >>> wfs = client.workflows(state=\"SUCCEEDED\")\n\n... or the operations for a particular instance...\n\n.. code-block:: python\n\n >>> wf = client.workflow(instance_id=1646)\n >>> ops = wf.operations\n >>> for op in ops:\n print op.id + \": \" + op.state\n apply-acl: SUCCEEDED\n tag: SUCCEEDED\n tag: SUCCEEDED\n inspect: SUCCEEDED\n prepare-av: SUCCEEDED\n prepare-av: SUCCEEDED\n compose: SUCCEEDED\n compose: SUCCEEDED\n ...\n\nGet the list of currently configured capture agents\n\n.. code-block:: python\n\n >>> cas = client.agents()\n >>> for ca in cas:\n print ca.name + \": \" + ca.state\n epiphan001: unknown\n epiphan002: unknown\n ewave001: idle\n ewave002: idle\n ncast001: idle\n ncast002: shutting_down\n\nEndpoint Object Wrappers\n------------------------\n\npyhorn attempts to make the Matterhorn API responses more convenient to work with\nby wrapping the json response data in a set of classes that provide easy access\nvia object attributes and automatic \"dereferencing\" of associated data.\n\nThe following endpoint data classes are defined:\n\n* Workflow\n* WorkflowOperation\n* ServiceJob\n* Episode\n* Mediapackage\n* MediaTrack\n* CaptureAgent\n* UserAction\n* Search\n\nThese are just the initial set because they represent the data I needed to deal\nwith in the other projects that prompted the creation of pyhorn. It is trivial\nto add additional wrapper classes. Pull requests welcome!\n\n**Attribute access**\n\nEndpoint data classes inherit from ``pyhorn.endpoints.base.EndpointObj``. The\njson response data is stored in a ``_raw`` attribute and made accessible via\ndot-notation by overriding ``__getattr__``. A simple illustration:\n\n.. code-block:: python\n\n >>> from pyhorn.endpoints.base import EndpointObj\n >>> obj = EndpointObj({\"foo\": \"bar\", \"baz\": [1,2,3]}, client)\n >>> obj.foo\n bar\n >>> obj.baz\n [1, 2, 3]\n >>> obj.abc\n Traceback ...\n ...\n AttributeError: response data for has no key 'abc'\n\nAt this point the dot-notation access only works for top-level values. There is a ``EndpointObj.raw_get`` method\nthat accepts a ``path_key`` argument if you need to access something deeper in the response\nstructure.\n\n.. code-block:: python\n\n >>> obj = EndpointObj({\"foo\": {\"bar\": {\"baz\": 1}}})\n >>> obj.raw_get(\"foo.bar.baz\")\n 1\n\n**Dereferencing**\n\nIn a handful of cases accessing certain attributes (``@property``, actually)\nof an endpoint data wrapper object\nwill return an instance or instances of a different wrapper class. For example,\n``Workflow.operations`` will extract the operation data from the raw json and\nreturn a list of ``WorkflowOperation`` objects that wrap the individual operation\ndata structures contained in the original response.\n\nThis works also for dereferencing data that requires an additional request to the\nMatterhorn API. For instance, Accessing the ``WorkflowOperation.job`` property\ntriggers a request to the ``/services/job/{job_id}.json``, with the response\nbeing wrapped in a ``ServiceJob`` object and returned.\n\nThe current list of these dereferencing relationships is:\n\n* ``Workflow.operations`` -> list of ``WorkflowOperation`` objects\n* ``Workflow.job`` -> ``ServiceJob``\n* ``Workflow.episode`` -> ``Episode``\n* ``Workflow.mediapackage`` -> ``Mediapackage``\n* ``WorkflowOperation.job`` -> ``ServiceJob``\n* ``ServiceJob.parent`` -> ``ServiceJob``\n* ``ServiceJob.children`` -> list of ``ServiceJob`` objects\n* ``Episode.mediapackage`` -> ``Mediapackage``\n* ``Mediapackage.tracks`` -> list of ``MediaTrack`` objects\n* ``UserAction.episode`` -> ``SearchEpisode``\n\n**Setting Maintenance Mode**\n\nAs of v0.4.0 you can toggle the maintenance mode on a host.\n\n.. code-block:: python\n\n >>> hosts = client.hosts()\n >>> for host in hosts:\n host.set_maintenance(True)\n\n\n**Caching**\n\nAs of v0.7.0 the use of requests_cache has been dropped in favor of an internal\ncache that stores the responses from a subset of the single-item endpoint\nmethods. A future goal is to allow more granular control over the caching policy,\nbut for now the following endpoint responses are cached:\n\n* CaptureEndpoint.agent\n* EpisodeEndpoint.episode\n* SearchEndpoint.episode\n* Workflow.instance\n\nCaching works via a decorator function on the endpoint methods. The JSON response\ndata from the Matterhorn API is cached in-memory with each entry assigned a\ntime-to-live (`ttl`) value to control expiration. Each cached method also has\na configured `max_entries` value. If/when the number of entries reaches that\nlimit a cull operation will prune 1/3 of the existing entries.\n\nTo disable caching altogether pass `cache_enabled=False` to the `MHClient`\nconstructor.\n\nTo clear the cache call `client.clear_cache()`.\n\nTesting\n-------\n\nDuring development pyhorn tests are executed using `pytest `_.\n\nTo run the tests from a local git clone:\n\n.. code-block:: bash\n\n pip install -r tests/requirements.txt\n\nthen\n\n.. code-block:: bash\n\n python setup.py test\n\nLicense\n-------\npyhorn is licensed under the Apache 2.0 license\n\nCopyright\n---------\n2015 President and Fellows of Harvard College\n\n\n\n.. :changelog:\n\nRelease History\n---------------\n\n0.1.0 (2014-10-23)\n++++++++++++++++++\n\n* Birth!\n\n0.1.1 (2014-10-28)\n++++++++++++++++++\n\n* copyright tweak\n\n0.1.2 (2014-10-28)\n++++++++++++++++++\n\n* blerg. forgot to update history with last version bump.\n\n0.2.0 (2014-11-12)\n++++++++++++++++++\n\n* expanded endpoint methods and wrapper objects\n* better endpoint class test coverage and fixture/mocking approach\n\n0.3.0 (2015-05-07)\n++++++++++++++++++\n\nUserAction.episode now fetches from SearchEndpoint\n\n* new SearchEndpoint for fetching episode data\n* new client methods: search_episodes(), search_episode()\n\n0.3.1 (2015-08-04)\n++++++++++++++++++\n\nbug fix in client http exception handling\n\n0.4.1 (2015-08-27)\n++++++++++++++++++\n\nAdditional services endpoint methods\n\n* basic service listing and statistics\n* methods for getting count of queued/running jobs\n* maintenance on/off\n\nAdded request timeouts\n\nUnhandled http exceptions are now re-raised\n\n0.5.0 (2015-10-30)\n++++++++++++++++++\n\n* added is_live() method to UserAction\n* workflow is now a property Mediapackage objects\n\n0.6.0 (2016-04-14)\n++++++++++++++++++\n\n* add new `includeDeleted` param for episode search\n\n0.7.0 (2016-04-14)\n++++++++++++++++++\n\n* ripped out the braindead use of requests_cache\n* new per-endpoint method caching mechanism\n\n0.8.0 (2016-07-29)\n++++++++++++++++++\n\n* allow client creation and usage without user/pass auth\n (note: requests will fail for endpoints that require auth)\n\n0.8.1 (2016-09-20)\n++++++++++++++++++\n\n* SearchEpisode endpoint was missing `sort` param\n\n0.9.0 (2018-08-29)\n++++++++++++++++++\n\n* Python 3 compatibility!\n\n\n",
"description_content_type": "",
"docs_url": null,
"download_url": "",
"downloads": {
"last_day": -1,
"last_month": -1,
"last_week": -1
},
"home_page": "https://bitbucket.org/lbjay/pyhorn",
"keywords": "",
"license": "Apache 2.0",
"maintainer": "",
"maintainer_email": "",
"name": "pyhorn",
"package_url": "https://pypi.org/project/pyhorn/",
"platform": "",
"project_url": "https://pypi.org/project/pyhorn/",
"project_urls": {
"Homepage": "https://bitbucket.org/lbjay/pyhorn"
},
"release_url": "https://pypi.org/project/pyhorn/0.9.0/",
"requires_dist": [
"requests",
"requests-cache",
"arrow",
"rwlock",
"six"
],
"requires_python": "",
"summary": "Python wrapper for the Matterhorn RESTful APIs",
"version": "0.9.0"
},
"last_serial": 4265733,
"releases": {
"0.1.0": [
{
"comment_text": "",
"digests": {
"md5": "9aeb8d9f52f24238f53dced57250c325",
"sha256": "0ae888ef98bb6efccc376d3f330c8115dfb9ce31a4fb1f718645a390b8dd4580"
},
"downloads": -1,
"filename": "pyhorn-0.1.0-py2-none-any.whl",
"has_sig": false,
"md5_digest": "9aeb8d9f52f24238f53dced57250c325",
"packagetype": "bdist_wheel",
"python_version": "py2",
"requires_python": null,
"size": 11136,
"upload_time": "2014-10-28T14:34:16",
"url": "https://files.pythonhosted.org/packages/dd/d5/d565f175e13c4c62ff7fd743c57c16fb38bd9dcd8fa33e75ba47066fbb19/pyhorn-0.1.0-py2-none-any.whl"
}
],
"0.1.1": [
{
"comment_text": "",
"digests": {
"md5": "52d0bf626ea564f90013aa9c2c006d42",
"sha256": "09f34aa444f90d8f2ac197ba746fd54a24313eae89d8a1d9f8cb167175856616"
},
"downloads": -1,
"filename": "pyhorn-0.1.1-py2-none-any.whl",
"has_sig": false,
"md5_digest": "52d0bf626ea564f90013aa9c2c006d42",
"packagetype": "bdist_wheel",
"python_version": "py2",
"requires_python": null,
"size": 11284,
"upload_time": "2014-10-28T15:22:20",
"url": "https://files.pythonhosted.org/packages/d8/31/8c25bd330e5532e66bd4bdfc98ce07ce5fddd758a024daba3e71653461d5/pyhorn-0.1.1-py2-none-any.whl"
}
],
"0.1.2": [
{
"comment_text": "",
"digests": {
"md5": "676a49cf8c0a120f302f849f45fa697a",
"sha256": "9055787f3170e8cc09e389a350b5b7c25a79ae913bd9e023c9efed4deb772944"
},
"downloads": -1,
"filename": "pyhorn-0.1.2-py2-none-any.whl",
"has_sig": false,
"md5_digest": "676a49cf8c0a120f302f849f45fa697a",
"packagetype": "bdist_wheel",
"python_version": "py2",
"requires_python": null,
"size": 11386,
"upload_time": "2014-10-28T15:31:13",
"url": "https://files.pythonhosted.org/packages/50/a1/dd8ec1f544452e876eecfac915faec852e7465ab9224128b5f2dda8ba009/pyhorn-0.1.2-py2-none-any.whl"
}
],
"0.2.0": [
{
"comment_text": "",
"digests": {
"md5": "87b79f09b8dd218373c0e481f5aae835",
"sha256": "91e0700cabb40621c989ba812ae99687240b4ee0e66e0e2e6348c465ee82821f"
},
"downloads": -1,
"filename": "pyhorn-0.2.0-py2-none-any.whl",
"has_sig": false,
"md5_digest": "87b79f09b8dd218373c0e481f5aae835",
"packagetype": "bdist_wheel",
"python_version": "py2",
"requires_python": null,
"size": 15973,
"upload_time": "2014-11-13T20:22:03",
"url": "https://files.pythonhosted.org/packages/d0/85/907aee25d1ca7c54858d2a90fdc47c04d30829dc25c1d2f7f914889e2aab/pyhorn-0.2.0-py2-none-any.whl"
}
],
"0.2.1": [
{
"comment_text": "",
"digests": {
"md5": "88ad954696a2c8118c2435adacfed002",
"sha256": "e1c8c62c20c7e149cccd9a25100304117c8c881a06680e9622f3e736c16d29b4"
},
"downloads": -1,
"filename": "pyhorn-0.2.1-py2-none-any.whl",
"has_sig": false,
"md5_digest": "88ad954696a2c8118c2435adacfed002",
"packagetype": "bdist_wheel",
"python_version": "py2",
"requires_python": null,
"size": 16009,
"upload_time": "2014-11-14T13:46:46",
"url": "https://files.pythonhosted.org/packages/0f/0e/f1fa0e90ef6afbcab70349860ffecdb1eb2943cd4e74836031c128da992d/pyhorn-0.2.1-py2-none-any.whl"
}
],
"0.3.0": [
{
"comment_text": "",
"digests": {
"md5": "864af8c8f950fa32f7d34ae2cbc6737f",
"sha256": "3667a0b5ef90fc5fc5cf6767046b24a7ab1c63e10105cb3b1e976dbf954573de"
},
"downloads": -1,
"filename": "pyhorn-0.3.0-py2-none-any.whl",
"has_sig": false,
"md5_digest": "864af8c8f950fa32f7d34ae2cbc6737f",
"packagetype": "bdist_wheel",
"python_version": "py2",
"requires_python": null,
"size": 16869,
"upload_time": "2015-05-08T13:46:12",
"url": "https://files.pythonhosted.org/packages/92/b7/c25f0c3c9a6d65986f64c361af81cdcb46a67e1d1ffb049e6c754444f9ab/pyhorn-0.3.0-py2-none-any.whl"
}
],
"0.3.1": [
{
"comment_text": "",
"digests": {
"md5": "30d378a268449c3959c4b4f2c63ebe8a",
"sha256": "a88fff8ed242a15d404c8804bef3c0d908da7ed894f7c7342d4fc83711c011e6"
},
"downloads": -1,
"filename": "pyhorn-0.3.1-py2-none-any.whl",
"has_sig": false,
"md5_digest": "30d378a268449c3959c4b4f2c63ebe8a",
"packagetype": "bdist_wheel",
"python_version": "py2",
"requires_python": null,
"size": 16984,
"upload_time": "2015-08-04T14:52:08",
"url": "https://files.pythonhosted.org/packages/7c/3b/2fb485aabef7e58f38933eebb79190a9dc6e965b88552049f1fe4255cf42/pyhorn-0.3.1-py2-none-any.whl"
}
],
"0.4.0": [],
"0.4.1": [
{
"comment_text": "",
"digests": {
"md5": "e9d39996786c9e7339f993aeb0459139",
"sha256": "5f46d8874299265f77c85ed4459d0460f9df81207b9ed3331f376878cdeccf9d"
},
"downloads": -1,
"filename": "pyhorn-0.4.1-py2-none-any.whl",
"has_sig": false,
"md5_digest": "e9d39996786c9e7339f993aeb0459139",
"packagetype": "bdist_wheel",
"python_version": "py2",
"requires_python": null,
"size": 18404,
"upload_time": "2015-08-27T15:36:52",
"url": "https://files.pythonhosted.org/packages/03/48/f9e18768e73217dcb184d2affec5a31297cc6411401db727f6d084b7129d/pyhorn-0.4.1-py2-none-any.whl"
}
],
"0.5.0": [
{
"comment_text": "",
"digests": {
"md5": "1ca807a19892e7dca02b617cca7b1c5f",
"sha256": "747f9935b6530d6b80142b3f67e64b3f44bfbcfc31476eb558e9aacae6f87f38"
},
"downloads": -1,
"filename": "pyhorn-0.5.0-py2-none-any.whl",
"has_sig": false,
"md5_digest": "1ca807a19892e7dca02b617cca7b1c5f",
"packagetype": "bdist_wheel",
"python_version": "py2",
"requires_python": null,
"size": 18763,
"upload_time": "2015-10-30T19:08:55",
"url": "https://files.pythonhosted.org/packages/ae/5b/722c7f8c6312492b7f9e7cb1abce0556b7706f0df6a41bc4cfbd223c1ce8/pyhorn-0.5.0-py2-none-any.whl"
}
],
"0.6.0": [
{
"comment_text": "",
"digests": {
"md5": "1aac0956305be0e37a5b096914d29627",
"sha256": "4822ea2d332d2ad31b98190a82fdccbff102cd2fbee929528e671a565966d8f1"
},
"downloads": -1,
"filename": "pyhorn-0.6.0-py2-none-any.whl",
"has_sig": false,
"md5_digest": "1aac0956305be0e37a5b096914d29627",
"packagetype": "bdist_wheel",
"python_version": "2.7",
"requires_python": null,
"size": 18871,
"upload_time": "2016-04-14T18:02:10",
"url": "https://files.pythonhosted.org/packages/2e/8f/6f454a72effa61df0ec3153f2dac8b861e7e19e13d834293b3d006b087a5/pyhorn-0.6.0-py2-none-any.whl"
}
],
"0.7.0": [
{
"comment_text": "",
"digests": {
"md5": "8d11805ab68867f599ad2b9b396cb386",
"sha256": "54dc05a67d3c71baae1c0c528930a30b72462c73f802440f434ddf5d9cf625e1"
},
"downloads": -1,
"filename": "pyhorn-0.7.0-py2-none-any.whl",
"has_sig": false,
"md5_digest": "8d11805ab68867f599ad2b9b396cb386",
"packagetype": "bdist_wheel",
"python_version": "2.7",
"requires_python": null,
"size": 20846,
"upload_time": "2016-05-26T16:42:45",
"url": "https://files.pythonhosted.org/packages/b7/91/8780b9fd127a0bffdf491dbc5ad9352e5a7a0039f057719a6b45f5d41437/pyhorn-0.7.0-py2-none-any.whl"
}
],
"0.8.0": [
{
"comment_text": "",
"digests": {
"md5": "c956e7fe2a694ebb11a06f7896f98455",
"sha256": "805025c51d20f5888c11276c28dc3488d6951d02a9d848a01f157611ae3b4db8"
},
"downloads": -1,
"filename": "pyhorn-0.8.0-py2-none-any.whl",
"has_sig": false,
"md5_digest": "c956e7fe2a694ebb11a06f7896f98455",
"packagetype": "bdist_wheel",
"python_version": "2.7",
"requires_python": null,
"size": 21244,
"upload_time": "2016-07-29T19:15:26",
"url": "https://files.pythonhosted.org/packages/0a/8a/1152b7a4333d2f4cebf2cb276ce189c2e23a9ba1f9fc2b3ca1f0ed18496b/pyhorn-0.8.0-py2-none-any.whl"
}
],
"0.8.1": [
{
"comment_text": "",
"digests": {
"md5": "a8e9dc86ad7d06c715d3930b0bc09d40",
"sha256": "343a8d867b34d29c631354dbae50490905fa1cf6f1fd379646116fb597e22cf4"
},
"downloads": -1,
"filename": "pyhorn-0.8.1-py2-none-any.whl",
"has_sig": false,
"md5_digest": "a8e9dc86ad7d06c715d3930b0bc09d40",
"packagetype": "bdist_wheel",
"python_version": "2.7",
"requires_python": null,
"size": 21306,
"upload_time": "2016-09-20T20:25:05",
"url": "https://files.pythonhosted.org/packages/f1/fa/8860d5217b6b8e61b09de00ec0804fa1cb0cd47b9b4569371a4f07cef4c2/pyhorn-0.8.1-py2-none-any.whl"
}
],
"0.9.0": [
{
"comment_text": "",
"digests": {
"md5": "5a9d4272da26de13f4c3cdcf8f805adb",
"sha256": "be9ca420a92d588742387d6d964aded96768c06f026de34f18994746c5e2514f"
},
"downloads": -1,
"filename": "pyhorn-0.9.0-py2-none-any.whl",
"has_sig": false,
"md5_digest": "5a9d4272da26de13f4c3cdcf8f805adb",
"packagetype": "bdist_wheel",
"python_version": "py2",
"requires_python": null,
"size": 21325,
"upload_time": "2018-08-29T18:14:32",
"url": "https://files.pythonhosted.org/packages/37/c1/25e54703731265a64c7bd8368677fa15cb84a1d0407ed64d93288b62fc9c/pyhorn-0.9.0-py2-none-any.whl"
},
{
"comment_text": "",
"digests": {
"md5": "28be3d868889f9b7b3cc1cafa015bb8c",
"sha256": "2a25042d533e31f16d24edb3ea5f2c3e3654bd634e3decd9776c3053c4476bb2"
},
"downloads": -1,
"filename": "pyhorn-0.9.0-py2.py3-none-any.whl",
"has_sig": false,
"md5_digest": "28be3d868889f9b7b3cc1cafa015bb8c",
"packagetype": "bdist_wheel",
"python_version": "py2.py3",
"requires_python": null,
"size": 16383,
"upload_time": "2018-09-12T17:19:15",
"url": "https://files.pythonhosted.org/packages/99/5b/07b37089a885ce76a879f032921fa18166f96804badc14f5d041d53e6d8b/pyhorn-0.9.0-py2.py3-none-any.whl"
}
]
},
"urls": [
{
"comment_text": "",
"digests": {
"md5": "5a9d4272da26de13f4c3cdcf8f805adb",
"sha256": "be9ca420a92d588742387d6d964aded96768c06f026de34f18994746c5e2514f"
},
"downloads": -1,
"filename": "pyhorn-0.9.0-py2-none-any.whl",
"has_sig": false,
"md5_digest": "5a9d4272da26de13f4c3cdcf8f805adb",
"packagetype": "bdist_wheel",
"python_version": "py2",
"requires_python": null,
"size": 21325,
"upload_time": "2018-08-29T18:14:32",
"url": "https://files.pythonhosted.org/packages/37/c1/25e54703731265a64c7bd8368677fa15cb84a1d0407ed64d93288b62fc9c/pyhorn-0.9.0-py2-none-any.whl"
},
{
"comment_text": "",
"digests": {
"md5": "28be3d868889f9b7b3cc1cafa015bb8c",
"sha256": "2a25042d533e31f16d24edb3ea5f2c3e3654bd634e3decd9776c3053c4476bb2"
},
"downloads": -1,
"filename": "pyhorn-0.9.0-py2.py3-none-any.whl",
"has_sig": false,
"md5_digest": "28be3d868889f9b7b3cc1cafa015bb8c",
"packagetype": "bdist_wheel",
"python_version": "py2.py3",
"requires_python": null,
"size": 16383,
"upload_time": "2018-09-12T17:19:15",
"url": "https://files.pythonhosted.org/packages/99/5b/07b37089a885ce76a879f032921fa18166f96804badc14f5d041d53e6d8b/pyhorn-0.9.0-py2.py3-none-any.whl"
}
]
}