- @param cls: Existing class to mix features into
- @type cls: class
- @param new_cls: Class containing features to add
- @type new_cls: class
- @param ignore: Ignore these methods from the mixin
- @type ignore: iterable
- '''
- # loop over all names in the new class
- for name, func in new_cls.__dict__.items():
- if name in ignore:
- continue
- if isinstance(func, types.FunctionType):
- # build a new function that is a clone of the one from new_cls
- method = new.function(func.func_code, func.func_globals, name,
- func.func_defaults, func.func_closure)
- try:
- # check if a method of the same name already exists in the target
- old_method = getattr(cls, name)
- except AttributeError:
- pass
- else:
- # rename the old method so we can still call it if need be
- setattr(cls, '_mix_'+name, old_method)
- # add the clone to cls
- setattr(cls, name, method)
- elif isinstance(func, staticmethod):
- try:
- # check if a method of the same name already exists in the target
- old_method = getattr(cls, name)
- except AttributeError:
- pass
- else:
- # rename the old method so we can still call it if need be
- setattr(cls, '_mix_'+name, old_method)
- setattr(cls, name, func)
- elif isinstance(func, property):
- try:
- # check if a method of the same name already exists in the target
- old_prop = getattr(cls, name)
- except AttributeError:
- pass
- else:
- # IMPORTANT: We save the old property before overwriting it, even
- # though we never end up calling the old prop from our mixin class.
- # If we don't save the old one, we seem to introduce a Python ref count
- # problem where the property get/set methods disappear before we can
- # use them at a later time. This is a minor waste of memory because
- # a property is a class object and we only overwrite a few of them.
- setattr(cls, '_mix_'+name, old_prop)
- setattr(cls, name, func)
-
-class _AccessibleMixin(object):
- '''
- Defines methods to be added to the Accessibility.Accessible class. The
- features defined here will be added to the Accessible class at run time so
- that all instances of Accessible have them (i.e. there is no need to
- explicitly wrap an Accessible in this class or derive a new class from it.)
-
- @cvar SLOTTED_CLASSES: Mapping from raw Accessibility class to a new class
- having the slots defined by L{SLOTS}
- @type SLOTTED_CLASSES: dictionary
- @cvar SLOTS: All slots to create
- @type SLOTS: tuple
- '''
- SLOTTED_CLASSES = {}
- SLOTS = ('_icache', 'user_data')
-
- def __new__(cls):
- '''
- Creates a new class mimicking the one requested, but with extra named
- defined in __slots__. The _cache attribute is used internally for interface
- caching. The user_data field may be populated with whatever data structure
- a client wishes to use. Neither is set to a default value by default.
-
- Note that we can't simply mix __slots__ into this class because __slots__
- has an effect only at class creation time.