{ "info": { "author": "Nathan Wilcox", "author_email": "nejucomo@gmail.com", "bugtrack_url": null, "classifiers": [], "description": "=============\npreconditions\n=============\n\n``preconditions`` - A precondition decorator utility which relies on\n`parameter-name equivalence` for conciseness and consistency.\n\nExamples\n========\n\nFirst let's take a tour of examples. All examples assume the\n``preconditions`` decorator has been imported:\n\n.. code:: python\n\n from preconditions import preconditions\n\nBasic type checking\n-------------------\n\nThe ``double`` `application function` requires that the ``i`` parameter\nis an ``int``, which is verified by a single `predicate` (the ``lambda``\nexpression):\n\n.. code:: python\n\n @preconditions(lambda i: isinstance(i, int))\n def double(i):\n return 2*i\n\nMultiple predicates\n-------------------\n\nMultiple predicates may be specified:\n\n.. code:: python\n\n @preconditions(\n lambda i: isinstance(i, int),\n lambda i: i > 0,\n )\n def double(i):\n return 2*i\n\nNote that this is functionally equivalent to this single predicate\nversion:\n\n.. code:: python\n\n @preconditions(\n lambda i: isinstance(i, int) and i > 0,\n )\n def double(i):\n return 2*i\n\nThe multi-predicate version should (eventually) have more specific\nerror reporting for a failure, while the single predicate version may\nbe more efficient.\n\nMultiple arguments\n------------------\n\nMultiple predicates can express preconditions for multiple arguments:\n\n.. code:: python\n\n @preconditions(\n lambda s: isinstance(s, unicode),\n lambda n: isinstance(n, int) and n >= 0,\n )\n def repeat(s, n):\n return s*n\n\nHowever, a *single predicate* can express preconditions for multiple\narguments. This allows `relational preconditions`:\n\n.. code:: python\n\n @preconditions(\n lambda a, b: a <= b\n )\n def strict_range(a, b):\n return range(a, b)\n\nMethod preconditions\n--------------------\n\nPredicates can be expressed for methods, including relations to\n``self``. For example, a ``Monotonic`` instance ensures that each call to\n``.set`` must pass a value larger than any previous call:\n\n.. code:: python\n\n class Monotonic (object):\n def __init__(self):\n self.v = 0\n\n @preconditions(lambda self, v: v > self.v)\n def set(self, v):\n self.v = v\n\nPreconditions can be applied to special methods, such as ``__new__``,\n``__init__``, ``__call__``, etc...\n\n.. code:: python\n\n class LinearRange (tuple):\n @preconditions(\n lambda a: isinstance(a, float),\n lambda b: isinstance(b, float),\n lambda a, b: a < b,\n )\n def __new__(cls, a, b):\n return super(OrderedTuple, cls).__new__(cls, (a, b))\n\n @preconditions(lambda w: 0 <= w < 1.0)\n def __call__(self, w):\n lo, hi = self\n return w * (hi - lo) + lo\n\n @preconditions(lambda x: self[0] <= x < self[1])\n def invert(self, x):\n lo, hi = self\n return (x - lo) / (hi - lo)\n\nConcepts\n========\n\nAn `application function` may be guarded with `precondition\npredicates`. These `predicates` are callables passed to the\n``preconditions`` decorator. Consider this code:\n\n.. code:: python\n\n @preconditions(\n lambda a: isinstance(a, float) and a >= 0,\n lambda b: isinstance(b, float) and b >= 0,\n )\n def area(a, b):\n return a*b\n\nThe application function is ``area``, and it has two predicates defined\nwith ``lambda``, each of which ensures one of the arguments is a\nnon-negative float.\n\nParameter Name Equivalence\n--------------------------\n\nThe parameter names in a predicate must match parameter names in\nthe application function. This is known as `parameter name equivalence`\n[#]_.\n\n.. [#] This is a bit magical, relying on function introspection. The\n design assumes the conciseness and consistency benefits outweigh\n the potential confusion of \"magic\".\n\nOne exception to this rule is for default parameters within\npredicates. Default parameters may be used to associate some state at\npredicate definition time. For example:\n\n.. code:: python\n\n scores = {}\n\n @preconditions(\n lambda color, _colors=['RED', 'GREEN', 'BLUE']: color in _colors\n )\n def get_color_score(color):\n return scores[color]\n\nThis feature may be most convenient when there's a need to remember a\nlocal loop variable.\n\n.. FIXME: create an example.\n\nSimilar Projects\n================\n\n`covenant`_ - Code contracts for Python 3.\n\n.. _`covenant`: https://github.com/kisielk/covenant\n\n", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/nejucomo/preconditions", "keywords": null, "license": "MIT", "maintainer": null, "maintainer_email": null, "name": "preconditions", "package_url": "https://pypi.org/project/preconditions/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/preconditions/", "project_urls": { "Download": "UNKNOWN", "Homepage": "https://github.com/nejucomo/preconditions" }, "release_url": "https://pypi.org/project/preconditions/0.1/", "requires_dist": null, "requires_python": null, "summary": "Flexible, concise preconditions.", "version": "0.1" }, "last_serial": 1538162, "releases": { "0.1": [ { "comment_text": "", "digests": { "md5": "c61bf4e2f5052ea8ff6903fa656a2e23", "sha256": "e783f97bee1e3302745a67575ce788fc98874968e1c9343b7e0cdfd5d4c13527" }, "downloads": -1, "filename": "preconditions-0.1.tar.gz", "has_sig": true, "md5_digest": "c61bf4e2f5052ea8ff6903fa656a2e23", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5242, "upload_time": "2015-05-08T00:47:04", "url": "https://files.pythonhosted.org/packages/5d/19/324c00d1399e5997c25d49ece9f9f68868621f06ea1f553671229d28601d/preconditions-0.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "c61bf4e2f5052ea8ff6903fa656a2e23", "sha256": "e783f97bee1e3302745a67575ce788fc98874968e1c9343b7e0cdfd5d4c13527" }, "downloads": -1, "filename": "preconditions-0.1.tar.gz", "has_sig": true, "md5_digest": "c61bf4e2f5052ea8ff6903fa656a2e23", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5242, "upload_time": "2015-05-08T00:47:04", "url": "https://files.pythonhosted.org/packages/5d/19/324c00d1399e5997c25d49ece9f9f68868621f06ea1f553671229d28601d/preconditions-0.1.tar.gz" } ] }