renamed package.

This commit is contained in:
tylerlaberge
2016-09-10 17:11:45 -04:00
parent 52ceb712d4
commit cee2bc400b
39 changed files with 23 additions and 23 deletions

0
pypat/__init__.py Normal file
View File

View File

73
pypat/behavioral/chain.py Normal file
View File

@@ -0,0 +1,73 @@
from abc import ABCMeta, abstractmethod
class ChainLink(object, metaclass=ABCMeta):
"""
Abstract ChainLink object as part of the Chain of Responsibility pattern.
External Chain of Responsibility Pattern documentation: U{https://en.wikipedia.org/wiki/Chain-of-responsibility_pattern}
"""
def __init__(self):
"""
Initialize a new ChainLink instance.
"""
self.successor = None
def set_successor(self, successor):
"""
Set a chain link to call if this chain link fails.
@param successor: The chain link to call if this chain link fails.
@type successor: ChainLink
"""
self.successor = successor
def successor_handle(self, request):
"""
Have this chain links successor handle a request.
@param request: The request to handle.
"""
return self.successor.handle(request)
@abstractmethod
def handle(self, request):
"""
Handle a request.
@param request: The request to handle.
"""
pass
class Chain(object, metaclass=ABCMeta):
"""
Abstract Chain class as part of the Chain of Responsibility pattern.
External Chain of Responsibility Pattern documentation: U{https://en.wikipedia.org/wiki/Chain-of-responsibility_pattern}
"""
def __init__(self, chainlink):
"""
Initialize a new Chain instance.
@param chainlink: The starting chain link.
"""
self.chainlink = chainlink
def handle(self, request):
"""
Handle a request.
@param request: The request to handle.
"""
try:
return self.chainlink.handle(request)
except AttributeError:
return self.fail()
@abstractmethod
def fail(self):
"""
The method to call when the chain could not handle a request.
"""
pass

View File

@@ -0,0 +1,87 @@
from abc import ABCMeta, abstractmethod
class Receiver(object, metaclass=ABCMeta):
"""
Abstract receiver class as part of the Command pattern.
External Command Pattern documentation: U{https://en.wikipedia.org/wiki/Command_pattern}
"""
def action(self, name, *args, **kwargs):
"""
Delegates which method to be called for a desired action.
@param name: The name of the action to execute.
@type name: str
@param args: Any arguments for the action.
@param kwargs: Any keyword arguments for the action.
"""
try:
return getattr(self, name)(*args, **kwargs)
except AttributeError:
raise AttributeError('Invalid Action.')
class Command(object, metaclass=ABCMeta):
"""
Abstract Command class as part of the Command pattern.
External Command Pattern documentation: U{https://en.wikipedia.org/wiki/Command_pattern}
"""
def __init__(self, receiver):
"""
Initialize a new command instance.
@param receiver: The receiver for this command to use.
@type receiver: Receiver
"""
self._receiver = receiver
@abstractmethod
def execute(self):
"""
Abstract method for executing an action.
"""
pass
@abstractmethod
def unexecute(self):
"""
Abstract method for unexecuting an action.
"""
pass
class Invoker(object, metaclass=ABCMeta):
"""
Abstract Invoker class as part of the Command pattern.
External Command Pattern documentation: U{https://en.wikipedia.org/wiki/Command_pattern}
"""
def __init__(self, valid_commands):
"""
Initialize a new Invoker instance.
@param valid_commands: A list of command classes this invoker can handle.
"""
self._history = []
self._valid_commands = valid_commands
def execute(self, command):
"""
Execute a command.
@param command: A command for the invoker to execute.
@type command: Command
"""
if command.__class__ not in self._valid_commands:
raise AttributeError('Invalid Command')
else:
self._history.append(command)
return command.execute()
def undo(self):
"""
Undo the last command.
"""
return self._history.pop().unexecute()

View File

