declarative

Problem

Python does not let derived class have access to their base classes while the derived class is being defined:

>>> class base:
...     foo = ('a', 'b')
>>> class derived(base):
...     foo += ('c', 'd')
Traceback (most recent call last):
    ...
NameError: name 'foo' is not defined

Solution

The declarative metaclass solves this:

>>> from flask.ext.dry.api.class_init import declarative
>>> class base(metaclass=declarative):
...     foo = ('a', 'b')
>>> class derived(base):
...     foo += ('c', 'd')
>>> derived.foo
('a', 'b', 'c', 'd')

Now methods defined on the base class may access these class variables as the declarations that tell them what to do:

>>> class base(metaclass=declarative):
...     foo = ('a', 'b')  # default values
...     def do_foo(self):
...         for i in self.foo:
...             print("doing", i)
>>> class derived1(base):
...     foo += ('c', 'd') # extend default values
>>> class derived2(base):
...     foo = ('x', 'y')  # replace default values
>>> derived1().do_foo()
doing a
doing b
doing c
doing d
>>> derived2().do_foo()
doing x
doing y

The declarative metaclass makes a deepcopy of each base class attribute referenced by the derived class. This prevents updates made in the derived class from corrupting the base class:

>>> class base(metaclass=declarative):
...     foo = ['a', 'b']
>>> class derived(base):
...     foo.extend(('c', 'd'))
>>> derived.foo
['a', 'b', 'c', 'd']
>>> base.foo
['a', 'b']