renamed package to pypattyrn
This commit is contained in:
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