Skip to content

ldunham1/abstract_factories

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

99 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Abstract Factories

PyPI - Version Actions Status

Python 2.7 Version Python 3 Versions

Abstract Factory lends itself well to systems that need to scale quickly and safely, allowing users to build and interact with code constructs through names.
Typically, additional functionality is required to ensure this design fits into a framework well, and even more work to allow for speedy iteration and development.

abstract_factories is a collection of classes to support this design with those additional conveniences built-in.

  • automatic (dynamic) registration from paths or modules
  • simple or conditional querying
  • versioning
  • type or instance items

and more.

Example Usage

Tool Versioning

Imagine you have a simple action you want to apply, already using the Abstract Factory design.

from .abstracts import ActionAbstract

class DemoAction(ActionAbstract):
    Version = 1

    def apply(self):
        print('Applied Demo.')

You then need to create a new action that addresses a bug BUT its old behavior is still required in places.
You can use abstract_factories to provide the correct version contextually.

from .abstracts import ActionAbstract

class MyAction(ActionAbstract):
    Version = 2

    def apply(self):
        logging.info('Applied Demo.')

Now we just create a tool factory and tell it where to find these tools.

import abstract_factories
from .abstracts import ActionAbstract
from . import actions

tool_factory = abstract_factories.AbstractTypeFactory(ActionAbstract, version_key='Version')
tool_factory.register_module(actions)

demo_action = tool_factory.get('DemoAction')  # Automatically retrieves latest.
old_demo_action = tool_factory.get('DemoAction', version=1)

Rigging Frameworks

See rig factory.
Rig components can often be updated to address bugs, improve performance or introduce features.
A common unintentional side effect is introducing behavioural regressions or different results.

abstract_factories encourages the use of versioning to "soft-lock" components so when a change is necessary, it can be done safely. The new rig component version is used by default, but the previous versions are still accessible at the same time. Better yet, the Abstract Factory design simplifies serialization and deserialization of the data, so older rigs can still be built as they were whilst being aware of the potential to upgrade.

Validation Frameworks (Files, Rigs, Models, Animations etc)

See simple_validation.
Asset validation is relatively simple to implement, but increasingly difficult to manage during a production.
Some validation frameworks, like Pyblish manages this well.

abstract_factories provides the minimum required to build your own similar Validation framework. Its item auto-registration provides a very flexible environment to quickly develop, improve, iterate and scale as you see fit.

Installation

Clone this repo or access it from PyPI;

pip install abstract-factories

Usage

Initialize AbstractTypeFactory or AbstractInstanceFactory with an abstract type.
Optionally, provide the attribute/method name to identify items by name (and optionally version).

Registering items can be done directly.

from abstract_factories import AbstractTypeFactory


class AbstractVehicle(object):
    def start(self):
        raise NotImplementedError()


class Car(AbstractVehicle):
    def start(self):
        print('Vrooom...')


# Type Factory
type_factory = AbstractTypeFactory(AbstractVehicle)
type_factory.register_item(Car)
assert type_factory.get('Car') is Car

By default, items are referred to by class name, unless a name_key is provided.

Abstract factories can automatically register items found in given python modules or paths.

from abstract_factories import AbstractTypeFactory
from . import my_vehicle_package


# Type Factory
type_factory = AbstractTypeFactory(my_vehicle_package.AbstractVehicle)

# Find any AbstractVehicle subclasses in `my_vehicle_package` and register them.
type_factory.register_module(my_vehicle_package)
assert type_factory.get('Car') is my_vehicle_package.Car

# Can also find any AbstractVehicle subclasses in a directory and register those too.
type_factory.register_path('c:/Users/user/downloads/other_vehicles')

In some use-cases, instances are a much better fit for the type of data you want to use in your factory (a factory of factories?).
In that case, use AbstractInstanceFactory.

from abstract_factories import AbstractInstanceFactory


class AbstractVehicle(object):
    def __init__(self, make=None):
        self.make = make

    def start(self):
        raise NotImplementedError()


class Car(AbstractVehicle):
    def start(self):
        print('Vrooom...')


# Instance Factory
honda = Car('Honda')
instance_factory = AbstractInstanceFactory(AbstractVehicle, name_key='make')
instance_factory.register_item(honda)
assert instance_factory.get('Honda') is honda

Registration:

Register viable items directly.

  • type_factory.register_item(AbstractSubclass)
  • instance_factory.register_item(AbstractSubclass())

Find and register any viable items found in the module's locals.

  • type_factory/instance_factory.register_module(module)

Find and register any viable items found in any nested python file from a dynamic import. Some limitation using relative imports.

  • type_factory/instance_factory.register_path(r'c:/tools/tool_plugins')
  • type_factory/instance_factory.register_path(r'c:/tools/tool_plugins/plugin.py')

Additional

Contextual get:

Instead of a str type name_key or version_key value, you can instead provide a callable. This will be used to determine each item's name and/or version.
This is especially useful when the context of an item's name or version lies outside the Factory's remit.

Further Information

Abstract factories is influenced by https://github.com/mikemalinowski/factories.

License

This project is licensed under the MIT License.

About

Collection of functional abstract factory designs

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages