{ "info": { "author": "Adfinis SyGroup AG", "author_email": "ganwell@fangorn.ch", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "Intended Audience :: Information Technology", "License :: OSI Approved :: MIT License", "Natural Language :: English", "Operating System :: OS Independent", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Topic :: Software Development :: Libraries", "Topic :: Software Development :: Testing" ], "description": "\n=========\nPure-func\n=========\n\n|travis| |pypi|\n\n.. |travis| image:: https://travis-ci.org/adfinis-sygroup/pure_func.svg?branch=master # noqa\n :target: https://travis-ci.org/adfinis-sygroup/pure_func\n\n.. |pypi| image:: https://badge.fury.io/py/pure-func.svg\n :target: https://badge.fury.io/py/pure-func\n\nPure-func contains decorators that help writing pure functions in python.\n\nIn python it is impossible to determine if a function is pure for certain.\nEven writing a static-analysis that gets the most cases right is very hard.\nTherefore pure-func checks purity at run-time in the spirit of python.\n\nThe canonical way to use pure-func is:\n\n.. code-block:: python\n\n @gcd_lru_cache()\n @pure_check()\n def fib(x):\n if x == 0 or x == 1:\n return 1\n return fib(x - 1) + fib(x - 2)\n\n def test_fib1(x):\n with checking():\n return fib(x)\n\n @checked()\n def test_fib2(x):\n return fib(x)\n\n # production\n x = fib(30)\n\n # testing\n x = test_fib1(30)\n x = test_fib2(30)\n\n*pure_check* in check-mode will run the function with its current input and\nreturn the output, but it will also run the function against up to three past\ninputs and check if the output matches to that past output. If the function is\nstateful, it will probably fail that check and an *NotPureException* is risen.\n\nCheck-mode is enabled by *@checked()* or *with checking()*, if check-mode is\nnot enabled, pure_check will simply pass the input and output through.\n\nIf your function has discrete reoccurring input, you can use *gcd_lru_cache* as\nvery neat way to memoize_ your function. The cache will be cleared when python\ndoes garbage-collection. For more long-term cache you might consider\n*functools.lru_cache*.\n\n**IMPORTANT:** *@pure_check()*/*@pure_simpling()* have always to be the\ninnermost (closest to the function) decorator.\n\n.. _memoize: https://en.wikipedia.org/wiki/Memoization\n\nWriting pure functions works best when the input and output is immutable,\nplease consider using pyrsistent_. Memoization_ will work better with pyristent\nand using multiprocessing is a lot easier with pyrsistent_ (no more\npickling errors).\n\n.. _Memoization: https://en.wikipedia.org/wiki/Memoization\n\n.. _pyrsistent: https://pyrsistent.readthedocs.io/en/latest/\n\n*pure_sampling* allows to run pure_check in production by calling the checked\nfunction exponentially less frequent over time. Note that *pure_sampling* will\nwrap the function in *pure_check* so you should **not** use both decorators.\nAlso if check-mode is enabled *pure_sampling* will always check the function\njust like *pure_check*.\n\n**Nice fact:** *with checking*/*@checked()* will enable the check-mode for all\nfunctions even functions that are called by other functions. So you check your\nwhole program, which means if functions influence each other you will probably\ncatch that.\n\n@pure_check()\n=============\n\nCheck if the function has no side-effects during unit-tests.\n\nIf check-mode is enabled using *@checked()* or *with checking()* the\nfunction decorated with *@pure_check()* will be checked for purity.\n\nFirst the function will be executed as normal. Then the function will be\nexecuted against up to three (if available) past inputs in random order.\nDuring these checks the function is guarded against recursive checks: If\nthe function is called recursively it will be executed as normal without\nchecks.\n\nIf a check fails *NotPureException* is raised.\n\nIn the end result of the first (normal) execution is returned.\n\n@gcd_lru_cache(maxsize=128, typed=False)\n========================================\n\nGarbage-collected least-recently-used-cache.\n\nIf *maxsize* is set to None, the LRU features are disabled and the cache\ncan grow without bound.\n\nIf *typed* is True, arguments of different types will be cached separately.\nFor example, f(3.0) and f(3) will be treated as distinct calls with\ndistinct results.\n\nThe cache is cleared before garbage-collection is run.\n\nArguments to the cached function must be hashable.\n\nView the cache statistics named tuple (hits, misses, maxsize, currsize)\nwith f.cache_info(). Clear the cache and statistics with f.cache_clear().\nAccess the underlying function with f.__wrapped__.\n\nSee: Wikipedia_\n\n.. _Wikipedia: http://en.wikipedia.org/wiki/Cache_algorithms#Least_Recently_Used # noqa\n\nTypically gcd_lru_cache is good in tight loops and *functools.lru_cache*\nshould be used for periodical- or IO-tasks.\n\n@pure_sampling(base=2)\n======================\n\nCheck if the function has no side-effects using sampling.\n\nIt allows to run *pure_check* in production by calling the checked function\nexponentially less over time.\n\nThe distance between checks is *base* to the power of *checks* in function\ncalls. Assuming *base=2* on third check it will be check again after 8\ncalls. So it will take exponentially longer after every check for the next\ncheck to occur. It raises *NotPureException* if impurity has been detected.\n\nIf *base=1* the function is always checked.\n\nIf check-mode is enabled the function is always checked.\n\nwith checking()\n===============\n\nEnable check-mode (Context).\n\nAny functions with decorators *@pure_check()* or *@pure_sampling()* will\nalways be checked. Use this in unit-tests to enable checking. Nesting\n*checking*/*checked* works fine.\n\n@checked()\n==========\n\nEnable check-mode (Decorator).\n\nAny functions with decorators *@pure_check()* or *@pure_sampling()* will\nalways be checked. Use this in unit-tests to enable checking. Nesting\n*checking*/*checked* works fine.\n\nPerformance\n===========\n\n.. code-block:: text\n\n Plain fibonacci(20): 10946 (took 0.00353 seconds)\n Fibonacci(20) with pure_check (direct): 10946 (took 0.01075 seconds)\n Fibonacci(20) with pure_check (checked): 10946 (took 0.46707 seconds)\n Fibonacci(20) with pure_sampling: 10946 (took 0.05350 seconds)\n Fibonacci(20) with pure_sampling(base=1): 10946 (took 0.75588 seconds)\n Fibonacci(20) with pure_sampling (checked): 10946 (took 0.83311 seconds)\n Plain fibonacci(30): 1346269 (took 0.43068 seconds)\n Fibonacci(30) composed (direct): 1346269 (took 0.00004 seconds)\n Fibonacci(30) composed (checked): 1346269 (took 0.00001 seconds)\n Fibonacci(30) with gcd_lru_cache: 1346269 (took 0.00002 seconds)\n Plain expansive fibonacci(8): 34 (took 0.68938 seconds)\n Expansive fibonacci(8) with pure_check: 34 (took 0.68841 seconds)\n Expansive fibonacci(8) with pure_check (checked): 34 (took 9.47059 seconds)\n Expansive fibonacci(8) with pure_sampling: 34 (took 1.34284 seconds)\n Expansive fibonacci(8) with pure_sampling (checked): 34 (took 8.50167 seconds)\n Plain mergesort (took 1.60277 seconds)\n Mergesort with pure_check (direct) (took 1.60405 seconds)\n Mergesort with pure_check (checked) (took 8.65274 seconds)\n Mergesort with pure_sampling (took 2.45293 seconds)\n\nNote that the fibonacci function is very short, please compare to the expansive\nfibonacci tests.\n\nLicense\n=======\n\nMIT\n\nChangelog\n=========\n\n1.2 - 2017-04-19\n----------------\n\n* Fix setup.py to point to the correct homepage (@lucaswiman)\n\n* Fix @pure_sampling(base=1) not checking at all\n", "description_content_type": null, "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "http://github.com/adfinis-sygroup/pure_func", "keywords": "pure functional programming unit-testing", "license": "", "maintainer": "", "maintainer_email": "", "name": "pure-func", "package_url": "https://pypi.org/project/pure-func/", "platform": "", "project_url": "https://pypi.org/project/pure-func/", "project_urls": { "Homepage": "http://github.com/adfinis-sygroup/pure_func" }, "release_url": "https://pypi.org/project/pure-func/1.2/", "requires_dist": null, "requires_python": "", "summary": "Pure-func helps to write pure functions in python", "version": "1.2" }, "last_serial": 3798534, "releases": { "1.0": [ { "comment_text": "", "digests": { "md5": "a970b68a062a1b20ed078fd3e4354db7", "sha256": "bdaee62a983b19afc7e74cae5542a7258326504a6dfd18c56dcade15fe2755cb" }, "downloads": -1, "filename": "pure-func-1.0.tar.gz", "has_sig": false, "md5_digest": "a970b68a062a1b20ed078fd3e4354db7", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4283, "upload_time": "2017-04-17T14:48:35", "url": "https://files.pythonhosted.org/packages/dd/3f/45adf94508c6f862169b176d2036b969eda8cbb9db82de7abb3478f13640/pure-func-1.0.tar.gz" } ], "1.1": [ { "comment_text": "", "digests": { "md5": "2c99939ad889e78427c5da1f6693321c", "sha256": "2ce0ba8ffc1c5a138029f93a38f9fbf2c4a4fd8e91c31b53f29b3565d5dfcc03" }, "downloads": -1, "filename": "pure-func-1.1.tar.gz", "has_sig": false, "md5_digest": "2c99939ad889e78427c5da1f6693321c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5708, "upload_time": "2017-04-18T15:25:02", "url": "https://files.pythonhosted.org/packages/3f/e1/06a7781f2acccba39e4b30a31d85a202948b1b2c9ad3aaa2329cd92af6a7/pure-func-1.1.tar.gz" } ], "1.2": [ { "comment_text": "", "digests": { "md5": "9a885c2c06a40200455d31f04470c00a", "sha256": "9ed528c6dfc4e3505aedb5291ea2186ca9ac512a994ad86e0c93cfa390843f97" }, "downloads": -1, "filename": "pure-func-1.2.tar.gz", "has_sig": false, "md5_digest": "9a885c2c06a40200455d31f04470c00a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5876, "upload_time": "2017-04-19T11:31:03", "url": "https://files.pythonhosted.org/packages/0b/aa/2af3fc4bfc8b2d6d4c0a7089ffc9c1e95d070fd80940023fc9bb497e506b/pure-func-1.2.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "9a885c2c06a40200455d31f04470c00a", "sha256": "9ed528c6dfc4e3505aedb5291ea2186ca9ac512a994ad86e0c93cfa390843f97" }, "downloads": -1, "filename": "pure-func-1.2.tar.gz", "has_sig": false, "md5_digest": "9a885c2c06a40200455d31f04470c00a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5876, "upload_time": "2017-04-19T11:31:03", "url": "https://files.pythonhosted.org/packages/0b/aa/2af3fc4bfc8b2d6d4c0a7089ffc9c1e95d070fd80940023fc9bb497e506b/pure-func-1.2.tar.gz" } ] }