Package grassyknoll :: Package lib :: Module meta :: Class Factory
[hide private]

Class Factory

source code


easier construction of instance factories.

This class is intended to replace the closure-over-constructor pattern while being safer and easier to work with. Such closures are typically used when there are several implementations of the same interface, but each has a different constructor, or as a means of 'configuring' an instance before it's actually needed. Rather than writing a lambda, you can assign attributes to factory and then call the factory to produce a new instance. Finally, Factories can be pickled (assuming all attributes can).

In the following examples, we mix in FactoryMixin to provide a factory classmethod on the base class. This isn't strictly necessary, but looks nice and is recommend so that you hurt the little user's brains less:
>>> class Foo(FactoryMixin):
...     def __init__(self, foo):
...         self.foo=foo
...
>>> foo_factory=Foo.factory()
>>> foo_factory.foo=66
Factories have a bind method that can be used to set several attributes at once and returns the factory. It is useful for binding arguments without assigning the factory to a local variable.
>>> foo_factory2=foo_factory.bind(foo=11)
>>> foo_factory2 is foo_factory
True
>>> foo_factory.foo
11
You can also bind attributes when constructing the factory
>>> foo_factory=Foo.factory(foo=11)
>>> foo_factory.foo
11
Factories ensure that attributes match up with arguments; this makes finding errors easier (instead of raising a unexpected keyword argument later).
>>> foo_factory.bar=42  #doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'No such argument bar'
Call the Factory to get a new instance:
>>> foo=foo_factory()
>>> foo.foo
11
Arguments to the factory override attributes:
>>> foo=foo_factory(foo=1111)
>>> foo.foo
1111
Each call to the factory returns a new instance.
>>> foo2=foo_factory()
>>> foo2 is foo
False
>>> class Bar(Foo):
...     def __init__(self, bar, **kwargs):
...         super(Bar, self).__init__(**kwargs)
...         self.bar=bar
...
>>> bar_factory=Bar.factory()
The set of valid attributes is the union of all __init__ arguments in the inheritance chain:
>>> bar_factory.foo=11
>>> bar_factory.bar=42
>>> bar_factory.quux=666  #doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'No such argument quux'
>>> bar=bar_factory()
>>> bar.foo
11
>>> bar.bar
42
If you want to use a Factory directly, be sure to pass it a class, not an instance.
>>> Factory(bar)  # doctest:+ELLIPSIS, +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: must provide class, not <grassyknoll.lib.meta.Bar object at ...>


Instance Methods [hide private]
 
__init__(self, cls)
x.__init__(...) initializes x; see x.__class__.__doc__ for signature
source code
 
__setattr__(self, name, value)
x.__setattr__('name', value) <==> x.name = value
source code
 
__call__(self, *args, **kwargs) source code
 
bind(self, **kwargs)
set attributes to kwargs and return self
source code

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __str__

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, cls)
(Constructor)

source code 
x.__init__(...) initializes x; see x.__class__.__doc__ for signature
Overrides: object.__init__
(inherited documentation)

__setattr__(self, name, value)

source code 
x.__setattr__('name', value) <==> x.name = value
Overrides: object.__setattr__
(inherited documentation)