protocols.advice -- Metaclasses and other ``Magic''

This module provides a variety of utility functions and classes used by the protocols package. None of them are really specific to the protocols package, and so may be useful to other libraries or applications.

addClassAdvisor( callback [, depth=2])
Set up callback to be called with the containing class, once it is created. This function is designed to be called by an ``advising'' function (such as protocols.advise()) executed in the body of a class suite. The ``advising'' function supplies a callback that it wishes to have executed when the containing class is created. The callback will be given one argument: the newly created containing class. The return value of the callback will be used in place of the class, so the callback should return the input if it does not wish to replace the class.

The optional depth argument determines the number of frames between this function and the targeted class suite. depth defaults to 2, since this skips this function's frame and one calling function frame. If you use this function from a function called directly in the class suite, the default will be correct, otherwise you will need to determine the correct depth yourself.

This function works by installing a special class factory function in place of the __metaclass__ of the containing class. Therefore, only callbacks after the last __metaclass__ assignment in the containing class will be executed. Be sure that classes using ``advising'' functions declare any __metaclass__ first, to ensure all callbacks are run.

isClassAdvisor( ob)
Returns truth if ob is a class advisor function. This is used to determine if a __metaclass__ value is a ``magic'' metaclass installed by addClassAdvisor(). If so, then ob will have a previousMetaclass attribute pointing to the previous metaclass, if any, and a callback attribute containing the callback that was given to addClassAdvisor().

getFrameInfo( frame)
Return a (kind,module,locals,globals) tuple for the supplied frame object. The returned kind is a string: either ``exec'', ``module'', ``class'', ``function call'', or ``unknown''. module is the module object the frame is/was executed in, or None if the frame's globals could not be correlated with a module in sys.modules. locals and globals are the frame's local and global dictionaries, respectively. Note that they can be the same dictionary, and that modifications to locals may not have any effect on the execution of the frame.

This function is used by functions like addClassAdvisor() and advise() to verify where they're being called from, and to work their respective magics.

getMRO( ob [, extendedClassic=False])
Return an iterable over the ``method resolution order'' of ob. If ob is a ``new-style'' class or type, this returns its __mro__ attribute. If ob is a ``classic'' class, this returns classicMRO(ob,extendedClassic). If ob is not a class or type of any kind, a one-element sequence containing just ob is returned.

classicMRO( ob [, extendedClassic=False])
Return an iterator over the ``method resolution order'' of classic class ob, following the ``classic'' method resolution algorithm of recursively traversing __bases__ from left to right. (Note that this may return the same class more than once, for some inheritance graphs.) If varextendedClassic is a true value, InstanceType and object are added at the end of the iteration. This is used by Protocol objects to allow generic adapters for InstanceType and object to be used with ``classic'' class instances.

determineMetaclass( bases [, explicit_mc=None])
Determine the metaclass that would be used by Python, given a non-empty sequence of base classes, and an optional explicitly supplied __metaclass__. Returns ClassType if all bases are ``classic'' and there is no explicit_mc. Raises TypeError if the bases' metaclasses are incompatible, just like Python would.

minimalBases( classes)
Return the shortest ordered subset of the input sequence classes that still contains the ``most specific'' classes. That is, the result sequence contains only classes that are not subclasses of each other. This function is used by determineMetaclass() to narrow down its list of candidate metaclasses, but is also useful for dynamically generating metaclasses.

mkRef( ob [, callable])
If ob is weak-referenceable, returns weakref.ref(ob,callable). Otherwise, returns a StrongRef(ob), emulating the interface of weakref.ref(). This is used by code that wants to use weak references, but may be given objects that are not weak-referenceable. Note that callable, if supplied, will not be called if ob is not weak-referenceable.

class StrongRef( ob)
An object that emulates the interface of weakref.ref(). When called, an instance of StrongRef will return the ob it was created for. Also, it will hash the same as ob and compare equal to it. Thus, it can be used as a dictionary key, as long as the underlying object can. Of course, since it is not really a weak reference, it does not contribute to the garbage collection of the underlying object, and may in fact hinder it, since it holds a live reference to the object.