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