Metadata-Version: 1.1
Name: progeny
Version: 0.1.0
Summary: Simple but powerful management for complex class hierarchies
Home-page: https://github.com/GoodRx/progeny
Author: Lyndsy Simon
Author-email: lyndsy@goodrx.com
License: MIT
Description-Content-Type: UNKNOWN
Description: =======
        Progeny
        =======
        
        Simple (but powerful) management for complex class hierarchies.
        
        .. image:: https://travis-ci.org/GoodRx/progeny.svg?branch=master
            :target: https://travis-ci.org/GoodRx/progeny
        
        
        Motivation
        ----------
        
        While ``XYZClass.__subclasses__()`` returns the children of a class, there is
        no built-in way to return all descendants. This is the core of Progeny's
        purpose.
        
        In addition, Progeny provides tools to help manage complex, deeply nested
        class hierarchies - hiding individual classes, keeping a registry of
        descendants, etc.
        
        Examples
        --------
        
        Basic Usage
        ===========
        
        .. code:: python
        
            import progeny
        
        
            class NotificationHandler(progeny.Base):
                def send_message(self, *args, **kwargs):
                    raise RuntimeError
        
        
            class CustomerOneNotificationHandler(NotificationHandler):
                def send_message(self, *args, **kwargs):
                    # .. business logic ...
        
        
            class CustomerTwoNotificationHandler(NotificationHandler):
                def send_message(self, *args, **kwargs):
                    # .. business logic ...
        
        Now we can iterate over all of the subclasses of ``NotificationHandler``:
        
        .. code:: python
        
            def send_newsletter():
                for handler in NotificationHandler.progeny:
                    handler.send_message('Your attention, please!')
        
        Omitting descendant classes
        ===========================
        
        In some cases, it may be useful to prevent descendant classes from being visible to Progeny.
        
        .. code:: python
        
            from progeny import progeny.Base
        
        
            class NotificationHandler(progeny.Base):
                def send_message(self, *args, **kwargs):
                    raise RuntimeError
        
        
            class EmailNotificationHandler(NotificationHandler):
                __progeny_tracked__ = False
        
                def send_message(self, *args, **kwargs):
                    # .. business logic ..
        
        
            class SmsNotificationHandler(NotificationHandler):
                __progeny_tracked__ = False
        
                def send_message(self, *args, **kwargs):
                    # .. business logic ..
        
        
            class CustomerOneNotificationHandler(EmailNotificationHandler):
                pass
        
        
            class CustomerTwoNotificationHandler(SmsNotificationHandler):
                pass
        
        Any classes with ``__progeny_tracked__`` set to a falsy value during class
        construction will be ignored by Progeny. It's descendant classes are unaffected:
        
        .. code:: python
        
            NotificationHandler.progeny
            # {CustomerOneNotificationHandler, CustomerTwoNotificationHandler}
        
        This can be especially handy to conditionally track subclasses based on config
        context:
        
        .. code:: python
        
            class CustomerFooNotificationHandler(EmailNotificationHandler):
                __progeny_tracked__ = config.get('CUSTOMER_FOO_ACTIVE')
        
        Using the descendants registry
        ==============================
        
        Progeny makes it easy to choose between descendant classes at runtime:
        
        .. code:: python
        
            from progeny import progeny.Base
            from my_app.users import UserLevel
        
        
            class UploadParser(progeny.Base):
                pass
        
        
            class FreeUserUploadParser(UploadParser):
                __progeny_key__ = UserLevel.FREE
        
                def parse_upload(self, *args, **kwargs):
                    # .. logic to parse the upload slowly, using shared resources
        
        
            class PremiumUserUploadParser(UploadParser):
                __progeny_key__ = UserLevel.PAID
        
                def parse_upload(self, *args, **kwargs):
                    # .. logic to parse the upload immediately with dedicated resources
        
        .. code:: python
        
            def parse_upload(data):
                UploadParser.progeny.get(session.user.level).parse_upload(data)
        
        Publishing to PyPI
        ------------------
        
        `python setup.py sdist`
        `python setup.py bdist_wheel`
        `twine upload "dist/*"`
Platform: UNKNOWN
Classifier: Development Status :: 4 - Beta
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: Implementation :: PyPy
