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.values():
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.values()
# {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 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 Distributions
Built Distribution
File details
Details for the file progeny-0.1.1-py2.py3-none-any.whl
.
File metadata
- Download URL: progeny-0.1.1-py2.py3-none-any.whl
- Upload date:
- Size: 5.0 kB
- Tags: Python 2, Python 3
- Uploaded using Trusted Publishing? No
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 8c4d9a2c841b0ccdf45c16b7b72c3af1e76e83cb59c077806bfbc51cfe720ffe |
|
MD5 | 810f724e2764bf561cdb43d74e84c6c1 |
|
BLAKE2b-256 | 9739201a9999c68bc8a4faf23aa9d8dbb7dc3b0916e9b56d052cda19d5f56a70 |