Simple but powerful management for complex class hierarchies
Project description
Simple (but powerful) management for complex class hierarchies.
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
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:
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.
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:
NotificationHandler.progeny
# {CustomerOneNotificationHandler, CustomerTwoNotificationHandler}
This can be especially handy to conditionally track subclasses based on config context:
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:
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
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/*”
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Hashes for progeny-0.1.0-py2.py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 35ad13797988e3c3ac5d66507c92e4adfcf5efea955f1750a20562bbdb45b1b1 |
|
MD5 | a1b7ec2efc9d28e001a02e694a141054 |
|
BLAKE2b-256 | 0cd5a0251bdd209f9c9855ff8306018cdbdb83ce4180f829050ad728e3494933 |