{ "info": { "author": "Jevgeni Tarassov", "author_email": "jevgeni@tarasov.ch", "bugtrack_url": null, "classifiers": [], "description": "=======================================\r\nStrict Functions & Structures in Python\r\n=======================================\r\n\r\n``strict`` is a module, that addresses the frequent need for type checking in\r\nPython.\r\n\r\n\r\nQuick Example\r\n=============\r\n\r\nFunction Constraints\r\n--------------------\r\n\r\nAdd type constraints to the function signature::\r\n\r\n from __future__ import print_function\r\n from strict.functions import *\r\n\r\n @expects(arg(float), arg(float), message=arg(str))\r\n def multiply_and_print(a, b, message=\"You've got {result}\"):\r\n print(message.format(result=(a * b)))\r\n\r\n # This works just fine\r\n multiply_and_print(2.0, 3.0)\r\n\r\n # This raises a TypeConstraintError\r\n multiply_and_print(int(2.0), 3.0)\r\n\r\n\r\nAdd type constraint to a method::\r\n\r\n from __future__ import print_function\r\n from strict.functions import *\r\n\r\n class Foo(object):\r\n\r\n @expects(self, arg(str))\r\n def __init__(self, name):\r\n self.name = name\r\n \r\n def say_hello(self):\r\n print(\", \".join([\"Hello\", self.name]))\r\n\r\n # This works\r\n f = Foo(\"Jim\")\r\n f.say_hello()\r\n\r\n # This doesn't\r\n f = Foo(123)\r\n f.say_hello()\r\n\r\n\r\nAdd a constraint on the return value of a function::\r\n\r\n from strict.functions import *\r\n\r\n @returns(int)\r\n def return_two():\r\n return 2\r\n\r\n @returns(int)\r\n def return_half():\r\n return 0.5\r\n\r\n # This works fine\r\n return_two()\r\n\r\n # This raises an exception\r\n return_half()\r\n\r\n\r\nAdd a subject matter constraint, as well as a type constraint to a function::\r\n\r\n @expects(arg(float), arg(float, lambda x: x != 0))\r\n def divide(a, b):\r\n \"We need to make sure, that b isn't zero...\"\r\n return a / b\r\n\r\n # This works\r\n divide(4.0, 2.0)\r\n\r\n # This all fails with a TypeConstraintError\r\n divide(4, 2.0)\r\n divide(4.0, \"poop\")\r\n\r\n # This fails with a SubjectConstraintError\r\n divide(4.0, 0.0)\r\n\r\n\r\nStructures\r\n----------\r\n\r\nDefine a structure::\r\n\r\n from strict.structures import *\r\n\r\n class Point(Structure):\r\n \"\"\"\r\n Let's have a point, that can fit only on a certain area.\r\n \"\"\"\r\n x = Field(float, lambda x: 0.0 < x < 1000.0)\r\n y = Field(float, lambda y: 0.0 < y < 1000.0)\r\n\r\n def __init__(self, x, y):\r\n self.x = x\r\n self.y = y\r\n\r\n # This works\r\n a = Point(10.0, 15.0)\r\n\r\n # This all fails with the correct exception\r\n Point(10, 15)\r\n Point(10.0, 1001.0)\r\n Point(-2.0, 50.0)\r\n\r\n\r\nSerialize your structure::\r\n\r\n from strict.structures import *\r\n\r\n class Point(Structure):\r\n \"\"\"\r\n Let's have a point, that can fit only on a certain area.\r\n \"\"\"\r\n x = Field(float, lambda x: 0.0 < x < 1000.0)\r\n y = Field(float, lambda y: 0.0 < y < 1000.0)\r\n\r\n def __init__(self, x, y):\r\n self.x = x\r\n self.y = y\r\n\r\n a = Point(10.0, 15.0)\r\n\r\n # This outputs a dictionary\r\n a.to_dict()\r\n\r\n # This outputs a list\r\n a.to_list()\r\n\r\n\r\nWhy Would I Type Check?\r\n=======================\r\n\r\nAlthough, the common idiom to deal with type compatibility issues in Python is\r\nduck typing, in some cases it is not adequate.\r\n\r\nQuite often the information about the *usage context* is implicitly encoded in\r\nthe class name, which duck typing would usually fail to handle, unless you\r\nintroduce wildly differing class interfaces or just kludge.\r\n\r\nConsider the following class tree of a financial application::\r\n\r\n +--------------------------+ \r\n | | \r\n | BaseVolatilitySurface | \r\n | | \r\n +-------------+------------+ \r\n | \r\n | \r\n | \r\n | \r\n +---------------------------+ | +-------------------------+\r\n | | | | |\r\n | EquityVolatilitySurface <-----+-----> RateVolatilitySurface |\r\n | | | |\r\n +---------------------------+ +-------------------------+\r\n\r\nVolatility of some value (usually of an asset price) is the key input of\r\nvaluation models for financial derivatives. In this case, we try to model in our\r\napplication the volatility of equity and interest rates, implied by market\r\nprices.\r\n\r\nBoth classes would have mostly the same interface. If we rely on duck typing and\r\naccidentaly pass a ``RateVolatilitySurface`` to value an equity option, no\r\nexception would be raised, since **techically** the input would satisfy the\r\nconstraint expressed through duck typing. However, the result would be wrong and\r\nwe'd get a typical example of a SH*T IN, SH*T OUT program.\r\n\r\nThe obvious solution is to sprinkle your code with a liberal amount of\r\n``isinstance`` checks. This, however, quickly leads to your business code being\r\ndominated by boilerplate checks and error handling. To avoid this I tried to put\r\nthe most useful and simple patterns in a module:\r\n\r\n- Assigning constraints to function arguments and return values \r\n- Creating a class with strict type checking of its properties and the correctly \r\n filled ``__slots__`` variable.\r\n\r\n\r\n2014, Jevgeni Tarasov (jevgeni@tarasov.ch)", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://bitbucket.org/slenderboy/strict", "keywords": null, "license": "MIT", "maintainer": null, "maintainer_email": null, "name": "strict", "package_url": "https://pypi.org/project/strict/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/strict/", "project_urls": { "Download": "UNKNOWN", "Homepage": "https://bitbucket.org/slenderboy/strict" }, "release_url": "https://pypi.org/project/strict/0.1alpha/", "requires_dist": null, "requires_python": null, "summary": "Type and subject matter checks for functions and classes.", "version": "0.1alpha" }, "last_serial": 1187007, "releases": { "0.1alpha": [ { "comment_text": "", "digests": { "md5": "db97084a405b90413fe3c77d6506e821", "sha256": "caad92ee5f9e825c5d9e0d0eab4b14051efa867987eefc44e52964337ccad1d4" }, "downloads": -1, "filename": "strict-0.1alpha.tar.gz", "has_sig": false, "md5_digest": "db97084a405b90413fe3c77d6506e821", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7442, "upload_time": "2014-08-11T21:57:00", "url": "https://files.pythonhosted.org/packages/1a/47/9e66c2e593abfce27dff7d97b593c7b9c55d37bcd5a02458553f1763ef59/strict-0.1alpha.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "db97084a405b90413fe3c77d6506e821", "sha256": "caad92ee5f9e825c5d9e0d0eab4b14051efa867987eefc44e52964337ccad1d4" }, "downloads": -1, "filename": "strict-0.1alpha.tar.gz", "has_sig": false, "md5_digest": "db97084a405b90413fe3c77d6506e821", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7442, "upload_time": "2014-08-11T21:57:00", "url": "https://files.pythonhosted.org/packages/1a/47/9e66c2e593abfce27dff7d97b593c7b9c55d37bcd5a02458553f1763ef59/strict-0.1alpha.tar.gz" } ] }