{ "info": { "author": "Rodney Gomes", "author_email": "rodneygomes@gmail.com", "bugtrack_url": null, "classifiers": [], "description": "Contracts For Python\n--------------------\n\nThis library is a very simple and straightforward way of implementing contracts\nin python using decorators. I did have a look at a few other contract libraries \nand found that they were either not very pythonic or decided to use strings to \nencode the contract logic which makes it horrible to debug or even write your \ncontracts cleanly.\n\nIn the hopes of creating something better I've created this library to see if\nothers find it useful. \n\nInstallation\n------------\n\n> sudo python setup.py install\n\nWill install the contracts library which you can then import with the usual \n'import contracts' and start using the contracts library immediately.\n\nor install directly from github with:\n\npip install -e git+git://github.com/rlgomes/contracts.git#egg=contracts\n\nUsage\n-----\n\nFunction Decorators\n-------------------\n\n@post\n-----\n\nThe post decorator will validate whatever you want to validate after the \nexecution of the decorated function and the contract library will pass the \nreturn value of the decorated function as your first argument. You can then \nchoose to do any required validation to the result of that function or check \nany other global variable state of importance.\n\nExample: return constraint check\n--------------------------------\n \n@post(lambda x: x > 0,\"return is not a positive number\")\ndef bad_abs(a):\n return a\n \nThe previous function is a bad implementation of the abs function and with the \npost contract that checks the return to be positive we can easily catch that \nwhen we call the function with -2 as an argument this is what we'd see:\n \n>>> bad_abs(-2) Traceback (most recent call last): File \"\", line 1, in \n File \"contracts.py\", line 35, in new_f\n assert function(result), message\nAssertionError: return is not a positive number\n\n@pre\n----\n\nThe pre decorator will validate whatever you want to validate befor the \nexecution of the decorated function and the contract library will pass the \nexact arguments that are about to be passed to the decorated function before \nexecuting that.\n\nExample: argument validation\n\n@pre(lambda _,y: len(y) > 0)\ndef find_element(elem,list):\n ...\n \nThe above example shows you can guarantee your function is never called with a\nlist that has zero elements.\n\nClass Decorators\n----------------\n\n@inv\n----\n\nThe invariant decorator will validate that the contract you want is always \nvalidated for every interaction with any instance of the class you just decorated.\nBasically the framework is able to hijack all of the methods, constructors, etc \nin a way that makes sure that every change to the object is validated before and\nafter the change to not be in violation of the contract specified.\n\n@inv(lambda obj: obj.visitors >= 0)\nclass VistorTracker(object):\n \n # if not set the pre condition will fail at initialization phase because\n # the attribute visitors doesn't exist at that time if removed from this \n # line \n visitors = 0\n \n def __init__(self):\n self.visitors = 0\n \n def leave(self):\n self.visitors=self.visitors-1\n\n def visit(self): \n self.visitors=self.visitors+1\n \n \nNow basically the class VisitorTracker is constantly being checked whenever any\nmethod is called on the class or variable is modified the invariant contract \nchecks that the number of visitors is superior to 0 and that there haven't\nbeen more leave() method calls executed then visit() methods called.", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "UNKNOWN", "keywords": "contracts", "license": "Apache 2.0 License", "maintainer": null, "maintainer_email": null, "name": "contracts", "package_url": "https://pypi.org/project/contracts/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/contracts/", "project_urls": { "Download": "UNKNOWN", "Homepage": "UNKNOWN" }, "release_url": "https://pypi.org/project/contracts/0.1.0/", "requires_dist": null, "requires_python": null, "summary": "UNKNOWN", "version": "0.1.0" }, "last_serial": 749380, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "60a9db0d8d84f457d76b17fb4c0c2f25", "sha256": "f5b6aa18a2a51216758caf5fc179769fe8947b54dbcda01c641d2f956c13a779" }, "downloads": -1, "filename": "contracts-0.1.0.tar.gz", "has_sig": false, "md5_digest": "60a9db0d8d84f457d76b17fb4c0c2f25", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 3512, "upload_time": "2013-05-25T04:27:21", "url": "https://files.pythonhosted.org/packages/4c/89/b924c4591c2aa21358b650d45f5fc09ca399075ae259a4c88be8ab131ec9/contracts-0.1.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "60a9db0d8d84f457d76b17fb4c0c2f25", "sha256": "f5b6aa18a2a51216758caf5fc179769fe8947b54dbcda01c641d2f956c13a779" }, "downloads": -1, "filename": "contracts-0.1.0.tar.gz", "has_sig": false, "md5_digest": "60a9db0d8d84f457d76b17fb4c0c2f25", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 3512, "upload_time": "2013-05-25T04:27:21", "url": "https://files.pythonhosted.org/packages/4c/89/b924c4591c2aa21358b650d45f5fc09ca399075ae259a4c88be8ab131ec9/contracts-0.1.0.tar.gz" } ] }