{ "info": { "author": "Juan Pedro Bol\u00edvar Puente", "author_email": "raskolnikov@gnu.org", "bugtrack_url": null, "classifiers": [], "description": ".. image:: https://img.shields.io/pypi/v/cooper.svg\n :target: https://pypi.python.org/pypi/cooper\n :alt: PyPI version\n\n.. image:: https://travis-ci.org/arximboldi/cooper.svg\n :target: https://travis-ci.org/arximboldi/cooper\n :alt: Build Status\n\n.. image:: https://img.shields.io/codecov/c/github/arximboldi/cooper/master.svg\n :target: http://codecov.io/github/arximboldi/cooper?branch=master\n :alt: Code Coverage\n\ncooper\n======\n\n Making super safe, a cooperative methods library\n\n.. image:: https://cdn.rawgit.com/arximboldi/cooper/master/doc/gary-cooper.png\n :align: right\n\nPython's ``super`` is a very useful tool to write cooperative methods.\nA **cooperative method** is one such that cooperates with the other\noverrides in the same hierarchy. A good example is ``__init__``, as\nall the overrides must be called in class-hierarchy ascending order to\nproperly build an object.\n\nInstallation\n------------\n\n.. code:: bash\n\n pip install cooper\n\n\nThe problem\n-----------\n\nMaking cooperative methods in linear hierarchies is simple, but that\nis not the case in the presence of multiple inheritance. The problem\nlies on the fact that the next override to be called is not known at\nclass definition time. `James Knight rant\n`_ against ``super`` makes a very clear\nexposition of the problem and proposes a methodology to use ``super``\nconsistently, if used at all.\n\nWe believe that ``super`` is very useful and many interesting and\nexpressive programming patterns arise when using horizontal\nhierarchies extensively. This library is attempt to make these safer\nand usable in large projects.\n\nExamples\n--------\n\n.. code:: python\n\n from cooper import *\n\nCooperative constructors\n````````````````````````\n\n.. code:: python\n\n class Base(Cooperative):\n @cooperate\n def __init__(self):\n print \"Base.__init__\"\n\n class Deriv(Base):\n @cooperate\n def __init__(self):\n print \"Deriv.__init__\"\n\n Deriv()\n..\n\n **Output**::\n\n Base.__init__\n Deriv.__init__\n\nAutomatic argument forwarding\n`````````````````````````````\n\n.. code:: python\n\n class Base(Cooperative):\n @cooperate\n def __init__(base_param=None)\n print \"base_param = \", base_param\n\n class Deriv(Base):\n @cooperate\n def __init__(deriv_param=None)\n print \"deriv_param = \", base_param\n\n Base(deriv_param = \"Hello\",\n base_param = \"world!\")\n..\n\n **Output:**::\n\n base_param = Hello\n deriv_param = World!\n\n\nOther methods\n`````````````\n\n.. code:: python\n\n class Entity(Cooperative):\n @cooperative\n def update(self, timer):\n print \"Entity.update\"\n\n class Player(Entity):\n @cooperate\n def update(self, timer):\n print \"Player.update\"\n\n Player().update(0)\n..\n\n **Output:**::\n\n Entity.update\n Player.update\n\nAbstract methods\n````````````````\n\n.. code:: python\n\n class Abstract(Cooperative):\n @abstract\n def method(self):\n pass\n\n class Concrete(Abstract):\n @cooperate\n def method(self):\n print \"Concrete.method\"\n\n try:\n obj = Abstract()\n except TypeError:\n print \"Abstract could not be instantiated\".\n\n obj = Concrete()\n obj.method()\n..\n\n **Output:**::\n\n Abstract could not be instantiated\n Concrete.method\n\nCompatibility with standard abstract methods\n````````````````````````````````````````````\n\n.. code:: python\n\n import abc\n\n class Abstract(Cooperative):\n @abc.abstractmethod\n def method(self):\n pass\n\n Abstract() # Error\n..\n\nPost-cooperation\n````````````````\n\n.. code:: python\n\n class Entity(Cooperative):\n @cooperative\n def dispose(self):\n print \"Entity.dispose\"\n\n class ConcreteEntity(Entity):\n @post_cooperate\n def dispose(self):\n print \"ConcreteEntity.dispose\"\n\n ConcreteEntity().dispose()\n..\n\n **Output:**::\n\n ConcreteEntity.dispose\n Entity.dispose\n\nFix arguments to superclass\n```````````````````````````\n\n.. code:: python\n\n class TextWidget(Cooperative):\n @cooperate\n def __init__(self, color=\"black\", background=\"white\"):\n print \"color = \", color\n print \"background = \", background\n\n class ShadedTextWidget(TextWidget):\n @cooperate_with_params(color=\"gray\")\n def __init__(self):\n pass\n\n ShadedTextWidget()\n..\n\n **Output:**::\n\n color = gray\n background = white\n\nInner cooperation\n`````````````````\n\n.. code:: python\n\n import random\n\n class FunnyTextWidget(TextWidget):\n @inner_cooperate\n def __init__(self, next_method):\n random_color = random.choice([\"green\", \"yellow\", \"red\"])\n next_method (color = random_color)\n..\n\nManual cooperation\n``````````````````\n\n.. code:: python\n\n class MockEntity(Entity):\n @manual_cooperate\n def update(self, timer, **k):\n super(MockEntity, self).update(**k)\n self.updated_called = True\n..\n\nReferences\n----------\n\n- `Python's super is nifty, but you can't use it `_\n- `Python's method resolution order `_\n\nLicense\n-------\n\n Copyright (c) 2012, 2015 Juan Pedro Bolivar Puente \n\n Permission is hereby granted, free of charge, to any person obtaining a copy\n of this software and associated documentation files (the \"Software\"), to deal\n in the Software without restriction, including without limitation the rights\n to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n copies of the Software, and to permit persons to whom the Software is\n furnished to do so, subject to the following conditions:\n\n The above copyright notice and this permission notice shall be included in\n all copies or substantial portions of the Software.\n\n THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n THE SOFTWARE.", "description_content_type": null, "docs_url": null, "download_url": "https://github.com/arximboldi/cooper/tarball/0.1.3", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/arximboldi/cooper", "keywords": "", "license": "UNKNOWN", "maintainer": "", "maintainer_email": "", "name": "cooper", "package_url": "https://pypi.org/project/cooper/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/cooper/", "project_urls": { "Download": "https://github.com/arximboldi/cooper/tarball/0.1.3", "Homepage": "https://github.com/arximboldi/cooper" }, "release_url": "https://pypi.org/project/cooper/0.1.3/", "requires_dist": null, "requires_python": "", "summary": "Easy and safe cooperative methods", "version": "0.1.3" }, "last_serial": 2451387, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "dad668481551b6495f95d66e77b62dd2", "sha256": "696678eb3b9863737ebcbe805f3c6cda2f8ae3441f616b5c28ceb54b3f97b9a5" }, "downloads": -1, "filename": "cooper-0.1.0.tar.gz", "has_sig": false, "md5_digest": "dad668481551b6495f95d66e77b62dd2", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5203, "upload_time": "2015-07-22T14:20:15", "url": "https://files.pythonhosted.org/packages/df/cf/db8579e0b4920028a82ea0abf8e87a83c3136e6be409d60ea5210260cbfd/cooper-0.1.0.tar.gz" } ], "0.1.1": [ { "comment_text": "", "digests": { "md5": "4ec2bc703baa432f5e506c5da35733b0", "sha256": "667220d46a6d042b53c2a154d124eb6f140ced4c63cd0b3b2cecefbd909351f0" }, "downloads": -1, "filename": "cooper-0.1.1.tar.gz", "has_sig": false, "md5_digest": "4ec2bc703baa432f5e506c5da35733b0", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 3617, "upload_time": "2016-11-09T10:49:31", "url": "https://files.pythonhosted.org/packages/1d/8c/70e36a13770d622d3d1ac7c349e1bf5d2fafa80a185956506a974b3beeb7/cooper-0.1.1.tar.gz" } ], "0.1.2": [ { "comment_text": "", "digests": { "md5": "187cf4b480b742c92183a1925e6b57b0", "sha256": "92d2dc22506864a31dc64e1d00194e3e39775a96342f34612319c9cce3645b39" }, "downloads": -1, "filename": "cooper-0.1.2.2.tar.gz", "has_sig": false, "md5_digest": "187cf4b480b742c92183a1925e6b57b0", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7234, "upload_time": "2016-11-09T11:21:49", "url": "https://files.pythonhosted.org/packages/12/56/fb1a63a306b542ca26d12db6acef4b83df7d5f9e195e26e4679821bb384b/cooper-0.1.2.2.tar.gz" } ], "0.1.3": [ { "comment_text": "", "digests": { "md5": "cc52b8f540e2b0cb2191f5a6629c00f2", "sha256": "4ac850c90fcfbe4a4633447927beb25f1949a72ee53e3364441bdc987d661fa8" }, "downloads": -1, "filename": "cooper-0.1.3.tar.gz", "has_sig": false, "md5_digest": "cc52b8f540e2b0cb2191f5a6629c00f2", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7213, "upload_time": "2016-11-09T17:04:51", "url": "https://files.pythonhosted.org/packages/70/ac/ce39c7743aa0342982b18b90b7712edb17ed6565df4f0a76818478f0e008/cooper-0.1.3.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "cc52b8f540e2b0cb2191f5a6629c00f2", "sha256": "4ac850c90fcfbe4a4633447927beb25f1949a72ee53e3364441bdc987d661fa8" }, "downloads": -1, "filename": "cooper-0.1.3.tar.gz", "has_sig": false, "md5_digest": "cc52b8f540e2b0cb2191f5a6629c00f2", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7213, "upload_time": "2016-11-09T17:04:51", "url": "https://files.pythonhosted.org/packages/70/ac/ce39c7743aa0342982b18b90b7712edb17ed6565df4f0a76818478f0e008/cooper-0.1.3.tar.gz" } ] }