@@ -0,0 +1,37 @@
from abc import ABCMeta, abstractmethod
class Iterator(object):
"""
An Iterator class for the Iterator design pattern.
External Iterator Pattern documentation: U{https://en.wikipedia.org/wiki/Iterator_pattern}
"""
def __init__(self, iterable):
"""
Initialize a new Iterator instance.
@param iterable: An Iterable object to iterate over.
@type iterable: Iterable
"""
self.iterable = iterable
def __iter__(self):
return self
def __next__(self):
return self.iterable.__next__()
class Iterable(object, metaclass=ABCMeta):
"""
An abstract class representing an Iterable object as part of the Iterator design pattern.
External Iterator Pattern documentation: U{https://en.wikipedia.org/wiki/Iterator_pattern}
"""
@abstractmethod
def __next__(self):
"""
All Iterable's must implement a __next__ method which eventually raises StopIteration.
"""
pass

View File

@@ -0,0 +1,49 @@
from collections import defaultdict
class Mediator(object):
"""
Mediator class as part of the Mediator design pattern.
External Mediator Pattern documentation: U{https://en.wikipedia.org/wiki/Mediator_pattern}
"""
def __init__(self):
"""
Initialize a new Mediator instance.
"""
self.signals = defaultdict(list)
def signal(self, signal_name, *args, **kwargs):
"""
Send a signal out to all connected handlers.
@param signal_name: The name of the signal.
@type signal_name: Str
@param args: Positional arguments to send with the signal.
@param kwargs: Keyword arguments to send with the signal.
"""
for handler in self.signals[signal_name]:
handler(*args, **kwargs)
def connect(self, signal_name, receiver):
"""
Connect a receiver to a signal.
@param signal_name: The name of the signal to connect the receiver to.
@type signal_name: str
@param receiver: A handler to call when the signal is sent out.
"""
self.signals[signal_name].append(receiver)
def disconnect(self, signal_name, receiver):
"""
Disconnect a receiver from a signal.
@param signal_name: The name of the signal to disconnect the receiver from.
@type signal_name: str
@param receiver: The receiver to disconnect from the signal.
"""
try:
self.signals[signal_name].remove(receiver)
except ValueError:
pass

View File

@@ -0,0 +1,45 @@
from copy import deepcopy
class Memento(object):
"""
Memento class as part of the Memento design pattern.
External Memento Pattern documentation: U{https://en.wikipedia.org/wiki/Memento_pattern}
"""
def __init__(self, state):
"""
Initialize a new Memento instance.
@param state: The state to save in this Memento.
@type state: dict
"""
self.__state = state
@property
def state(self):
return self.__state
class Originator(object):
"""
Originator base class as part of the Memento design pattern.
External Mediator Pattern documentation: U{https://en.wikipedia.org/wiki/Memento_pattern}
"""
def commit(self):
"""
Commit this objects state to a memento.
@return: A memento instance with this objects state.
"""
return Memento(deepcopy(self.__dict__))
def rollback(self, memento):
"""
Rollback this objects state to a previous state.
@param memento: The memento object holding the state to rollback to.
@type memento: Memento
"""
self.__dict__ = memento.state

74
pypat/behavioral/null.py Normal file
View File

@@ -0,0 +1,74 @@
class Null(object):
"""
A Null object class as part of the Null object design pattern.
External Null Object Pattern documentation: U{https://en.wikipedia.org/wiki/Null_Object_pattern}
"""
def __init__(self, *args, **kwargs):
"""
Do nothing.
"""
pass
def __call__(self, *args, **kwargs):
"""
Do nothing.
@return: This object instance.
@rtype: Null
"""
return self
def __getattr__(self, name):
"""
Do nothing.
@return: This object instance.
@rtype: Null
"""
return self
def __setattr__(self, name, value):
"""
Do nothing.
@return: This object instance.
@rtype: Null
"""
return self
def __delattr__(self, name):
"""
Do nothing.
@return: This object instance.
@rtype: Null
"""
return self
def __repr__(self):
"""
Null object string representation is the empty string.
@return: An empty string.
@rtype: String
"""
return ''
def __str__(self):
"""
Null object string representation is the empty string.
@return: An empty string.
@rtype: String
"""
return ''
def __bool__(self):
"""
Null object evaluates to False.
@return: False.
@rtype: Boolean
"""
return False

