Here are some tweaks on both bits of code: Paul McGuire wrote:
On May 25, 8:37 am, Michael Hines <[EMAIL PROTECTED]> wrote:
...
m = False for b in bases : if hasattr(b, '__mro__'): for bb in b.__mro__ : if bb == MetaHocObject.ho : if m == True: raise Exception("Inheritance of multiple HocObject not allowed") m = True
m = [] for b in bases: if hasattr(b, '__mro__'): if MetaHocObject.ho in b.__mro__: m.append(b) if m: raise TypeError('Multiple Inheritance of HocObject by %s ' 'not allowed.' % ', '.join(b.__name__ for b in m))
Rationale: (1) "if m == True" is always a flag for trouble. (2) When you detect a problem and raise an exception, provide information about what was wrong. (3) There is no need to report error conditions early. Accumulate information and complain (if it can be done without much extra code) exhaustively because a failure case should not be in the performance-limiting section anyway.
Here's a more general version of your testing code, to detect *any* diamond multiple inheritance (using your sample classes). for cls in (A,B,C,D): seen = set() try: bases = cls.__bases__ for b in bases: if hasattr(b,"__mro__"): for m in b.__mro__: if m in seen: raise Exception("diamond multiple inheritance") seen.add(m) except Exception, e: print cls,"has diamond MI" else: print cls,"is ok"
Warning: any two "new-style" classes as parents are necessarily involved in diamond inheritance (because object will be a common superclass). I'd make sure you produce (or can produce) all common super-classes, so you can filter the list to what you want. Maybe something like this: def diamond_points(class_): seen = dict((b, set([class_])) for b in class_.__bases__) for b in class_.__bases__: if hasattr(b, "__mro__"): for m in b.__mro__: if b != m: seen.setdefault(m, set()).add(b) for subclass, sources in seen.items(): if len(sources) == 1: seen.pop(subclass) return seen Then you can do a test like: trouble = diamond_points(class_) if trouble and (len(trouble) > 1 or object not in trouble): # you know you have a problem # If you only have forbidden multi-roots, you could # test if set(trouble) & forbidden_multi_parents: ... if object in trouble: trouble.pop(object) # Avoid simply new-style classes for common_ancestor, progeny in trouble.items(): print common_ancestor.__name__, 'used by:', ' & '.join( child.__name__ for child in progeny) --Scott David Daniels [EMAIL PROTECTED] -- http://mail.python.org/mailman/listinfo/python-list