{ "info": { "author": "Alexey Bogdanenko", "author_email": "alexey@bogdanenko.com", "bugtrack_url": null, "classifiers": [ "License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)", "Operating System :: POSIX :: Linux", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3 :: Only" ], "description": "####\nAlpy\n####\n\n*Test network virtual appliance using Docker containers*\n\n.. contents::\n :backlinks: none\n\nGeneral information\n===================\n\nDescription\n-----------\n\nThis project is a Python library for testing network virtual appliances.\n\nAuthor\n------\n\nAlexey Bogdanenko\n\nLicense\n-------\n\nAlpy is licensed under ``SPDX-License-Identifier: GPL-3.0-or-later``. See\n``COPYING`` for more details.\n\nFeatures\n========\n\nThe simplest docker to QEMU networking connection\n-------------------------------------------------\n\nNothing in the middle. No bridges, no veth pairs, no NAT etc.\n\nEach layer 2 frame emitted is delivered unmodified, reliably.\n\nReliable packet capture\n-----------------------\n\nEach frame is captured reliably thanks to the QEMU *filter-dump* feature.\n\nFirst-class Docker container support\n------------------------------------\n\nAlpy follows and encourages single process per container design.\n\nLogging\n-------\n\nTest logs are easy to configure and customize. Alpy consistently uses Python\n*logging* module.\n\nAlpy collects serial console log in binary as well as text (escaped) form.\n\nNo trash left behind\n--------------------\n\nAlpy cleans up after itself:\n\n- processes stopped with error codes and logs collected,\n- files, directories unmounted,\n- temporary files removed,\n- sockets closed,\n- interfaces removed...\n\n... reliably.\n\nNo root required\n----------------\n\nRun as a regular user.\n\nDocumentation\n=============\n\nGeneral\n-------\n\nAlpy manages containers via Docker Python API.\n\nAlpy interacts with QEMU using Python API of the QEMU Monitor Protocol (QMP).\nQMP is a JSON-based protocol that allows applications to communicate with a QEMU\ninstance. For information about QMP, see `qmp package page on PyPI`__.\n\n__ https://pypi.org/project/qmp/\n\nAlpy gives user Pexpect object to interact with a serial console. The Pexpect\nobject is configured to log console input and output via the standard *logging*\nmodule.\n\nAPI documentation\n-----------------\n\nThe documentation is published on GitLab Pages of your GitLab project (if GitLab\nPages is enabled on your GitLab instance). For example, upstream project\ndocumentation lives at https://abogdanenko.gitlab.io/alpy.\n\nAlpy API documentation is generated using Sphinx__. To generate HTML API\ndocumentation locally, install `Sphinx package`__ and run the following\ncommand::\n\n PYTHONPATH=. sphinx-build docs public\n\nTo view the generated documentation, open ``public/index.html`` in a browser.\n\n__ https://www.sphinx-doc.org/\n__ https://pypi.org/project/Sphinx/\n\nFAQ\n---\n\nHow do I watch serial console?\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nUse *tail*::\n\n tail --follow name --retry console.log\n\nThe same command, but shorter::\n\n tail -F console.log\n\nHow do I watch traffic on an interface?\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nUse tcpdump::\n\n tail --bytes +0 --follow name --retry link0.pcap | tcpdump -n -r -\n\nThe same command, but shorter::\n\n tail -Fc +0 link0.pcap | tcpdump -nr-\n\nCan I use Wireshark to watch traffic on an interface?\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nYes, you can::\n\n tail --bytes +0 --follow name --retry link0.pcap | wireshark -k -i -\n\nThe same command, but shorter::\n\n tail -Fc +0 link0.pcap | wireshark -ki-\n\nHow do I debug my program?\n^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nUse `The Python Debugger `_.\n\nHow do I enter node network namespace?\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n#. Get node pid::\n\n docker inspect --format '{{.State.Pid}}' node0\n\n#. Jump into node namespace using that pid::\n\n nsenter --net --target \"$pid\"\n\nOne-liner::\n\n nsenter --net --target \"$(docker inspect --format '{{.State.Pid}}' node0)\"\n\nNetwork design\n--------------\n\nThe appliance being tested is referred to as a *device under test* or *DUT*.\n\nThe DUT communicates with containers attached to each of its network links.\n\nGuest network adapters are connected to the host via tap devices (Figure 1)::\n\n +-----QEMU hypervisor------+\n | | +-------------+\n | +-----Guest OS-----+ | | |\n | | | | | docker |\n | | +--------------+ | | | container |\n | | | | | | | network |\n | | | NIC driver | | | | namespace |\n | | | | | | | |\n | +------------------+ | | +-----+ |\n | | | | | | | |\n | | NIC hardware +---+-----------+ tap | |\n | | | | | | | | |\n | +--------------+ | | | +-----+ |\n | | | | |\n +--------------------------+ +-------------+\n |\n |\n v\n +-----------+\n | |\n | pcap file |\n | |\n +-----------+\n\n*Figure 1. Network link between QEMU guest and a docker container.*\n\nEach tap device lives in its network namespace. This namespace belongs to a\ndedicated container - a *node*. The node's purpose is to keep the namespace\nalive during the lifetime of a test.\n\nFor an application to be able to communicate with the DUT the application is\ncontainerized. The application container must be created in a special way: it\nmust share network namespace with one of the nodes.\n\nFigure 2 shows an example where application containers *app0* and *app1* share\nnetwork namespace with node container *node0*. Application container *app2*\nshares another network namespace with *node2*.\n\nThis sharing is supported by Docker. All we have to do is to create the\napplication container with the ``--network=container:NODE_NAME`` Docker option.\nFor example, if we want to send traffic to the DUT via its first link, we create\na traffic generator container with Docker option ``--network=container:node0``.\n\n::\n\n +----QEMU---+ +------shared network namespace-----+\n | | | |\n | | | eth0 |\n | +---+ | | +---+ +-----+ +----+ +----+ |\n | |NIC+-----------+tap| |node0| |app0| |app1| |\n | +---+ | | +---+ +-----+ +----+ +----+ |\n | | | |\n | | +-----------------------------------+\n | |\n | |\n | |\n | | +------shared network namespace-----+\n | | | |\n | | | eth0 |\n | +---+ | | +---+ +-----+ |\n | |NIC+-----------+tap| |node1| |\n | +---+ | | +---+ +-----+ |\n | | | |\n | | +-----------------------------------+\n | |\n | |\n | |\n | | +------shared network namespace-----+\n | | | |\n | | | eth0 |\n | +---+ | | +---+ +-----+ +----+ |\n | |NIC+-----------+tap| |node2| |app2| |\n | +---+ | | +---+ +-----+ +----+ |\n | | | |\n +-----------+ +-----------------------------------+\n\n*Figure 2. Application containers attached to the DUT links.*\n\nRabbit\n------\n\nThe alpy library repository includes scripts and modules to build a simple\nappliance called Rabbit. Rabbit is Alpine Linux with a few packages\npre-installed. Having this simple DUT allows to demonstrate the library\nfeatures.\n\nThe tests for the Rabbit device share a lot of code so the code is organized as\na library. The library is called *carrot*.\n\nTesting the alpy library\n========================\n\nA note about GitLab Container Registry\n--------------------------------------\n\nMany CI jobs use one of the custom images built on the \"build-docker-images\"\nstage. The images are stored in the GitLab Container Registry.\n\nThe images are pulled from locations specified by GitLab variables. By default,\nthe variables point to the registry of the current GitLab project.\n\nIf you forked this project and GitLab Container Registry is disabled in your\nproject, override the variables on a project level so that the images are pulled\nfrom some other registry.\n\nFor example, set ``IMAGE_ALPINE=registry.gitlab.com/abogdanenko/alpy/alpine``.\n\nRelated projects\n================\n\n- `Containernet `_\n- `Kathar\u00e1 `_\n- `Netkit `_\n- `GNS3 `_\n- `Eve-NG `_\n\n\n", "description_content_type": "text/x-rst", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://gitlab.com/abogdanenko/alpy", "keywords": "", "license": "", "maintainer": "", "maintainer_email": "", "name": "alpy", "package_url": "https://pypi.org/project/alpy/", "platform": "", "project_url": "https://pypi.org/project/alpy/", "project_urls": { "Homepage": "https://gitlab.com/abogdanenko/alpy" }, "release_url": "https://pypi.org/project/alpy/0.23.0/", "requires_dist": [ "docker", "pexpect", "qmp" ], "requires_python": "", "summary": "Library for testing network virtual appliances using Docker", "version": "0.23.0" }, "last_serial": 6002576, "releases": { "0.10.0": [ { "comment_text": "", "digests": { "md5": "e390a6cc971d6db1c7e954fe99446464", "sha256": "bca61fa2fa41a0615a47290fe017aadf55e6c8cd77e3310e664447881611bfc3" }, "downloads": -1, "filename": "alpy-0.10.0-py3-none-any.whl", "has_sig": false, "md5_digest": "e390a6cc971d6db1c7e954fe99446464", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 20802, "upload_time": "2019-04-07T18:47:04", "url": "https://files.pythonhosted.org/packages/a3/46/48afb02e95ae4605fb4dfeab3b08fc4d5b9069d2dfb415c4d577e8b19733/alpy-0.10.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "d1f9f0dd2db77eab5e2155bce2821553", "sha256": "077cb938d550f9d0a396048bc7c907398733f5c4b4c25cbe98cc8fcdfc3a28f6" }, "downloads": -1, "filename": "alpy-0.10.0.tar.gz", "has_sig": false, "md5_digest": "d1f9f0dd2db77eab5e2155bce2821553", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6384, "upload_time": "2019-04-07T18:47:06", "url": "https://files.pythonhosted.org/packages/9a/a3/4db400c9f750415375a776a56179b65c3bd8771a215fa8f301976eb2ccfe/alpy-0.10.0.tar.gz" } ], "0.11.0": [ { "comment_text": "", "digests": { "md5": "a45a8903b19ca5c907e0d00122750267", "sha256": "5c23d78cd490891c8af2646f6c2925cd7de0caf96a6aa6880c1ab2b02a104307" }, "downloads": -1, "filename": "alpy-0.11.0-py3-none-any.whl", "has_sig": false, "md5_digest": "a45a8903b19ca5c907e0d00122750267", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 21869, "upload_time": "2019-04-14T18:11:09", "url": "https://files.pythonhosted.org/packages/0e/eb/f04cbcf616304d264906978a51ad0f62f3deb25762aedfbadd5ad8ff0c0b/alpy-0.11.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "7ec36cac0fc8f8814b31571b17733087", "sha256": "473d172f1536ec835b5026cb9101b0271eaeff6f51b936988d416c28e48121fb" }, "downloads": -1, "filename": "alpy-0.11.0.tar.gz", "has_sig": false, "md5_digest": "7ec36cac0fc8f8814b31571b17733087", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8194, "upload_time": "2019-04-14T18:11:11", "url": "https://files.pythonhosted.org/packages/83/0c/5bf8f6020083ff0bc089f3d72a1bb94fa6cc04f17e683f3fa42053ced848/alpy-0.11.0.tar.gz" } ], "0.12.0": [ { "comment_text": "", "digests": { "md5": "7095ec712734b9da38da38c4908cf2e6", "sha256": "5848511d82df243235ddf7f374aba86ae81e3327d5b80204561568d75b4b7422" }, "downloads": -1, "filename": "alpy-0.12.0-py3-none-any.whl", "has_sig": false, "md5_digest": "7095ec712734b9da38da38c4908cf2e6", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 22275, "upload_time": "2019-04-21T18:34:18", "url": "https://files.pythonhosted.org/packages/47/45/3eca25cb6c9228291b82ec236f4c45990745867165a2d60118e94ff61a12/alpy-0.12.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "ff15d6084616e5c9381f01e4774ad744", "sha256": "a6f7e70b09730cd7471b10de581476f173e4af96fa6a6dcb26b82facaa2b0f4d" }, "downloads": -1, "filename": "alpy-0.12.0.tar.gz", "has_sig": false, "md5_digest": "ff15d6084616e5c9381f01e4774ad744", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8531, "upload_time": "2019-04-21T18:34:20", "url": "https://files.pythonhosted.org/packages/d0/d0/e0cbd0e3cc3c89127c67ba5b9a092d7f0536330457f3b95a5b6b40126916/alpy-0.12.0.tar.gz" } ], "0.13.0": [ { "comment_text": "", "digests": { "md5": "5c0e6f0bf68c3cbac338d9e1ede4226d", "sha256": "aa77422b507d7274cf25839e3158868b7f44d2e9c05734d91bbc00ca7825be0d" }, "downloads": -1, "filename": "alpy-0.13.0-py3-none-any.whl", "has_sig": false, "md5_digest": "5c0e6f0bf68c3cbac338d9e1ede4226d", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 22936, "upload_time": "2019-05-02T17:08:53", "url": "https://files.pythonhosted.org/packages/f6/68/0ca9b3fa3fef8f4363178002db05d0d831e95000db93aa5ac3a38081a5f8/alpy-0.13.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "ab2cd8fa0012807b104711dbfd88bd88", "sha256": "f8d974e3f6a3343e75804913cbb1e95408fac786cdc36b6908b0e7f0b78f50eb" }, "downloads": -1, "filename": "alpy-0.13.0.tar.gz", "has_sig": false, "md5_digest": "ab2cd8fa0012807b104711dbfd88bd88", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9740, "upload_time": "2019-05-02T17:08:54", "url": "https://files.pythonhosted.org/packages/cf/86/fc13d3c51128420d608e21f02dd45a0d5c1a8ba0c01b8df5c18eafce6bad/alpy-0.13.0.tar.gz" } ], "0.14.0": [ { "comment_text": "", "digests": { "md5": "5b31c900a20546afba38d19ddde921ff", "sha256": "2484f723b9bcc08de54dbf9fc71b4bdd73bc1ec859f52b92b5fa1b7c7be182de" }, "downloads": -1, "filename": "alpy-0.14.0-py3-none-any.whl", "has_sig": false, "md5_digest": "5b31c900a20546afba38d19ddde921ff", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 22689, "upload_time": "2019-05-05T19:25:22", "url": "https://files.pythonhosted.org/packages/8e/b1/eabde3c0de9f53724163bdaca70b84e3882cacff903f6b1ead8dd0430879/alpy-0.14.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "907ddd64a6227e9e4a35b4271c780d10", "sha256": "3414e9bcdd9309b5daab0c9f5e17019e4e4b91636450e2b2501d993765fb8998" }, "downloads": -1, "filename": "alpy-0.14.0.tar.gz", "has_sig": false, "md5_digest": "907ddd64a6227e9e4a35b4271c780d10", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9578, "upload_time": "2019-05-05T19:25:23", "url": "https://files.pythonhosted.org/packages/87/e4/ba534c08fcffaa18f070eda1b82a3c595d820b164c51dbdd9b347bf7c092/alpy-0.14.0.tar.gz" } ], "0.15.0": [ { "comment_text": "", "digests": { "md5": "02e17e6b10934d0470ddaf4b72124c60", "sha256": "45881ec7ce3c2074eb31c7cde2055975bc674cfa299cdc3d2539ec24f38af0dc" }, "downloads": -1, "filename": "alpy-0.15.0-py3-none-any.whl", "has_sig": false, "md5_digest": "02e17e6b10934d0470ddaf4b72124c60", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 22952, "upload_time": "2019-05-11T17:21:51", "url": "https://files.pythonhosted.org/packages/10/1a/a213880f086e54de1cb35f9ba2ecc215c6d0dd18bd3633e242fdba980e08/alpy-0.15.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "10287e6c256999fbc70aab9da3425f2d", "sha256": "52eeb5f06a5473beaca6920ed03e92cbefbd912ba6c1a5492ebc0c94e736235e" }, "downloads": -1, "filename": "alpy-0.15.0.tar.gz", "has_sig": false, "md5_digest": "10287e6c256999fbc70aab9da3425f2d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9615, "upload_time": "2019-05-11T17:21:53", "url": "https://files.pythonhosted.org/packages/e9/51/4aa4fe7d7eb57721f0d4a04b14360704e22e8db6746b9ff6feeeb7331160/alpy-0.15.0.tar.gz" } ], "0.16.0": [ { "comment_text": "", "digests": { "md5": "9a830d97856e8c06edc7de4252bb3653", "sha256": "f3388ea386ee7992f720d7346a6794315f4a835a3c32a084eadd995f16ec5198" }, "downloads": -1, "filename": "alpy-0.16.0-py3-none-any.whl", "has_sig": false, "md5_digest": "9a830d97856e8c06edc7de4252bb3653", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 23260, "upload_time": "2019-05-18T16:13:39", "url": "https://files.pythonhosted.org/packages/62/ca/34a2713c6d1bd3b462e1b83a18bdc9eb2a91a28f921b254c5b445fcad723/alpy-0.16.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "dda9050dabfa26943322e21e9fce0612", "sha256": "6e987ce6c0351a16a0e30c83119029c1081a34899354eea784fecf966b2b2022" }, "downloads": -1, "filename": "alpy-0.16.0.tar.gz", "has_sig": false, "md5_digest": "dda9050dabfa26943322e21e9fce0612", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10252, "upload_time": "2019-05-18T16:13:41", "url": "https://files.pythonhosted.org/packages/cf/0e/aeb4d26c560878c4a7c1930e6148c36bf6c9ae1773f39d96afcf55a12ba2/alpy-0.16.0.tar.gz" } ], "0.17.0": [ { "comment_text": "", "digests": { "md5": "441f3c7309fe34399e1b000b532390fb", "sha256": "811287d70128f1147ed7f636182a9b722b6d4c42b7914b3b25457eecee985622" }, "downloads": -1, "filename": "alpy-0.17.0-py3-none-any.whl", "has_sig": false, "md5_digest": "441f3c7309fe34399e1b000b532390fb", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 23673, "upload_time": "2019-06-01T16:13:01", "url": "https://files.pythonhosted.org/packages/b3/cf/7721b0440b14a53d99fa4cb00344d45830be86715d4cae642130f2d3311b/alpy-0.17.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "19555122b6c4047a21fe81128f3c68df", "sha256": "8d0e28605696e0a59294eaf1c71526923f83ae6e0995a082537cc87788090365" }, "downloads": -1, "filename": "alpy-0.17.0.tar.gz", "has_sig": false, "md5_digest": "19555122b6c4047a21fe81128f3c68df", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10466, "upload_time": "2019-06-01T16:13:03", "url": "https://files.pythonhosted.org/packages/9e/cf/c5442feaadc4f95bb11c3e005ec5b6efa2083cf85b428112a623c239835a/alpy-0.17.0.tar.gz" } ], "0.18.0": [ { "comment_text": "", "digests": { "md5": "1853fb87af9308c72610ecac226c001f", "sha256": "8d78e3735c5c12534e163f2af6368d3440f526d0f0693edc6e4ea462bbcc4528" }, "downloads": -1, "filename": "alpy-0.18.0-py3-none-any.whl", "has_sig": false, "md5_digest": "1853fb87af9308c72610ecac226c001f", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 24089, "upload_time": "2019-06-16T18:42:27", "url": "https://files.pythonhosted.org/packages/a5/10/f4eb9369482de98d3be35255bcb06d41eec40ae6d68a1d79c2643349538c/alpy-0.18.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "e9a68c08fb7dc4b0eb613ce0d91c7b39", "sha256": "3ab480d970712fce0f1ccd32c9a260c185a803737975609bf11a08014b242ead" }, "downloads": -1, "filename": "alpy-0.18.0.tar.gz", "has_sig": false, "md5_digest": "e9a68c08fb7dc4b0eb613ce0d91c7b39", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10763, "upload_time": "2019-06-16T18:42:29", "url": "https://files.pythonhosted.org/packages/2b/67/9fd36aeadbb004f9737eb161e20b54705045931e0bf3b5c1d64bb7dba40e/alpy-0.18.0.tar.gz" } ], "0.19.0": [ { "comment_text": "", "digests": { "md5": "282fe7e5a4eeb0f420ba2da1e37eb06a", "sha256": "f6209348b7a9acc16f12d2fd21d6622f59896a92ae545a7f2bc44e67386711e5" }, "downloads": -1, "filename": "alpy-0.19.0-py3-none-any.whl", "has_sig": false, "md5_digest": "282fe7e5a4eeb0f420ba2da1e37eb06a", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 23541, "upload_time": "2019-06-23T15:42:58", "url": "https://files.pythonhosted.org/packages/cf/f0/9944a969684a2bf92dbdf827192146b2eaeb2734c04798a238245ec4e807/alpy-0.19.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "a4b3d6a96ae7bc2cab1f37e3b4792ec3", "sha256": "d00bdb8a1b795822e9419fa139fbbee63558901a7591f8ba8ecc25aac8b5118e" }, "downloads": -1, "filename": "alpy-0.19.0.tar.gz", "has_sig": false, "md5_digest": "a4b3d6a96ae7bc2cab1f37e3b4792ec3", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10283, "upload_time": "2019-06-23T15:42:59", "url": "https://files.pythonhosted.org/packages/e8/d8/362605b6a6a3406f0131fcf4928584d5e0f8a2a970758b82daca8a0d7f80/alpy-0.19.0.tar.gz" } ], "0.20.0": [ { "comment_text": "", "digests": { "md5": "35b884aa84f086bbceb1f15329614c5b", "sha256": "edf46aa74534d1e8b219bb363c1bac21b423dee7b2fe24355e33c4ce102212d3" }, "downloads": -1, "filename": "alpy-0.20.0-py3-none-any.whl", "has_sig": false, "md5_digest": "35b884aa84f086bbceb1f15329614c5b", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 23366, "upload_time": "2019-07-06T18:35:30", "url": "https://files.pythonhosted.org/packages/87/f2/b18b4fe4f0613b8f73c4991279ac9c95432813b8f8346bd0504597e8fcef/alpy-0.20.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "608e0f06b971cb2023f5588336f7323a", "sha256": "a9a909fff83c5983094cb22d7c28f0b43c4b8cf14ba185774ac2632717bbddec" }, "downloads": -1, "filename": "alpy-0.20.0.tar.gz", "has_sig": false, "md5_digest": "608e0f06b971cb2023f5588336f7323a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10289, "upload_time": "2019-07-06T18:35:32", "url": "https://files.pythonhosted.org/packages/c6/f4/250087ef3dffb61e5fe02120c0298d265abb79110c042c4053aaba633b47/alpy-0.20.0.tar.gz" } ], "0.21.0": [ { "comment_text": "", "digests": { "md5": "d17ef9fdf5c7872aecc499cd00f075cc", "sha256": "a8671fa0615fa36636ebbc896e5d53902585c6f2feaa8e8656f91f73bb433e7f" }, "downloads": -1, "filename": "alpy-0.21.0-py3-none-any.whl", "has_sig": false, "md5_digest": "d17ef9fdf5c7872aecc499cd00f075cc", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 23389, "upload_time": "2019-07-13T13:01:58", "url": "https://files.pythonhosted.org/packages/df/6e/23467dc292d573c3d32ab36fd1ac72d1b160397af428521bde8282ba8289/alpy-0.21.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "38a599857ac35dce9fafd20354800614", "sha256": "138889912cb5a3bf0cceebedd9556361d63e036bdca65992f1dfbc7522d06cce" }, "downloads": -1, "filename": "alpy-0.21.0.tar.gz", "has_sig": false, "md5_digest": "38a599857ac35dce9fafd20354800614", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10310, "upload_time": "2019-07-13T13:02:00", "url": "https://files.pythonhosted.org/packages/7d/b0/7723fb7eb27c64e79065cd306940a8ed2f746f341fcde4624b49cc920b7b/alpy-0.21.0.tar.gz" } ], "0.22.0": [ { "comment_text": "", "digests": { "md5": "08520ae0be36dd5eeaa820b55a9d917f", "sha256": "3b561ddd629d38405845811c70efca8f8db7c08730fc51c92b6892014166e605" }, "downloads": -1, "filename": "alpy-0.22.0-py3-none-any.whl", "has_sig": false, "md5_digest": "08520ae0be36dd5eeaa820b55a9d917f", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 23395, "upload_time": "2019-07-21T11:07:07", "url": "https://files.pythonhosted.org/packages/5d/c6/8646fb73f297b99d2dc664a5159c2be99a17e802972a2b565a830a361242/alpy-0.22.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "c5b621f0597aa9822a07083fb8580849", "sha256": "be63995646e6dbac48adb8dca322d37496a6718f68d60aded39f7e9a41195905" }, "downloads": -1, "filename": "alpy-0.22.0.tar.gz", "has_sig": false, "md5_digest": "c5b621f0597aa9822a07083fb8580849", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10314, "upload_time": "2019-07-21T11:07:09", "url": "https://files.pythonhosted.org/packages/ed/0e/3cd5f6f1392bc3209a60183d14cd4f15dcf522b1ea82e7c6ba66e107e519/alpy-0.22.0.tar.gz" } ], "0.23.0": [ { "comment_text": "", "digests": { "md5": "0d1472d14684589bb06cf6b1a17f22d1", "sha256": "c34615775a218b1cd126ced3e5ee437238d8931047fe6ee408ea0542ae08c551" }, "downloads": -1, "filename": "alpy-0.23.0-py3-none-any.whl", "has_sig": false, "md5_digest": "0d1472d14684589bb06cf6b1a17f22d1", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 24800, "upload_time": "2019-10-20T10:27:13", "url": "https://files.pythonhosted.org/packages/f9/14/08110e82844de1481700f1e1b1e6b398935950063e1035e985038e7ea4d2/alpy-0.23.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "ebb9e2c02f19d9a26ce3fb7dc02f5289", "sha256": "11d535ca717f701d99527483acbf5660618d9165901e75d814611c95ea715e72" }, "downloads": -1, "filename": "alpy-0.23.0.tar.gz", "has_sig": false, "md5_digest": "ebb9e2c02f19d9a26ce3fb7dc02f5289", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13935, "upload_time": "2019-10-20T10:27:15", "url": "https://files.pythonhosted.org/packages/0a/02/5077b6a0e2eaa3f6b7135c8d6df2abf417cf17e753a3f1a5a713ed5f2bf6/alpy-0.23.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "0d1472d14684589bb06cf6b1a17f22d1", "sha256": "c34615775a218b1cd126ced3e5ee437238d8931047fe6ee408ea0542ae08c551" }, "downloads": -1, "filename": "alpy-0.23.0-py3-none-any.whl", "has_sig": false, "md5_digest": "0d1472d14684589bb06cf6b1a17f22d1", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 24800, "upload_time": "2019-10-20T10:27:13", "url": "https://files.pythonhosted.org/packages/f9/14/08110e82844de1481700f1e1b1e6b398935950063e1035e985038e7ea4d2/alpy-0.23.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "ebb9e2c02f19d9a26ce3fb7dc02f5289", "sha256": "11d535ca717f701d99527483acbf5660618d9165901e75d814611c95ea715e72" }, "downloads": -1, "filename": "alpy-0.23.0.tar.gz", "has_sig": false, "md5_digest": "ebb9e2c02f19d9a26ce3fb7dc02f5289", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13935, "upload_time": "2019-10-20T10:27:15", "url": "https://files.pythonhosted.org/packages/0a/02/5077b6a0e2eaa3f6b7135c8d6df2abf417cf17e753a3f1a5a713ed5f2bf6/alpy-0.23.0.tar.gz" } ] }