View File

@@ -0,0 +1,58 @@
from abc import ABCMeta, abstractmethod
class Observer(object, metaclass=ABCMeta):
"""
Abstract Observer class as part of the Observer design pattern.
External Observer Pattern documentation: U{https://en.wikipedia.org/wiki/Observer_pattern}
"""
@abstractmethod
def update(self, **state):
"""
Abstract method that is called when an Observable's state changes.
"""
pass
class Observable(object):
"""
Base Observable class as part of the Observer design pattern.
External Observer Pattern documentation: U{https://en.wikipedia.org/wiki/Observer_pattern}
"""
def __init__(self):
"""
Initialize a new Observable instance.
"""
self._observers = set()
def attach(self, observer):
"""
Attach an observer to this Observable.
@param observer: The Observer to attach.
@type observer: Observer
"""
self._observers.add(observer)
def detach(self, observer):
"""
Detach an observer from this Observable.
@param observer: The Observer to detach.
@type observer: Observer
"""
try:
self._observers.remove(observer)
except KeyError:
pass
def notify(self):
"""
Notify all attached Observers of the state of this Observable.
"""
for observer in self._observers:
state = {k: v for k, v in self.__dict__.items() if not k.startswith('__') and not k.startswith('_')}
observer.update(**state)

View File

@@ -0,0 +1,56 @@
from abc import ABCMeta, abstractmethod
class Visitor(metaclass=ABCMeta):
"""
Abstract Visitor class as part of the Visitor Design Pattern.
External Visitor Design Pattern documentation: U{https://en.wikipedia.org/wiki/Visitor_pattern}
"""
def visit(self, node, *args, **kwargs):
"""
Visit the visitor with some object.
@param node: An object to call a visitor method with.
@param args: Arguments to go with the visitor method call.
@param kwargs: Keyword arguments to go with the visitor method call.
@return: The return value of the method that was called for visiting object.
"""
method = None
for cls in node.__class__.__mro__:
method_name = 'visit_'+cls.__name__.lower()
method = getattr(self, method_name, None)
if method:
break
if not method:
method = self.generic_visit
return method(node, *args, **kwargs)
@abstractmethod
def generic_visit(self, node, *args, **kwargs):
"""
The method to call if no methods were found for a visiting object.
@param node: An object to call a visitor method with.
@param args: Arguments to go with the visitor method call.
@param kwargs: Keyword arguments to go with the visitor method call.
"""
class Visitee(object):
"""
A base class for objects that wish to be able to be visited by a Visitor class.
External Visitor Design Pattern documentation: U{https://en.wikipedia.org/wiki/Visitor_pattern}
"""
def accept(self, visitor, *args, **kwargs):
"""
Have a visitor visit this class instance.
@param visitor: The visitor to visit.
@type visitor: Visitor
@param args: Any args to send with the visit.
@param kwargs: Any kwargs to send with the visit.
"""
return visitor.visit(self, *args, **kwargs)

View File

View File

