renamed package to pypattyrn
This commit is contained in:
0
pypattyrn/__init__.py
Normal file
0
pypattyrn/__init__.py
Normal file
0
pypattyrn/behavioral/__init__.py
Normal file
0
pypattyrn/behavioral/__init__.py
Normal file
75
pypattyrn/behavioral/chain.py
Normal file
75
pypattyrn/behavioral/chain.py
Normal file
@@ -0,0 +1,75 @@
|
||||
from abc import ABCMeta, abstractmethod
|
||||
|
||||
|
||||
class ChainLink(object, metaclass=ABCMeta):
|
||||
"""
|
||||
Abstract ChainLink object as part of the Chain of Responsibility pattern.
|
||||
|
||||
- External Usage documentation: U{https://github.com/tylerlaberge/PyPatterns/wiki/Behavioral-Pattern-Usage}
|
||||
- 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 Usage documentation: U{https://github.com/tylerlaberge/PyPatterns/wiki/Behavioral-Pattern-Usage}
|
||||
- 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
|
||||
90
pypattyrn/behavioral/command.py
Normal file
90
pypattyrn/behavioral/command.py
Normal file
@@ -0,0 +1,90 @@
|
||||
from abc import ABCMeta, abstractmethod
|
||||
|
||||
|
||||
class Receiver(object, metaclass=ABCMeta):
|
||||
"""
|
||||
Abstract receiver class as part of the Command pattern.
|
||||
|
||||
- External Usage documentation: U{https://github.com/tylerlaberge/PyPatterns/wiki/Behavioral-Pattern-Usage}
|
||||
- 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 Usage documentation: U{https://github.com/tylerlaberge/PyPatterns/wiki/Behavioral-Pattern-Usage}
|
||||
- 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 Usage documentation: U{https://github.com/tylerlaberge/PyPatterns/wiki/Behavioral-Pattern-Usage}
|
||||
- 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()
|
||||
39
pypattyrn/behavioral/iterator.py
Normal file
39
pypattyrn/behavioral/iterator.py
Normal file
@@ -0,0 +1,39 @@
|
||||
from abc import ABCMeta, abstractmethod
|
||||
|
||||
|
||||
class Iterator(object):
|
||||
"""
|
||||
An Iterator class for the Iterator design pattern.
|
||||
|
||||
- External Usage documentation: U{https://github.com/tylerlaberge/PyPatterns/wiki/Behavioral-Pattern-Usage}
|
||||
- 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 Usage documentation: U{https://github.com/tylerlaberge/PyPatterns/wiki/Behavioral-Pattern-Usage}
|
||||
- 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
|
||||
50
pypattyrn/behavioral/mediator.py
Normal file
50
pypattyrn/behavioral/mediator.py
Normal file
@@ -0,0 +1,50 @@
|
||||
from collections import defaultdict
|
||||
|
||||
|
||||
class Mediator(object):
|
||||
"""
|
||||
Mediator class as part of the Mediator design pattern.
|
||||
|
||||
- External Usage documentation: U{https://github.com/tylerlaberge/PyPatterns/wiki/Behavioral-Pattern-Usage}
|
||||
- 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
|
||||
47
pypattyrn/behavioral/memento.py
Normal file
47
pypattyrn/behavioral/memento.py
Normal file
@@ -0,0 +1,47 @@
|
||||
from copy import deepcopy
|
||||
|
||||
|
||||
class Memento(object):
|
||||
"""
|
||||
Memento class as part of the Memento design pattern.
|
||||
|
||||
- External Usage documentation: U{https://github.com/tylerlaberge/PyPatterns/wiki/Behavioral-Pattern-Usage}
|
||||
- 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 Usage documentation: U{https://github.com/tylerlaberge/PyPatterns/wiki/Behavioral-Pattern-Usage}
|
||||
- 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
|
||||
75
pypattyrn/behavioral/null.py
Normal file
75
pypattyrn/behavioral/null.py
Normal file
@@ -0,0 +1,75 @@
|
||||
class Null(object):
|
||||
"""
|
||||
A Null object class as part of the Null object design pattern.
|
||||
|
||||
- External Usage documentation: U{https://github.com/tylerlaberge/PyPatterns/wiki/Behavioral-Pattern-Usage}
|
||||
- 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
|
||||
60
pypattyrn/behavioral/observer.py
Normal file
60
pypattyrn/behavioral/observer.py
Normal file
@@ -0,0 +1,60 @@
|
||||
from abc import ABCMeta, abstractmethod
|
||||
|
||||
|
||||
class Observer(object, metaclass=ABCMeta):
|
||||
"""
|
||||
Abstract Observer class as part of the Observer design pattern.
|
||||
|
||||
- External Usage documentation: U{https://github.com/tylerlaberge/PyPatterns/wiki/Behavioral-Pattern-Usage}
|
||||
- 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 Usage documentation: U{https://github.com/tylerlaberge/PyPatterns/wiki/Behavioral-Pattern-Usage}
|
||||
- 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)
|
||||
|
||||
58
pypattyrn/behavioral/visitor.py
Normal file
58
pypattyrn/behavioral/visitor.py
Normal file
@@ -0,0 +1,58 @@
|
||||
from abc import ABCMeta, abstractmethod
|
||||
|
||||
|
||||
class Visitor(metaclass=ABCMeta):
|
||||
"""
|
||||
Abstract Visitor class as part of the Visitor Design Pattern.
|
||||
|
||||
- External Usage documentation: U{https://github.com/tylerlaberge/PyPatterns/wiki/Behavioral-Pattern-Usage}
|
||||
- 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 Usage documentation: U{https://github.com/tylerlaberge/PyPatterns/wiki/Behavioral-Pattern-Usage}
|
||||
- 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)
|
||||
0
pypattyrn/creational/__init__.py
Normal file
0
pypattyrn/creational/__init__.py
Normal file
79
pypattyrn/creational/builder.py
Normal file
79
pypattyrn/creational/builder.py
Normal 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
|
||||
60
pypattyrn/creational/factory.py
Normal file
60
pypattyrn/creational/factory.py
Normal 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
|
||||
75
pypattyrn/creational/pool.py
Normal file
75
pypattyrn/creational/pool.py
Normal file
@@ -0,0 +1,75 @@
|
||||
from abc import ABCMeta
|
||||
from copy import deepcopy
|
||||
from pypattyrn.behavioral.memento import Originator
|
||||
|
||||
|
||||
class Reusable(Originator, metaclass=ABCMeta):
|
||||
"""
|
||||
An abstract reusable class.
|
||||
|
||||
- External Usage documentation: U{https://github.com/tylerlaberge/PyPatterns/wiki/Creational-Pattern-Usage}
|
||||
- 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 Usage documentation: U{https://github.com/tylerlaberge/PyPatterns/wiki/Creational-Pattern-Usage}
|
||||
- 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))
|
||||
26
pypattyrn/creational/prototype.py
Normal file
26
pypattyrn/creational/prototype.py
Normal file
@@ -0,0 +1,26 @@
|
||||
from copy import deepcopy
|
||||
from types import MethodType
|
||||
|
||||
|
||||
class Prototype(object):
|
||||
"""
|
||||
Prototype design pattern abstract class.
|
||||
|
||||
- External Usage documentation: U{https://github.com/tylerlaberge/PyPatterns/wiki/Creational-Pattern-Usage}
|
||||
- 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
|
||||
19
pypattyrn/creational/singleton.py
Normal file
19
pypattyrn/creational/singleton.py
Normal file
@@ -0,0 +1,19 @@
|
||||
class Singleton(type):
|
||||
"""
|
||||
Singleton Metaclass.
|
||||
|
||||
Enforces any object using this metaclass to only create a single instance.
|
||||
|
||||
- External Usage documentation: U{https://github.com/tylerlaberge/PyPatterns/wiki/Creational-Pattern-Usage}
|
||||
- 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
|
||||
0
pypattyrn/structural/__init__.py
Normal file
0
pypattyrn/structural/__init__.py
Normal file
33
pypattyrn/structural/adapter.py
Normal file
33
pypattyrn/structural/adapter.py
Normal file
@@ -0,0 +1,33 @@
|
||||
class Adapter(object):
|
||||
"""
|
||||
Adapter class as part of the Adapter design pattern.
|
||||
|
||||
- External Usage Documentation: U{https://github.com/tylerlaberge/PyPatterns/wiki/Structural-Pattern-Usage}
|
||||
- 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__
|
||||
73
pypattyrn/structural/composite.py
Normal file
73
pypattyrn/structural/composite.py
Normal file
@@ -0,0 +1,73 @@
|
||||
class Composite(object):
|
||||
"""
|
||||
Composite class as part of the Composite pattern.
|
||||
|
||||
- External Usage Documentation: U{https://github.com/tylerlaberge/PyPatterns/wiki/Structural-Pattern-Usage}
|
||||
- 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)
|
||||
86
pypattyrn/structural/decorator.py
Normal file
86
pypattyrn/structural/decorator.py
Normal file
@@ -0,0 +1,86 @@
|
||||
from functools import partial
|
||||
from abc import ABCMeta, abstractmethod
|
||||
|
||||
|
||||
class Decorator(object, metaclass=ABCMeta):
|
||||
"""
|
||||
Base Decorator class that all decorator classes inherit from.
|
||||
|
||||
- External Usage Documentation: U{https://github.com/tylerlaberge/PyPatterns/wiki/Structural-Pattern-Usage}
|
||||
- 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 Usage Documentation: U{https://github.com/tylerlaberge/PyPatterns/wiki/Structural-Pattern-Usage}
|
||||
- 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 Usage Documentation: U{https://github.com/tylerlaberge/PyPatterns/wiki/Structural-Pattern-Usage}
|
||||
- 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 Usage Documentation: U{https://github.com/tylerlaberge/PyPatterns/wiki/Structural-Pattern-Usage}
|
||||
- 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
|
||||
48
pypattyrn/structural/flyweight.py
Normal file
48
pypattyrn/structural/flyweight.py
Normal file
@@ -0,0 +1,48 @@
|
||||
class FlyweightMeta(type):
|
||||
"""
|
||||
Flyweight meta class as part of the Flyweight design pattern.
|
||||
|
||||
- External Usage Documentation: U{https://github.com/tylerlaberge/PyPatterns/wiki/Structural-Pattern-Usage}
|
||||
- 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
|
||||
Reference in New Issue
Block a user