{ "info": { "author": "Lyndsy Simon", "author_email": "lyndsy@goodrx.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Natural Language :: English", "Programming Language :: Python", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy" ], "description": "=======\nProgeny\n=======\n\nSimple (but powerful) management for complex class hierarchies.\n\n.. image:: https://travis-ci.org/GoodRx/progeny.svg?branch=master\n :target: https://travis-ci.org/GoodRx/progeny\n\n\nMotivation\n----------\n\nWhile ``XYZClass.__subclasses__()`` returns the children of a class, there is\nno built-in way to return all descendants. This is the core of Progeny's\npurpose.\n\nIn addition, Progeny provides tools to help manage complex, deeply nested\nclass hierarchies - hiding individual classes, keeping a registry of\ndescendants, etc.\n\nExamples\n--------\n\nBasic Usage\n===========\n\n.. code:: python\n\n import progeny\n\n\n class NotificationHandler(progeny.Base):\n def send_message(self, *args, **kwargs):\n raise RuntimeError\n\n\n class CustomerOneNotificationHandler(NotificationHandler):\n def send_message(self, *args, **kwargs):\n # .. business logic ...\n\n\n class CustomerTwoNotificationHandler(NotificationHandler):\n def send_message(self, *args, **kwargs):\n # .. business logic ...\n\nNow we can iterate over all of the subclasses of ``NotificationHandler``:\n\n.. code:: python\n\n def send_newsletter():\n for handler in NotificationHandler.progeny.values():\n handler.send_message('Your attention, please!')\n\nOmitting descendant classes\n===========================\n\nIn some cases, it may be useful to prevent descendant classes from being visible to Progeny.\n\n.. code:: python\n\n from progeny import progeny.Base\n\n\n class NotificationHandler(progeny.Base):\n def send_message(self, *args, **kwargs):\n raise RuntimeError\n\n\n class EmailNotificationHandler(NotificationHandler):\n __progeny_tracked__ = False\n\n def send_message(self, *args, **kwargs):\n # .. business logic ..\n\n\n class SmsNotificationHandler(NotificationHandler):\n __progeny_tracked__ = False\n\n def send_message(self, *args, **kwargs):\n # .. business logic ..\n\n\n class CustomerOneNotificationHandler(EmailNotificationHandler):\n pass\n\n\n class CustomerTwoNotificationHandler(SmsNotificationHandler):\n pass\n\nAny classes with ``__progeny_tracked__`` set to a falsy value during class\nconstruction will be ignored by Progeny. It's descendant classes are unaffected:\n\n.. code:: python\n\n NotificationHandler.progeny.values()\n # {CustomerOneNotificationHandler, CustomerTwoNotificationHandler}\n\nThis can be especially handy to conditionally track subclasses based on config\ncontext:\n\n.. code:: python\n\n class CustomerFooNotificationHandler(EmailNotificationHandler):\n __progeny_tracked__ = config.get('CUSTOMER_FOO_ACTIVE')\n\nUsing the descendants registry\n==============================\n\nProgeny makes it easy to choose between descendant classes at runtime:\n\n.. code:: python\n\n from progeny import progeny.Base\n from my_app.users import UserLevel\n\n\n class UploadParser(progeny.Base):\n pass\n\n\n class FreeUserUploadParser(UploadParser):\n __progeny_key__ = UserLevel.FREE\n\n def parse_upload(self, *args, **kwargs):\n # .. logic to parse the upload slowly, using shared resources\n\n\n class PremiumUserUploadParser(UploadParser):\n __progeny_key__ = UserLevel.PAID\n\n def parse_upload(self, *args, **kwargs):\n # .. logic to parse the upload immediately with dedicated resources\n\n.. code:: python\n\n def parse_upload(data):\n UploadParser.progeny.get(session.user.level).parse_upload(data)\n\nPublishing to PyPI\n------------------\n\n`python setup.py sdist bdist_wheel`\n`twine upload \"dist/*\"`\n\n\n", "description_content_type": "", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/GoodRx/progeny", "keywords": "", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "progeny", "package_url": "https://pypi.org/project/progeny/", "platform": "", "project_url": "https://pypi.org/project/progeny/", "project_urls": { "Homepage": "https://github.com/GoodRx/progeny" }, "release_url": "https://pypi.org/project/progeny/0.1.1/", "requires_dist": [ "six" ], "requires_python": "", "summary": "Simple but powerful management for complex class hierarchies", "version": "0.1.1" }, "last_serial": 3699681, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "a1b7ec2efc9d28e001a02e694a141054", "sha256": "35ad13797988e3c3ac5d66507c92e4adfcf5efea955f1750a20562bbdb45b1b1" }, "downloads": -1, "filename": "progeny-0.1.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "a1b7ec2efc9d28e001a02e694a141054", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 4925, "upload_time": "2018-03-23T16:25:55", "url": "https://files.pythonhosted.org/packages/0c/d5/a0251bdd209f9c9855ff8306018cdbdb83ce4180f829050ad728e3494933/progeny-0.1.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "a870cc063e964244b60dd9ae1b2ec527", "sha256": "1c2ac37e375ee792a2174f7519f49896fc8cf723850bbb84b694578f11627ee0" }, "downloads": -1, "filename": "progeny-0.1.0.tar.gz", "has_sig": false, "md5_digest": "a870cc063e964244b60dd9ae1b2ec527", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 3984, "upload_time": "2018-03-23T16:25:56", "url": "https://files.pythonhosted.org/packages/e7/84/4711b963935d059ae0349b281f3bd2cced02e502cd2328b97e0222ce942c/progeny-0.1.0.tar.gz" } ], "0.1.1": [ { "comment_text": "", "digests": { "md5": "810f724e2764bf561cdb43d74e84c6c1", "sha256": "8c4d9a2c841b0ccdf45c16b7b72c3af1e76e83cb59c077806bfbc51cfe720ffe" }, "downloads": -1, "filename": "progeny-0.1.1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "810f724e2764bf561cdb43d74e84c6c1", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 5021, "upload_time": "2018-03-23T16:48:01", "url": "https://files.pythonhosted.org/packages/97/39/201a9999c68bc8a4faf23aa9d8dbb7dc3b0916e9b56d052cda19d5f56a70/progeny-0.1.1-py2.py3-none-any.whl" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "810f724e2764bf561cdb43d74e84c6c1", "sha256": "8c4d9a2c841b0ccdf45c16b7b72c3af1e76e83cb59c077806bfbc51cfe720ffe" }, "downloads": -1, "filename": "progeny-0.1.1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "810f724e2764bf561cdb43d74e84c6c1", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 5021, "upload_time": "2018-03-23T16:48:01", "url": "https://files.pythonhosted.org/packages/97/39/201a9999c68bc8a4faf23aa9d8dbb7dc3b0916e9b56d052cda19d5f56a70/progeny-0.1.1-py2.py3-none-any.whl" } ] }