@@ -0,0 +1,79 @@
from abc import ABCMeta, abstractmethod
class Director(object, metaclass=ABCMeta):
"""
Abstract director class, responsible for using a builder to fully construct an object.
- External Usage documentation: U{https://github.com/tylerlaberge/PyPatterns/wiki/Creational-Pattern-Usage}
- External Builder Pattern documentation: U{https://en.wikipedia.org/wiki/Builder_pattern}
"""
def __init__(self):
"""
Initialize a new Director.
"""
self.builder = None
@abstractmethod
def construct(self):
"""
Abstract method for fully constructing an object.
Concrete implementations should override this and use a builder to construct the object.
@raise NotImplementedError: If this method is not overridden.
"""
pass
def get_constructed_object(self):
"""
Get the object this director is responsible for constructing.
@return: The object that this director is responsible for constructing.
"""
return self.builder.constructed_object
class Builder(object, metaclass=ABCMeta):
"""
Abstract builder class, responsible for constructing various pieces of an object.
- External Usage documentation: U{https://github.com/tylerlaberge/PyPatterns/wiki/Creational-Pattern-Usage}
- External Builder Pattern documentation: U{https://en.wikipedia.org/wiki/Builder_pattern}
"""
def __init__(self, constructed_object):
"""
Initialize a new Builder.
Concrete Builders should call this method from within their own __init__ method.
The concrete __init__ method should also register all build options to build methods,
by using the _register method.
@param constructed_object: An instance of an object this builder is responsible for.
"""
self.constructed_object = constructed_object
self.build_methods = dict()
def build(self, build_option, **kwargs):
"""
Build a piece of the constructed object.
@param build_option: The part of the object to build. All build options should have been registered in __init__.
@type build_option: str
@param kwargs: Additional arguments for building.
"""
self.build_methods[build_option](**kwargs)
def _register(self, build_option, build_method):
"""
Register a build option to a build method.
All concrete builders should call this method in their constructor at least once.
@param build_option: A string representing the part of the object to build.
@type build_option: str
@param build_method: The method to call when given build option is selected.
"""
self.build_methods[build_option] = build_method

View File

@@ -0,0 +1,60 @@
from abc import abstractmethod, ABCMeta
class Factory(object, metaclass=ABCMeta):
"""
Factory Interface.
All Factories should inherit this class and overwrite the create method.
- External Usage documentation: U{https://github.com/tylerlaberge/PyPatterns/wiki/Creational-Pattern-Usage}
- External Factory Pattern documentation: U{https://en.wikipedia.org/wiki/Factory_method_pattern}
"""
@abstractmethod
def create(self, **kwargs):
"""
Abstract create method.
Concrete implementations should return a new instance of the object the factory class is responsible for.
@param kwargs: Arguments for object creation.
@return: A new instance of the object the factory is responsible for.
"""
pass
class AbstractFactory(Factory, metaclass=ABCMeta):
"""
Abstract Factory Class as part of the AbstractFactory design pattern.
- External Usage documentation: U{https://github.com/tylerlaberge/PyPatterns/wiki/Creational-Pattern-Usage}
- External Abstract Factory Pattern documentation: U{https://en.wikipedia.org/wiki/Abstract_factory_pattern}
"""
def __init__(self):
"""
Initialize the abstract factory.
Concrete implementations should call this from within their own __init__ method
and register all their factories to keys using the register method.
"""
self._factories = dict()
@abstractmethod
def create(self, **kwargs):
"""
Abstract create method.
Concrete implementations should return a new instance of an object by calling the appropriate factory.
@param kwargs: Arguments for object creation.
"""
pass
def _register(self, key, factory):
"""
Register a factory to a key.
@param key: Key for identifying which factory to use.
@type key: str
@param factory: The factory to register to the key.
"""
self._factories[str(key)] = factory

73
pypat/creational/pool.py Normal file
View File

@@ -0,0 +1,73 @@
from abc import ABCMeta
from copy import deepcopy
from pypat.behavioral.memento import Originator
class Reusable(Originator, metaclass=ABCMeta):
"""
An abstract reusable class.
External Object Pool Pattern documentation: U{https://en.wikipedia.org/wiki/Object_pool_pattern}
"""
def __init__(self):
"""
Initialize a new Reusable instance.
"""
self.memento = self.commit()
def reset(self):
"""
Reset this objects state to the state that it was created with.
"""
memento = self.memento
self.rollback(deepcopy(memento))
self.memento = memento
class Pool(object):
"""
An Object Pool design pattern implementation.
External Object Pool Pattern documentation: U{https://en.wikipedia.org/wiki/Object_pool_pattern}
"""
def __init__(self, reusable_class, *args, **kwargs):
"""
Initialize a new object pool instance.
@param reusable_class: The reusable class this object pool is responsible for.
@param args: args for reusable object creation.
@param kwargs: kwargs for reusable object creation.
"""
self.reusables = list()
self.reusable_class = reusable_class
self.args = args
self.kwargs = kwargs
self.pool_size = 2
self._expand(self.pool_size)
def acquire(self):
"""
Acquire an object from the pool.
@return: An object from the pool.
"""
try:
reusable = self.reusables.pop()
except IndexError:
self._expand(self.pool_size)
reusable = self.reusables.pop()
return reusable
def release(self, reusable):
"""
Release an object back into the pool.
@param reusable: The object to return to the pool.
"""
reusable.reset()
self.reusables.append(reusable)
def _expand(self, size):
for i in range(0, size):
self.reusables.append(self.reusable_class(*self.args, **self.kwargs))

