{ "info": { "author": "sobolevn", "author_email": "mail@sobolevn.me", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Topic :: Software Development :: Libraries :: Python Modules", "Topic :: Utilities" ], "description": "[![Returns logo](https://raw.githubusercontent.com/dry-python/brand/master/logo/returns.png)](https://github.com/dry-python/returns)\n\n-----\n\n[![Build Status](https://travis-ci.org/dry-python/returns.svg?branch=master)](https://travis-ci.org/dry-python/returns) [![Coverage Status](https://coveralls.io/repos/github/dry-python/returns/badge.svg?branch=master)](https://coveralls.io/github/dry-python/returns?branch=master) [![Documentation Status](https://readthedocs.org/projects/returns/badge/?version=latest)](https://returns.readthedocs.io/en/latest/?badge=latest) [![Python Version](https://img.shields.io/pypi/pyversions/returns.svg)](https://pypi.org/project/returns/) [![wemake-python-styleguide](https://img.shields.io/badge/style-wemake-000000.svg)](https://github.com/wemake-services/wemake-python-styleguide) [![Checked with mypy](http://www.mypy-lang.org/static/mypy_badge.svg)](http://mypy-lang.org/)\n\n-----\n\nMake your functions return something meaningful, typed, and safe!\n\n\n## Features\n\n- Provides a bunch of primitives to write declarative business logic\n- Enforces better architecture\n- Fully typed with annotations and checked with `mypy`, [PEP561 compatible](https://www.python.org/dev/peps/pep-0561/)\n- Has a bunch of helpers for better composition\n- Pythonic and pleasant to write and to read (!)\n- Support functions and coroutines, framework agnostic\n- Easy to start: has lots of docs, tests, and tutorials\n\n\n## Installation\n\n```bash\npip install returns\n```\n\nYou might also want to [configure](https://returns.readthedocs.io/en/latest/pages/container.html#type-safety)\n`mypy` correctly and install our plugin\nto fix [this existing issue](https://github.com/python/mypy/issues/3157):\n\n```ini\n# In setup.cfg or mypy.ini:\n[mypy]\nplugins =\n returns.contrib.mypy.decorator_plugin\n```\n\nWe also recommend to use the same `mypy` settings [we use](https://github.com/wemake-services/wemake-python-styleguide/blob/master/styles/mypy.toml).\n\nMake sure you know how to get started, [check out our docs](https://returns.readthedocs.io/en/latest/)!\n\n\n## Contents\n\n- [Maybe container](#maybe-container) that allows you to write `None`-free code\n- [Result container](#result-container) that let's you to get rid of exceptions\n- [IO marker](#io-marker) that marks all impure operations and structures them\n\n\n## Maybe container\n\n`None` is called the [worst mistake in the history of Computer Science](https://www.infoq.com/presentations/Null-References-The-Billion-Dollar-Mistake-Tony-Hoare/).\n\nSo, what can we do to check for `None` in our programs?\nYou can use `Optional` and write a lot of `if some is not None:` conditions.\nBut, having them here and there makes your code unreadable.\n\nOr you can use\n[Maybe](https://returns.readthedocs.io/en/latest/pages/maybe.html) container!\nIt consists of `Some` and `Nothing` types,\nrepresenting existing state and empty (instead of `None`) state respectively.\n\n```python\nfrom typing import Optional\nfrom returns.maybe import Maybe, maybe\n\n@maybe # decorator to convert existing Optional[int] to Maybe[int]\ndef bad_function() -> Optional[int]:\n ...\n\nmaybe_result: Maybe[float] = bad_function().map(\n lambda number: number / 2,\n)\n# => Maybe will return Some[float] only if there's a non-None value\n# Otherwise, will return Nothing\n```\n\nYou can be sure that `.map()` method won't be called for `Nothing`.\nForget about `None`-related errors forever!\n\n\n## Result container\n\nPlease, make sure that you are also aware of\n[Railway Oriented Programming](https://fsharpforfunandprofit.com/rop/).\n\n### Straight-forward approach\n\nConsider this code that you can find in **any** `python` project.\n\n```python\nimport requests\n\ndef fetch_user_profile(user_id: int) -> 'UserProfile':\n \"\"\"Fetches UserProfile dict from foreign API.\"\"\"\n response = requests.get('/api/users/{0}'.format(user_id))\n response.raise_for_status()\n return response.json()\n```\n\nSeems legit, does not it?\nIt also seems like a pretty straight forward code to test.\nAll you need is to mock `requests.get` to return the structure you need.\n\nBut, there are hidden problems in this tiny code sample\nthat are almost impossible to spot at the first glance.\n\n### Hidden problems\n\nLet's have a look at the exact same code,\nbut with the all hidden problems explained.\n\n```python\nimport requests\n\ndef fetch_user_profile(user_id: int) -> 'UserProfile':\n \"\"\"Fetches UserProfile dict from foreign API.\"\"\"\n response = requests.get('/api/users/{0}'.format(user_id))\n\n # What if we try to find user that does not exist?\n # Or network will go down? Or the server will return 500?\n # In this case the next line will fail with an exception.\n # We need to handle all possible errors in this function\n # and do not return corrupt data to consumers.\n response.raise_for_status()\n\n # What if we have received invalid JSON?\n # Next line will raise an exception!\n return response.json()\n```\n\nNow, all (probably all?) problems are clear.\nHow can we be sure that this function will be safe\nto use inside our complex business logic?\n\nWe really can not be sure!\nWe will have to create **lots** of `try` and `except` cases\njust to catch the expected exceptions.\n\nOur code will become complex and unreadable with all this mess!\n\n### Pipe example\n\n```python\nimport requests\nfrom returns.result import Result, safe\nfrom returns.pipeline import pipe\nfrom returns.functions import box\n\ndef fetch_user_profile(user_id: int) -> Result['UserProfile', Exception]:\n \"\"\"Fetches `UserProfile` TypedDict from foreign API.\"\"\"\n return pipe(\n _make_request,\n box(_parse_json),\n )(user_id)\n\n@safe\ndef _make_request(user_id: int) -> requests.Response:\n response = requests.get('/api/users/{0}'.format(user_id))\n response.raise_for_status()\n return response\n\n@safe\ndef _parse_json(response: requests.Response) -> 'UserProfile':\n return response.json()\n```\n\nNow we have a clean and a safe and declarative way\nto express our business need.\nWe start from making a request, that might fail at any moment.\nThen parsing the response if the request was successful.\nAnd then return the result.\nIt all happens smoothly due to [pipe](https://returns.readthedocs.io/en/latest/pages/pipeline.html#pipe) function.\n\nWe also use [box](https://returns.readthedocs.io/en/latest/pages/functions.html#box) for handy composition.\n\nNow, instead of returning a regular value\nit returns a wrapped value inside a special container\nthanks to the\n[@safe](https://returns.readthedocs.io/en/latest/pages/result.html#safe)\ndecorator.\n\nIt will return [Success[Response] or Failure[Exception]](https://returns.readthedocs.io/en/latest/pages/result.html).\nAnd will never throw this exception at us.\n\nAnd we can clearly see all result patterns\nthat might happen in this particular case:\n- `Success[UserProfile]`\n- `Failure[Exception]`\n\nFor more complex cases there's a [@pipeline](https://returns.readthedocs.io/en/latest/pages/functions.html#returns.functions.pipeline)\ndecorator to help you with the composition.\n\nAnd we can work with each of them precisely.\nIt is a good practice to create `Enum` classes or `Union` sum type\nwith all the possible errors.\n\n\n## IO marker\n\nBut is that all we can improve?\nLet's look at `FetchUserProfile` from another angle.\nAll its methods look like regular ones:\nit is impossible to tell whether they are pure or impure from the first sight.\n\nIt leads to a very important consequence:\n*we start to mix pure and impure code together*.\nWe should not do that!\n\nWhen these two concepts are mixed\nwe suffer really bad when testing or reusing it.\nAlmost everything should be pure by default.\nAnd we should explicitly mark impure parts of the program.\n\n### Explicit IO\n\nLet's refactor it to make our\n[IO](https://returns.readthedocs.io/en/latest/pages/io.html) explicit!\n\n```python\nimport requests\nfrom returns.io import IO, impure\nfrom returns.result import Result, safe\nfrom returns.pipeline import pipe\nfrom returns.functions import box\n\ndef fetch_user_profile(user_id: int) -> Result['UserProfile', Exception]:\n \"\"\"Fetches `UserProfile` TypedDict from foreign API.\"\"\"\n return pipe(\n _make_request,\n # after box: def (Result) -> Result\n # after IO.lift: def (IO[Result]) -> IO[Result]\n IO.lift(box(_parse_json)),\n )(user_id)\n\n@impure\n@safe\ndef _make_request(user_id: int) -> requests.Response:\n response = requests.get('/api/users/{0}'.format(user_id))\n response.raise_for_status()\n return response\n\n@safe\ndef _parse_json(response: requests.Response) -> 'UserProfile':\n return response.json()\n```\n\nNow we have explicit markers where the `IO` did happen\nand these markers cannot be removed.\n\nWhenever we access `FetchUserProfile` we now know\nthat it does `IO` and might fail.\nSo, we act accordingly!\n\n\n## More!\n\nWant more? [Go to the docs!](https://returns.readthedocs.io)\nOr read these articles:\n\n- [Python exceptions considered an anti-pattern](https://sobolevn.me/2019/02/python-exceptions-considered-an-antipattern)\n- [Enforcing Single Responsibility Principle in Python](https://sobolevn.me/2019/03/enforcing-srp)\n\nDo you have an article to submit? Feel free to open a pull request!\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://returns.readthedocs.io", "keywords": "functional programming,fp,monads,monad,monad transformers,composition,type-safety,mypy,railway-oriented-programming", "license": "BSD-2-Clause", "maintainer": "sobolevn", "maintainer_email": "mail@sobolevn.me", "name": "returns", "package_url": "https://pypi.org/project/returns/", "platform": "", "project_url": "https://pypi.org/project/returns/", "project_urls": { "Homepage": "https://returns.readthedocs.io", "Repository": "https://github.com/dry-python/returns" }, "release_url": "https://pypi.org/project/returns/0.11.0/", "requires_dist": [ "typing-extensions (>=3.7,<4.0)" ], "requires_python": ">=3.6,<4.0", "summary": "Make your functions return something meaningful, typed, and safe!", "version": "0.11.0" }, "last_serial": 5757137, "releases": { "0.10.0": [ { "comment_text": "", "digests": { "md5": "4c6269376ff3d5899810b2d1d4814dbc", "sha256": "50eac880d63bb21adf883a062fd07043d21ca33ec027fd9488d5ace147bb7a6c" }, "downloads": -1, "filename": "returns-0.10.0-py3-none-any.whl", "has_sig": false, "md5_digest": "4c6269376ff3d5899810b2d1d4814dbc", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.6,<4.0", "size": 48768, "upload_time": "2019-08-18T14:13:19", "url": "https://files.pythonhosted.org/packages/83/b1/571afee58555b18082505c144b0b5079a000c5d2966fc72965f79acae447/returns-0.10.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "bfa8ab0e209b57e68db0c8a7646e9f07", "sha256": "3d3cabfebb7175d2401dfd2d68b2f8f053b9280897817f07c35b027188fb4688" }, "downloads": -1, "filename": "returns-0.10.0.tar.gz", "has_sig": false, "md5_digest": "bfa8ab0e209b57e68db0c8a7646e9f07", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6,<4.0", "size": 17657, "upload_time": "2019-08-18T14:13:21", "url": "https://files.pythonhosted.org/packages/22/45/ec1cb65ebf6c4743b4e89b14ef2c9f5246f2006aefaf80ac73ac471ea528/returns-0.10.0.tar.gz" } ], "0.11.0": [ { "comment_text": "", "digests": { "md5": "848ed2e69c03a58f81acad68db35ee28", "sha256": "c70de72c2c4ac0adee77320933f2c80b9b153e0bed8bf8aa3e428a19b5006225" }, "downloads": -1, "filename": "returns-0.11.0-py3-none-any.whl", "has_sig": false, "md5_digest": "848ed2e69c03a58f81acad68db35ee28", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.6,<4.0", "size": 58545, "upload_time": "2019-08-29T21:41:00", "url": "https://files.pythonhosted.org/packages/a8/14/453ef80f0cfba6bca1396d41c6085598c2bcda26667c9e8a9a2c6999bb2e/returns-0.11.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "49d7044791d2d56b8b8beb97266ba7bd", "sha256": "5881eb97daa4d62d513104fa4520e625f90d2a9ff7d7827e1cda21645c5b0c76" }, "downloads": -1, "filename": "returns-0.11.0.tar.gz", "has_sig": false, "md5_digest": "49d7044791d2d56b8b8beb97266ba7bd", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6,<4.0", "size": 18935, "upload_time": "2019-08-29T21:41:02", "url": "https://files.pythonhosted.org/packages/23/44/fac13b51b4f0b5773830200d6eebecb80140f596fae06e7a98bd85129490/returns-0.11.0.tar.gz" } ], "0.2.0": [ { "comment_text": "", "digests": { "md5": "ec8c719dd853a3f62a76f66043e8c288", "sha256": "78d3fbfad8bf2e1934f1ee84f6bed3fba92ffaae156d441d3b118622379b8d0a" }, "downloads": -1, "filename": "returns-0.2.0-py3-none-any.whl", "has_sig": false, "md5_digest": "ec8c719dd853a3f62a76f66043e8c288", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.6,<4.0", "size": 22775, "upload_time": "2019-01-30T18:55:59", "url": "https://files.pythonhosted.org/packages/f0/30/e473806d819960ea7b0cbaa240be835f5f7f09ea52b29716f2b6aa0ae788/returns-0.2.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "4898ebc78056842ec5bc0486664e7693", "sha256": "cd7c37a745255d034fcb03e969a0927a820ae456c2c76c6e1968e6875ab25fac" }, "downloads": -1, "filename": "returns-0.2.0.tar.gz", "has_sig": false, "md5_digest": "4898ebc78056842ec5bc0486664e7693", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6,<4.0", "size": 8432, "upload_time": "2019-01-30T18:56:12", "url": "https://files.pythonhosted.org/packages/10/90/90aa7f935f96447bdbde413478cf969cb3448bcc28a1780c0edd0e4398dc/returns-0.2.0.tar.gz" } ], "0.3.0": [ { "comment_text": "", "digests": { "md5": "98e115b681de32c7f5e3d0d16c48e845", "sha256": "881f759a45cdaa92a52ef183bc1a051163b05389de1b2d30f19d63690e999aa0" }, "downloads": -1, "filename": "returns-0.3.0-py3-none-any.whl", "has_sig": false, "md5_digest": "98e115b681de32c7f5e3d0d16c48e845", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.6,<4.0", "size": 29774, "upload_time": "2019-02-02T13:30:27", "url": "https://files.pythonhosted.org/packages/25/1e/c01ebf5a97f6e44fa0f4902329059ce4f0af441824a5498d07d5a161a3b8/returns-0.3.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "d9a28c66cb8e14492da14e468ac38d7c", "sha256": "3899f29bbecd16794eb491fdfa0d98ef7453ea8de867f24bcae680ba23ef2c9d" }, "downloads": -1, "filename": "returns-0.3.0.tar.gz", "has_sig": false, "md5_digest": "d9a28c66cb8e14492da14e468ac38d7c", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6,<4.0", "size": 9294, "upload_time": "2019-02-02T13:30:29", "url": "https://files.pythonhosted.org/packages/28/fa/896d164f5bdaae305ca198b3d68c7f9c625dd4c7c28a8dc391a384607822/returns-0.3.0.tar.gz" } ], "0.3.1": [ { "comment_text": "", "digests": { "md5": "74c377c34a2bdf15f023687f4d5f0db1", "sha256": "3c34473e7fc62294551ac72f19461610e9989c5315e2688a67d819e2c8338bc0" }, "downloads": -1, "filename": "returns-0.3.1-py3-none-any.whl", "has_sig": false, "md5_digest": "74c377c34a2bdf15f023687f4d5f0db1", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.6,<4.0", "size": 29925, "upload_time": "2019-02-02T17:55:56", "url": "https://files.pythonhosted.org/packages/16/d3/c25201f48b415da7a8205d9723f3a6869b9b94aa5a2f2c17aa0d69eedcf0/returns-0.3.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "950b3c56a6bf0e16b496f3614c3ac873", "sha256": "d9dbd06e18bd3291ecf68768ef2d055ba7a48327ab199214988360c48d89a1bb" }, "downloads": -1, "filename": "returns-0.3.1.tar.gz", "has_sig": false, "md5_digest": "950b3c56a6bf0e16b496f3614c3ac873", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6,<4.0", "size": 9330, "upload_time": "2019-02-02T17:55:59", "url": "https://files.pythonhosted.org/packages/18/93/bfad45bce4385e017e35253f2c9fbedfd312720b03c1af5124458c6434d6/returns-0.3.1.tar.gz" } ], "0.4.0": [ { "comment_text": "", "digests": { "md5": "b218f1bc80a90bf43136f922d384c80b", "sha256": "7684bb25443011fa3d8ac01d72d5d341c96efccd4df689360b17450d86bf40fc" }, "downloads": -1, "filename": "returns-0.4.0-py3-none-any.whl", "has_sig": false, "md5_digest": "b218f1bc80a90bf43136f922d384c80b", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.6,<4.0", "size": 21889, "upload_time": "2019-02-04T11:49:19", "url": "https://files.pythonhosted.org/packages/c7/2b/a87d557db9186f77381ab178baf14fcc7e435924aab1a157b03cbd150a8a/returns-0.4.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "2703ac484c2f3c1e53c27ac3f6c3e842", "sha256": "1f276bcd3b9ae4105fa5c10b99552196f6f7679c722ba7a2bd0f30fe70ffd73a" }, "downloads": -1, "filename": "returns-0.4.0.tar.gz", "has_sig": false, "md5_digest": "2703ac484c2f3c1e53c27ac3f6c3e842", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6,<4.0", "size": 10241, "upload_time": "2019-02-04T11:49:21", "url": "https://files.pythonhosted.org/packages/0c/0a/466461214aec2f673d3c859cffd4ccf4069d227a555bbe97a7d1a7fb2509/returns-0.4.0.tar.gz" } ], "0.5.0": [ { "comment_text": "", "digests": { "md5": "6942c4f417863de26bd7648bb09d7038", "sha256": "843a60a9da47fb414786046da78103ea4903b51faaf93a9431ef1e607dfdb45a" }, "downloads": -1, "filename": "returns-0.5.0-py3-none-any.whl", "has_sig": false, "md5_digest": "6942c4f417863de26bd7648bb09d7038", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.6,<4.0", "size": 23548, "upload_time": "2019-06-01T11:06:56", "url": "https://files.pythonhosted.org/packages/aa/72/e29f17e86c0bfdf80608db2c6bac3adb244390f3d1538e798bb907b94338/returns-0.5.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "03a72ae4b07ed1320ed7782d1c79a2fd", "sha256": "bd920157db625f632eacc2b9e32d089367a22b4ebee69f59538fffe0f1ea2df6" }, "downloads": -1, "filename": "returns-0.5.0.tar.gz", "has_sig": false, "md5_digest": "03a72ae4b07ed1320ed7782d1c79a2fd", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6,<4.0", "size": 10213, "upload_time": "2019-06-01T11:06:57", "url": "https://files.pythonhosted.org/packages/81/17/7c3bb77baa1dc114290db5055d21cebf814ce743731c591a9708609a9261/returns-0.5.0.tar.gz" } ], "0.6.0": [ { "comment_text": "", "digests": { "md5": "8edb4bd11d697bebdbe6dba0820a6485", "sha256": "b77d66d6ffe8846bda087961e01a32daa760f18e2d6642644d7dd8e9db289356" }, "downloads": -1, "filename": "returns-0.6.0-py3-none-any.whl", "has_sig": false, "md5_digest": "8edb4bd11d697bebdbe6dba0820a6485", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.6,<4.0", "size": 25050, "upload_time": "2019-06-07T11:12:02", "url": "https://files.pythonhosted.org/packages/a5/9f/9fd2d3bfbd35a2ce81b5032e5fdee14268111cc5fac42e740b05715a002d/returns-0.6.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "6b7da9d0ab0f010f04770c19cacd6307", "sha256": "3ee82e04d15a201a41a069c95ffad225fbc59bf432fa16c59955282dc9c8a1fe" }, "downloads": -1, "filename": "returns-0.6.0.tar.gz", "has_sig": false, "md5_digest": "6b7da9d0ab0f010f04770c19cacd6307", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6,<4.0", "size": 10460, "upload_time": "2019-06-07T11:12:04", "url": "https://files.pythonhosted.org/packages/88/41/fb3ee0d0b5e11a0389555944c37a0c559fea82a4e6689728a6adcddc72e0/returns-0.6.0.tar.gz" } ], "0.7.0": [ { "comment_text": "", "digests": { "md5": "4b60ffc64e60ad454cb1779483a1c428", "sha256": "4ae24494066f50a272c979a3a562e7010e1c13bc3251c54cfaa3071015707177" }, "downloads": -1, "filename": "returns-0.7.0-py3-none-any.whl", "has_sig": false, "md5_digest": "4b60ffc64e60ad454cb1779483a1c428", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.6,<4.0", "size": 29562, "upload_time": "2019-06-11T08:49:54", "url": "https://files.pythonhosted.org/packages/c3/f9/8a54e06146b8f05a2659780241969424d1203c60d2d3870ea7ce6078b902/returns-0.7.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "58eb4e31e21cc83328584139b4b38490", "sha256": "70e8e02f142ad23d8d9289317aeef461fdaa4bda451dce08548a60268985a055" }, "downloads": -1, "filename": "returns-0.7.0.tar.gz", "has_sig": false, "md5_digest": "58eb4e31e21cc83328584139b4b38490", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6,<4.0", "size": 12526, "upload_time": "2019-06-11T08:49:56", "url": "https://files.pythonhosted.org/packages/c7/be/6c76a324f61c99fa58b268136d8a69c9490179dc4c55c4f9fc4633f093e5/returns-0.7.0.tar.gz" } ], "0.8.0": [ { "comment_text": "", "digests": { "md5": "864c2573d908a263ff55a53328418406", "sha256": "9650015abcef2783f13a890f875f9f1c96f6be4c61d4def099e8fefb19d762f6" }, "downloads": -1, "filename": "returns-0.8.0-py3-none-any.whl", "has_sig": false, "md5_digest": "864c2573d908a263ff55a53328418406", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.6,<4.0", "size": 40427, "upload_time": "2019-06-17T11:29:41", "url": "https://files.pythonhosted.org/packages/ec/d8/3ab34efd1eec6f176e94feee72395f141be28d3a9ba94229659766c2d221/returns-0.8.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "65a03e5b12313c4f2f35b533e54b9348", "sha256": "9ebfe9838212b3b4d53910f295f3706c6981ede3b025198a85dc6cbbeaeff36c" }, "downloads": -1, "filename": "returns-0.8.0.tar.gz", "has_sig": false, "md5_digest": "65a03e5b12313c4f2f35b533e54b9348", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6,<4.0", "size": 15185, "upload_time": "2019-06-17T11:29:43", "url": "https://files.pythonhosted.org/packages/2e/c4/743ea1d9753ba026c1e8af51067eb1b6c9a656da98da75776a44db324212/returns-0.8.0.tar.gz" } ], "0.9.0": [ { "comment_text": "", "digests": { "md5": "8df10fa0dfc0d81c4827fc22b813fec0", "sha256": "648ac841ea854952f2a6498aac2751b2d22d4aed5f0b421fda52741ccf8bed1c" }, "downloads": -1, "filename": "returns-0.9.0-py3-none-any.whl", "has_sig": false, "md5_digest": "8df10fa0dfc0d81c4827fc22b813fec0", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.6,<4.0", "size": 42442, "upload_time": "2019-07-01T14:25:59", "url": "https://files.pythonhosted.org/packages/1e/61/1f1c9d3391c9a236b648fdd58e1c0831f74fb97a48e7f4e8d83f0dfebfe1/returns-0.9.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "f80faa9461d80c026af59eb48bdbdfa2", "sha256": "c85129dfae5590d02428b977c744ed68584051629e66cd2f35f315911d52b07f" }, "downloads": -1, "filename": "returns-0.9.0.tar.gz", "has_sig": false, "md5_digest": "f80faa9461d80c026af59eb48bdbdfa2", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6,<4.0", "size": 15754, "upload_time": "2019-07-01T14:26:00", "url": "https://files.pythonhosted.org/packages/13/d4/3234481ab4da97faedee54629f6c0cfdcfc60de60d92d68aec646f7f88ff/returns-0.9.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "848ed2e69c03a58f81acad68db35ee28", "sha256": "c70de72c2c4ac0adee77320933f2c80b9b153e0bed8bf8aa3e428a19b5006225" }, "downloads": -1, "filename": "returns-0.11.0-py3-none-any.whl", "has_sig": false, "md5_digest": "848ed2e69c03a58f81acad68db35ee28", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.6,<4.0", "size": 58545, "upload_time": "2019-08-29T21:41:00", "url": "https://files.pythonhosted.org/packages/a8/14/453ef80f0cfba6bca1396d41c6085598c2bcda26667c9e8a9a2c6999bb2e/returns-0.11.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "49d7044791d2d56b8b8beb97266ba7bd", "sha256": "5881eb97daa4d62d513104fa4520e625f90d2a9ff7d7827e1cda21645c5b0c76" }, "downloads": -1, "filename": "returns-0.11.0.tar.gz", "has_sig": false, "md5_digest": "49d7044791d2d56b8b8beb97266ba7bd", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6,<4.0", "size": 18935, "upload_time": "2019-08-29T21:41:02", "url": "https://files.pythonhosted.org/packages/23/44/fac13b51b4f0b5773830200d6eebecb80140f596fae06e7a98bd85129490/returns-0.11.0.tar.gz" } ] }