{ "info": { "author": "Zach Kelling", "author_email": "zk@monoid.io", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4" ], "description": "=======\nDecorum\n=======\n\n.. image:: https://travis-ci.org/zeekay/decorum.png?branch=master\n :target: https://travis-ci.org/zeekay/decorum\n\nDecorum is a library which aims to make it easier to write flexible and simple\ndecorators:\n\n* use decorators just like you need: don't bother with parentheses, pass\n options when you need them.\n\n* write decorators just like you think: they get initialized with or without\n options, they wrap a function, they are callables.\n\n* test decorators: it's really easy, you have no excuse!\n\n\nInherit from Decorum\n====================\n\nIn order to write your own decorators, just subclass ``decorum.Decorum``:\n\n.. code:: pycon\n\n >>> from decorum import Decorum\n\n >>> class empty_decorator(Decorum):\n ... \"\"\"Just inherit from Decorum's builtins.\"\"\"\n\nOf course you will want to customize decorator's behaviour! There are only\nthree methods to be aware of:\n\n* ``init()`` setups the decorator itself;\n\n* ``wraps()`` decorates the function;\n\n* ``call()`` runs the wrapped function and returns result.\n\nHere is a simple decorator to illustrate Decorum usage:\n\n.. code:: pycon\n\n >>> from __future__ import print_function\n\n >>> class verbose_decorator(Decorum):\n ... \"\"\"Print info about decoration process.\"\"\"\n ... def init(self, *args, **kwargs):\n ... print('Initializing decorator with args={} and kwargs={}'\n ... .format(args, kwargs))\n ... return super(verbose_decorator, self).init(*args, **kwargs)\n ...\n ... def wraps(self, f):\n ... print('Wrapping function \"{}\"'.format(f.__name__))\n ... return super(verbose_decorator, self).wraps(f)\n ...\n ... def call(self, *args, **kwargs):\n ... print('Running wrapped function with args={} and kwargs={}'\n ... .format(args, kwargs))\n ... return super(verbose_decorator, self).call(*args, **kwargs)\n\nThen you can use it as any decorator:\n\n.. code:: pycon\n\n >>> @verbose_decorator\n ... def foo(x):\n ... print(x)\n Initializing decorator with args=() and kwargs={}\n Wrapping function \"foo\"\n\n >>> foo('bar')\n Running wrapped function with args=('bar',) and kwargs={}\n bar\n\n.. note::\n\n You can also use ``decorum.decorator`` to turn classes into decorators.\n\n .. code:: pycon\n\n >>> from decorum import decorator\n\n >>> @decorator\n ... class noop:\n ... \"\"\"Override init(), wraps() or call() if you like.\"\"\"\n\n >>> @noop\n ... def foo():\n ... \"\"\"Do nothing.\"\"\"\n\n The result is a class that inherits from the original class and Decorum:\n\n .. code:: pycon\n\n >>> isinstance(foo, noop)\n True\n >>> isinstance(foo, Decorum)\n True\n\n\nDon't bother with parentheses\n=============================\n\nDecorum lets you write decorators with and without arguments in a unified way.\nThen your decorator can be used with or without arguments, called or not, and\nit will work the same way:\n\n.. code:: pycon\n\n >>> @verbose_decorator\n ... def foo(x):\n ... print(x)\n Initializing decorator with args=() and kwargs={}\n Wrapping function \"foo\"\n\nIs identical to:\n\n.. code:: pycon\n\n >>> @verbose_decorator()\n ... def foo(x):\n ... print(x)\n Initializing decorator with args=() and kwargs={}\n Wrapping function \"foo\"\n\n\nInitialize decorator with options\n=================================\n\nTo implement a decorator that accepts a custom options, just change ``init()``:\n\n.. code:: pycon\n\n >>> class configurable_decorator(Decorum):\n ... def init(self, custom_option='default', *args, **kwargs):\n ... print('Initializing decorator with custom_option=\"{}\"'\n ... .format(custom_option))\n ... # Remember the option, typically for use in wraps() or call().\n ... self.custom_option = custom_option\n ... # Call super().init() with remaining arguments.\n ... return super(configurable_decorator, self).init(*args, **kwargs)\n\nAs we used a keyword argument, it is optional:\n\n.. code:: pycon\n\n >>> @configurable_decorator\n ... def foo(x):\n ... print(x)\n Initializing decorator with custom_option=\"default\"\n\n >>> foo.custom_option\n 'default'\n\nAnd we can pass this option when decorating a function. Either as positional\nargument...\n\n.. code:: pycon\n\n >>> @configurable_decorator('positional')\n ... def foo(x):\n ... print(x)\n Initializing decorator with custom_option=\"positional\"\n\n >>> foo.custom_option\n 'positional'\n\n... or keyword argument:\n\n.. code:: pycon\n\n >>> @configurable_decorator(custom_option='keyword')\n ... def foo(x):\n ... print(x)\n Initializing decorator with custom_option=\"keyword\"\n\n >>> foo.custom_option\n 'keyword'\n\nOf course, you cannot pass arguments that are not declared as ``init()``\noptions:\n\n.. code:: pycon\n\n >>> @configurable_decorator(wrong_option=True) #\u00a0doctest: +ELLIPSIS\n ... def foo(x):\n ... print(x)\n Traceback (most recent call last):\n ...\n TypeError: init() got an unexpected keyword argument 'wrong_option'\n\n.. note::\n\n In most cases, ``init()`` should accept additional arguments and and proxy\n them to parent via ``super(...).init(*args, **kwargs)``. This way, options\n of ancestor classes are supported.\n\n As an example, ``Decorum`` base class declares ``assigned`` keyword argument\n in ``init()`` (see section `wrap function <#wrap-function>`_ below).\n\n\nWrap function\n=============\n\nThe ``wraps()`` method allows you to handle the decorated function. It receives\nthe function to decorate as single positional argument, and returns a callable\n(typically ``self``).\n\nIn most cases, ``wraps()`` function will ``return super(..., self).wraps(f)``.\n\nBy default, the base ``Decorum.wraps()`` will try to keep assign certain\nattributes to the wrapped function for you, namely ``__doc__`` and\n``__name__``. This feature uses ``functools.wraps``.\n\n.. code:: pycon\n\n >>> class identity(Decorum):\n ... \"\"\"Noop decorator: does nothing!\"\"\"\n\n >>> @identity\n ... def my_function():\n ... \"\"\"My function's docstring.\"\"\"\n\n >>> print(my_function.__name__)\n my_function\n >>> print(my_function.__doc__)\n My function's docstring.\n\nThe optional ``assigned`` keyword argument can be used to specify which\nattributes of the original function are assigned directly to the matching\nattributes on the wrapper function. This defaults to\n``functools.WRAPPER_ASSIGNMENTS``. You can specify ``False`` or ``None`` to\ndisable this.\n\n.. code:: pycon\n\n >>> @identity(assigned=None)\n ... def my_function():\n ... \"\"\"My function's docstring.\"\"\"\n\n >>> print(my_function.__name__)\n identity\n >>> print(my_function.__doc__)\n Noop decorator: does nothing!\n\n\nRun decorated function\n======================\n\n``Decorum.call()`` method receives ``*args`` and ``**kwargs`` as input. It runs\nthe wrapped function, and returns the result.\n\nHere is a simple decorator that repeats the result of decorated function:\n\n.. code:: pycon\n\n >>> class repeat(Decorum):\n ... def call(self, *args, **kwargs):\n ... result = super(repeat, self).call(*args, **kwargs)\n ... return ' '.join([result] * 2)\n\n >>> @repeat\n ... def parrot(word):\n ... return word\n\n >>> parrot('hello')\n 'hello hello'\n\n\nTest decorators\n===============\n\nDecorum makes it easy to test custom decorators.\n\nAssert a decorator has expected behaviour\n-----------------------------------------\n\nDecorators are defined as classes, so you have fine-grained control over what\nyou test. And your tests can focus on what you customized.\n\nLet's check ``repeat`` decorator from the section before. Since we just\noverrode ``call()``, let's focus on it:\n\n.. code:: pycon\n\n >>> decorator = repeat(lambda x: x.upper())\n\n >>> result = decorator.call('input')\n >>> assert result == 'INPUT INPUT'\n\nThat's quite useful to unit test decorators.\n\n\nAssert a function has been decorated\n------------------------------------\n\nDecorators are instances of ``Decorum`` or subclasses. So you can inspect\ndecorated functions.\n\nLet's inspect ``my_function`` from the examples above:\n\n.. code:: pycon\n\n >>> assert isinstance(my_function, Decorum)\n >>> assert isinstance(my_function, identity)\n\n\nKnown limitations\n=================\n\nDecorum has little known limitations:\n\n* your decorator's ``init()`` cannot receive a single positional argument that\n is a callable. Decorum will try trigger ``wraps()`` instead of ``init()`` in\n such a case.\n\n\nAbout\n=====\n\nDecorum project is free software, published under MIT license.\n\n* PyPI: https://pypi.python.org/pypi/Decorum\n* Code repository: https://github.com/zeekay/decorum\n* Bugtracker: https://github.com/zeekay/decorum/issues\n* Continuous integration: https://travis-ci.org/zeekay/decorum", "description_content_type": null, "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://pypi.python.org/pypi/Decorum", "keywords": "decorator decorators", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "Decorum", "package_url": "https://pypi.org/project/Decorum/", "platform": "", "project_url": "https://pypi.org/project/Decorum/", "project_urls": { "Homepage": "https://pypi.python.org/pypi/Decorum" }, "release_url": "https://pypi.org/project/Decorum/1.0.3/", "requires_dist": null, "requires_python": "", "summary": "Tool for writing simple decorators.", "version": "1.0.3" }, "last_serial": 2745209, "releases": { "0.1": [ { "comment_text": "", "digests": { "md5": "21ea288e0c1575d5eb2323e9a017897d", "sha256": "aaa2ff347f0f230bf068f438107464e76d53906a2d5ca02ad40b2119aeed9f10" }, "downloads": -1, "filename": "Decorum-0.1.tar.gz", "has_sig": false, "md5_digest": "21ea288e0c1575d5eb2323e9a017897d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 1383, "upload_time": "2011-05-13T22:23:10", "url": "https://files.pythonhosted.org/packages/62/82/a013ebba9b9546281252dac6aaf4c36de8df837a681e421b9bb8acc0e7f8/Decorum-0.1.tar.gz" } ], "0.2": [ { "comment_text": "", "digests": { "md5": "25cbe5dc1153c624279b9e137e08aa3b", "sha256": "eb75ed12f53a6d6bd486269981b7729b243f896b9e777b3e480bdfca66e060f2" }, "downloads": -1, "filename": "Decorum-0.2.tar.gz", "has_sig": false, "md5_digest": "25cbe5dc1153c624279b9e137e08aa3b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 1445, "upload_time": "2011-05-14T00:02:56", "url": "https://files.pythonhosted.org/packages/ae/81/ed203cbafe4b2c5ebf92f495e89058082a01a82f5d33aaa1cb0d5d2587bb/Decorum-0.2.tar.gz" } ], "0.3": [ { "comment_text": "", "digests": { "md5": "0e766199503505aeabf810c47be99983", "sha256": "0a6234369325f3b20d13283837e1ad9352a48c19a636e7c2a79cb358a9cc8894" }, "downloads": -1, "filename": "Decorum-0.3.tar.gz", "has_sig": false, "md5_digest": "0e766199503505aeabf810c47be99983", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 1528, "upload_time": "2011-05-14T00:43:06", "url": "https://files.pythonhosted.org/packages/e8/f0/a4089eedf9aceb302d0ec878ea5fa2bc9ebaefc218054f391dfa74fec2c1/Decorum-0.3.tar.gz" } ], "0.4": [ { "comment_text": "", "digests": { "md5": "581f91db0a2581e671b401390f2f0934", "sha256": "f7e0a30e088bbc16f00763e51b5fdaa591dd3c7105af8280e380377e4e005a5a" }, "downloads": -1, "filename": "Decorum-0.4.tar.gz", "has_sig": false, "md5_digest": "581f91db0a2581e671b401390f2f0934", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 2061, "upload_time": "2011-05-14T01:15:27", "url": "https://files.pythonhosted.org/packages/94/e3/2d4b41430ecee2241a03342523f30cf798c26853caeb9a33f0796e8fab15/Decorum-0.4.tar.gz" } ], "0.4.1": [ { "comment_text": "", "digests": { "md5": "cb61fc898b982ce9040afda1b2b37be7", "sha256": "4c33892acde6d2f0cb24c47f0738a8d03361a458ddf7a1209b1ee0c05045d5cf" }, "downloads": -1, "filename": "Decorum-0.4.1.tar.gz", "has_sig": false, "md5_digest": "cb61fc898b982ce9040afda1b2b37be7", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 2059, "upload_time": "2011-05-14T01:21:34", "url": "https://files.pythonhosted.org/packages/1c/61/ee9bf4bc89cd21805c447edccfffab598b6e9f66d45fbb5bbe0ff44648be/Decorum-0.4.1.tar.gz" } ], "0.4.2": [ { "comment_text": "", "digests": { "md5": "c2d077f862314a36308b034994703ba3", "sha256": "c5898c4c7df2e9ce2d461f22b57002eff82d41be21e2f480d1a47f4fe8aa83f8" }, "downloads": -1, "filename": "Decorum-0.4.2.tar.gz", "has_sig": false, "md5_digest": "c2d077f862314a36308b034994703ba3", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 1895, "upload_time": "2014-09-12T09:15:09", "url": "https://files.pythonhosted.org/packages/fe/4a/4d0d56950fb307ec6d99f6ba552e45fb0d24b92539cb815a15ad067d6a35/Decorum-0.4.2.tar.gz" } ], "0.4.3": [ { "comment_text": "", "digests": { "md5": "8ec666039dc6f3bd23266aaf01a0997e", "sha256": "948042eebb4eca83344f9c84b53920433fcbca4735113fe980fa90f110b9e886" }, "downloads": -1, "filename": "Decorum-0.4.3.tar.gz", "has_sig": false, "md5_digest": "8ec666039dc6f3bd23266aaf01a0997e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 2799, "upload_time": "2014-09-12T09:24:24", "url": "https://files.pythonhosted.org/packages/d9/b7/eb4c56bb43ff65167f87c434b3b09e43ec7ca9e5f9df9282526238dca42d/Decorum-0.4.3.tar.gz" } ], "0.4.4": [ { "comment_text": "", "digests": { "md5": "19c82572bb58ab9d78da51ccbdb027cb", "sha256": "671dd7871f6f3675fac8342e5639f91db5dcc563767613592012cb4c8c93ea53" }, "downloads": -1, "filename": "Decorum-0.4.4.tar.gz", "has_sig": false, "md5_digest": "19c82572bb58ab9d78da51ccbdb027cb", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 2820, "upload_time": "2014-09-15T21:05:35", "url": "https://files.pythonhosted.org/packages/1f/c0/35e49b3bb69417a155ffd65d5a278942e6c41016807c47d971fb113881d9/Decorum-0.4.4.tar.gz" } ], "0.4.5": [ { "comment_text": "", "digests": { "md5": "87bd2745c68e0150dd60d7dd1c2dbf46", "sha256": "13970087138f172ed6018f4885c2760913be64846d8d00d302c59200a6156525" }, "downloads": -1, "filename": "Decorum-0.4.5.tar.gz", "has_sig": false, "md5_digest": "87bd2745c68e0150dd60d7dd1c2dbf46", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 2995, "upload_time": "2014-09-15T21:45:23", "url": "https://files.pythonhosted.org/packages/19/c8/85d9b4a250c15512c2b8b02dbd659c9e02f80525eb48c20d71268cc98ea6/Decorum-0.4.5.tar.gz" } ], "0.5.0": [ { "comment_text": "", "digests": { "md5": "2b2144967f9a5461fdac68fbaaf67e46", "sha256": "a4b5dcf150df073a0ca8f14a8af9a52be25e05288c4998dd0443d1457716973e" }, "downloads": -1, "filename": "Decorum-0.5.0.tar.gz", "has_sig": false, "md5_digest": "2b2144967f9a5461fdac68fbaaf67e46", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 3335, "upload_time": "2014-09-26T07:22:00", "url": "https://files.pythonhosted.org/packages/d0/ee/640d6c55232b090d25d0bb6b6f4a9d2440ea7ac369d8f318dcd34c6b5227/Decorum-0.5.0.tar.gz" } ], "0.5.1": [ { "comment_text": "", "digests": { "md5": "dc5be706b5ebca38158d1ce85ab56c8c", "sha256": "8f94d4a49893301bd5bab66ca80fb6cbf20752618d1fb1bd1269f1d042aa38ce" }, "downloads": -1, "filename": "Decorum-0.5.1.tar.gz", "has_sig": false, "md5_digest": "dc5be706b5ebca38158d1ce85ab56c8c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 3421, "upload_time": "2014-10-25T19:43:08", "url": "https://files.pythonhosted.org/packages/e9/6b/5af30f6e5a1a8a5b6478de73ca02731aec3b0dce12950b200168148f113e/Decorum-0.5.1.tar.gz" } ], "0.5.2": [ { "comment_text": "", "digests": { "md5": "bae7d4428b107041f7743087f0d025b2", "sha256": "37edb73dbc418135de6eac0ecfbf5aa784ad483650b38edc9ceee2a3da4acc74" }, "downloads": -1, "filename": "Decorum-0.5.2.tar.gz", "has_sig": false, "md5_digest": "bae7d4428b107041f7743087f0d025b2", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5690, "upload_time": "2015-08-01T20:56:02", "url": "https://files.pythonhosted.org/packages/73/d4/32a187b954cca271dce3ca21095413dfddc7fe0ee1cdbfcc0512c1ce3b58/Decorum-0.5.2.tar.gz" } ], "0.5.3": [ { "comment_text": "", "digests": { "md5": "4c02f79b79560ba5f37af86b4df999a2", "sha256": "08cccaea6b46187a6b09188223cd233b5b3be1cc2e271b40cac782614aacec65" }, "downloads": -1, "filename": "Decorum-0.5.3.tar.gz", "has_sig": false, "md5_digest": "4c02f79b79560ba5f37af86b4df999a2", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5720, "upload_time": "2015-08-01T21:30:14", "url": "https://files.pythonhosted.org/packages/b7/06/e5b31d662d685bf084f847c379099f6bba5071b27b8e484f6416b7af9ebd/Decorum-0.5.3.tar.gz" } ], "0.5.4": [ { "comment_text": "", "digests": { "md5": "af68bd8722b049f56cb1d3aba75d27cb", "sha256": "6d2b4dc5fe1c45229f5ca01903c11f230c6331923b2927aa95b246f22d3471f3" }, "downloads": -1, "filename": "Decorum-0.5.4.tar.gz", "has_sig": false, "md5_digest": "af68bd8722b049f56cb1d3aba75d27cb", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5996, "upload_time": "2015-08-06T13:28:49", "url": "https://files.pythonhosted.org/packages/52/fb/fcab977936c42e4e1af670a273af46d4c382f672f2aa7c9353a415f929d1/Decorum-0.5.4.tar.gz" } ], "1.0.0": [ { "comment_text": "", "digests": { "md5": "cbe42e26021c1cc377fd4e6574dc1b27", "sha256": "956aada87e8f5b38db8d1ef0584acfde9a52f37595b299779c4058aea5cc165c" }, "downloads": -1, "filename": "Decorum-1.0.0.tar.gz", "has_sig": false, "md5_digest": "cbe42e26021c1cc377fd4e6574dc1b27", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5985, "upload_time": "2015-08-06T17:36:04", "url": "https://files.pythonhosted.org/packages/54/0a/0f95c17892064f5ecfcbeef15bed9e1d7c14ac8fa9dc014867ea2563ca41/Decorum-1.0.0.tar.gz" } ], "1.0.1": [ { "comment_text": "", "digests": { "md5": "efb052b1d6673459b09a893aeed012b1", "sha256": "908cfc8a3a55bd6e67060309d41cc46deca18bc2e687f877973269146aef845b" }, "downloads": -1, "filename": "Decorum-1.0.1.tar.gz", "has_sig": false, "md5_digest": "efb052b1d6673459b09a893aeed012b1", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5981, "upload_time": "2015-08-07T16:37:32", "url": "https://files.pythonhosted.org/packages/99/0b/1106b6f19a9aff7d9d8f534ee53cb3299ad45bebfb5fa1465aacb3f07a15/Decorum-1.0.1.tar.gz" } ], "1.0.2": [ { "comment_text": "", "digests": { "md5": "0b24ff595b3e8e7edd0c8e3e8e107cb5", "sha256": "ce93e9f9ee40961862863e425dba72fbe9a33d9d90570eefae383ee826e46630" }, "downloads": -1, "filename": "Decorum-1.0.2.tar.gz", "has_sig": false, "md5_digest": "0b24ff595b3e8e7edd0c8e3e8e107cb5", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7725, "upload_time": "2015-08-10T22:02:35", "url": "https://files.pythonhosted.org/packages/f1/aa/ff5118dd3b0016ca9fb05c9168c7b812c3d1c59c05d2f00cf54327d3754d/Decorum-1.0.2.tar.gz" } ], "1.0.3": [ { "comment_text": "", "digests": { "md5": "5fdaec8bf7b64a49c4e78d4ce3c20fdd", "sha256": "a9fe77e1f55747402e46772e8d044549d7205ec42213654f766967e7ceef7197" }, "downloads": -1, "filename": "Decorum-1.0.3.tar.gz", "has_sig": false, "md5_digest": "5fdaec8bf7b64a49c4e78d4ce3c20fdd", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7752, "upload_time": "2017-04-01T02:27:23", "url": "https://files.pythonhosted.org/packages/ad/fc/1e2ca8480ed4fb46c4e53e1740a32cf9bd647fcb7f7a6bec7831391b2eeb/Decorum-1.0.3.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "5fdaec8bf7b64a49c4e78d4ce3c20fdd", "sha256": "a9fe77e1f55747402e46772e8d044549d7205ec42213654f766967e7ceef7197" }, "downloads": -1, "filename": "Decorum-1.0.3.tar.gz", "has_sig": false, "md5_digest": "5fdaec8bf7b64a49c4e78d4ce3c20fdd", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7752, "upload_time": "2017-04-01T02:27:23", "url": "https://files.pythonhosted.org/packages/ad/fc/1e2ca8480ed4fb46c4e53e1740a32cf9bd647fcb7f7a6bec7831391b2eeb/Decorum-1.0.3.tar.gz" } ] }