View File

@@ -0,0 +1,25 @@
from copy import deepcopy
from types import MethodType
class Prototype(object):
"""
Prototype design pattern abstract class.
External Prototype Pattern documentation: U{https://en.wikipedia.org/wiki/Prototype_pattern}
"""
def prototype(self, **attributes):
"""
Copy the prototype this object and optionally update attributes.
@param attributes: Keyword arguments of any attributes you wish to update.
@return: A copy of this object with the updated attributes.
"""
obj = deepcopy(self)
for attribute in attributes:
if callable(attributes[attribute]):
setattr(obj, attribute, MethodType(attributes[attribute], obj))
else:
setattr(obj, attribute, attributes[attribute])
return obj

View File

@@ -0,0 +1,18 @@
class Singleton(type):
"""
Singleton Metaclass.
Enforces any object using this metaclass to only create a single instance.
External Singleton Pattern documentation: U{https://en.wikipedia.org/wiki/Singleton_pattern}
"""
__instance = None
def __call__(cls, *args, **kwargs):
"""
Override the __call__ method to make sure only one instance is created.
"""
if cls.__instance is None:
cls.__instance = type.__call__(cls, *args, **kwargs)
return cls.__instance

View File

View File

@@ -0,0 +1,32 @@
class Adapter(object):
"""
Adapter class as part of the Adapter design pattern.
External Adapter Pattern Documentation: U{https://en.wikipedia.org/wiki/Adapter_pattern}
"""
def __init__(self, adaptee, **adapted_methods):
"""
Initialize a new adapter instance.
@param adaptee: The object to adapt to a new interface.
@type adaptee: Object
@param adapted_methods: A dictionary of methods to adapt.
@type adapted_methods: dict
"""
self.__adaptee = adaptee
self.__dict__.update({k: v for k, v in adapted_methods.items() if callable(v) and
getattr(self.__adaptee, v.__name__, None)})
def __getattr__(self, attr):
"""
All non-adapted calls are passed to the adaptee.
@param attr: The attribute to get from the adaptee.
"""
return getattr(self.__adaptee, attr)
def original_dict(self):
"""
Get the adaptee's __dict__
"""
return self.__adaptee.__dict__

View File

@@ -0,0 +1,72 @@
class Composite(object):
"""
Composite class as part of the Composite pattern.
External Composite Pattern documentation: U{https://en.wikipedia.org/wiki/Composite_pattern}
"""
def __init__(self, interface):
"""
Initialize a new Composite instance.
@param interface: The interface the all child components must adhere to when added to this composite.
@type interface: class
"""
self.components = set()
self.interface = interface
def add_component(self, component):
"""
Add a component to this composite.
@param component: The component to add to this Composite
@raise AttributeError: If the component does not adhere to this Composites interface.
"""
valid = False
try:
if component.interface == self.interface:
valid = True
except AttributeError:
if self.interface in component.__class__.__mro__:
valid = True
finally:
if valid:
self.components.add(component)
else:
raise AttributeError('Component {0} does not follow this composites interface {1}'.format(
component.__class__, self.interface))
def remove_component(self, component):
"""
Remove a component from this composite.
@param component: The component to remove from this Composite.
"""
try:
self.components.remove(component)
except KeyError:
pass
def _delegate(self, func_name):
"""
Apply a function to all child components by function name.
@param func_name: The name of the function to call with all child components.
@type func_name: str
@raise AttributeError: If a child component does not have a callable function with the given name.
"""
for component in self.components:
attribute = getattr(component, func_name)
if callable(attribute):
attribute()
else:
raise AttributeError()
def __getattr__(self, item):
"""
Override getattr to delegate all function calls to children.
@param item: The function to call with this composites children components.
@type item: str
@return: A function that when called will call all child functions with the given function name.
"""
return lambda: self._delegate(item)

View File

@@ -0,0 +1,82 @@
from functools import partial
from abc import ABCMeta, abstractmethod
class Decorator(object, metaclass=ABCMeta):
"""
Base Decorator class that all decorator classes inherit from.
External Decorator Pattern documentation: U{https://en.wikipedia.org/wiki/Decorator_pattern}
"""
def __get__(self, instance, owner):
"""
Override __get__ in order to get the instance of a bound of method call.
"""
return partial(self.__call__, instance)
@abstractmethod
def __call__(self, *args, **kwargs):
"""
All decorators must implement a __call__ method.
"""
pass
class DecoratorSimple(Decorator, metaclass=ABCMeta):
"""
A Base Decorator class for decorators with no arguments.
External Decorator Pattern documentation: U{https://en.wikipedia.org/wiki/Decorator_pattern}
"""
def __init__(self, func):
"""
Initialize a new DecoratorSimple instance.
@param func: The function being decorated.
"""
self.func = func
class DecoratorComplex(Decorator, metaclass=ABCMeta):
"""
A Base Decorator class for decorators with arguments.
External Decorator Pattern documentation: U{https://en.wikipedia.org/wiki/Decorator_pattern}
"""
@abstractmethod
def __init__(self, *args, **kwargs):
"""
Initialize a new DecoratorComplex instance.
@param args: Args for the decorator.
@param kwargs: Keyword args for the decorator.
"""
pass
@abstractmethod
def __call__(self, func, *args, **kwargs):
"""
Concrete DecoratorComplex instances must override the __call__ method.
@param func: The function being decorated.
@param args: Arguments for the decorated function.
@param kwargs: Keyword arguments for the decorated function.
@return:
"""
pass
class CallWrapper(DecoratorSimple):
"""
A Decorator for wrapping DecoratorComplex __call__ methods.
External Decorator Pattern documentation: U{https://en.wikipedia.org/wiki/Decorator_pattern}
"""
def __call__(self, instance, func):
"""
Wrap a concrete DecoratorComplex __call__ method.
"""
def wrapped(*args, **kwargs):
return self.func(instance, func, *args, **kwargs)
return wrapped

View File

@@ -0,0 +1,47 @@
class FlyweightMeta(type):
"""
Flyweight meta class as part of the Flyweight design pattern.
External Flyweight Pattern documentation: U{https://en.wikipedia.org/wiki/Flyweight_pattern}
"""
def __new__(mcs, name, bases, attrs):
"""
Override class construction to add 'pool' attribute to classes dict.
@param name: The name of the class.
@param bases: Base classes of the class.
@param attrs: Attributes of the class.
@return: A new Class.
"""
attrs['pool'] = dict()
return super(FlyweightMeta, mcs).__new__(mcs, name, bases, attrs)
@staticmethod
def _serialize(cls, *args, **kwargs):
"""
Serialize arguments to a string representation.
"""
serialized_args = [str(arg) for arg in args]
serialized_kwargs = [str(kwargs), cls.__name__]
serialized_args.extend(serialized_kwargs)
return ''.join(serialized_args)
def __call__(cls, *args, **kwargs):
"""
Override call to use objects from a pool if identical parameters are used for object creation.
@param args: Arguments for class instantiation.
@param kwargs: Keyword arguments for class instantiation.
@return: A new instance of the class.
"""
key = FlyweightMeta._serialize(cls, *args, **kwargs)
pool = getattr(cls, 'pool', {})
instance = pool.get(key)
if not instance:
instance = super(FlyweightMeta, cls).__call__(*args, **kwargs)
pool[key] = instance
return instance