00001 import inspect, types, __builtin__ 00002 00003 ############## preliminary: two utility functions ##################### 00004 00005 def skip_redundant(iterable, skipset=None): 00006 "Redundant items are repeated items or items in the original skipset." 00007 if skipset is None: skipset = set() 00008 for item in iterable: 00009 if item not in skipset: 00010 skipset.add(item) 00011 yield item 00012 00013 00014 def remove_redundant(metaclasses): 00015 skipset = set([types.ClassType]) 00016 for meta in metaclasses: # determines the metaclasses to be skipped 00017 skipset.update(inspect.getmro(meta)[1:]) 00018 return tuple(skip_redundant(metaclasses, skipset)) 00019 00020 ################################################################## 00021 ## now the core of the module: two mutually recursive functions ## 00022 ################################################################## 00023 00024 memoized_metaclasses_map = {} 00025 00026 ## 00027 # Not intended to be used outside of this module, unless you know 00028 # what you are doing. 00029 def get_noconflict_metaclass(bases, left_metas, right_metas): 00030 # make tuple of needed metaclasses in specified priority order 00031 metas = left_metas + tuple(map(type, bases)) + right_metas 00032 needed_metas = remove_redundant(metas) 00033 00034 # return existing confict-solving meta, if any 00035 if needed_metas in memoized_metaclasses_map: 00036 return memoized_metaclasses_map[needed_metas] 00037 # nope: compute, memoize and return needed conflict-solving meta 00038 elif not needed_metas: # wee, a trivial case, happy us 00039 meta = type 00040 elif len(needed_metas) == 1: # another trivial case 00041 meta = needed_metas[0] 00042 # check for recursion, can happen i.e. for Zope ExtensionClasses 00043 elif needed_metas == bases: 00044 raise TypeError("Incompatible root metatypes", needed_metas) 00045 else: # gotta work ... 00046 metaname = '_' + ''.join([m.__name__ for m in needed_metas]) 00047 meta = classmaker()(metaname, needed_metas, {}) 00048 memoized_metaclasses_map[needed_metas] = meta 00049 return meta 00050 00051 def classmaker(left_metas=(), right_metas=()): 00052 def make_class(name, bases, adict): 00053 metaclass = get_noconflict_metaclass(bases, left_metas, right_metas) 00054 return metaclass(name, bases, adict) 00055 return make_class 00056 00057 if (__name__ == '__main__'): 00058 from vyperlogix.misc import ObjectTypeName 00059 00060 class M_A(type): 00061 pass 00062 class M_B(type): 00063 pass 00064 class A(object): 00065 __metaclass__=M_A 00066 class B(object): 00067 __metaclass__=M_B 00068 #from noconflict import classmaker 00069 class C(A,B): 00070 __metaclass__=classmaker() 00071 print ObjectTypeName._typeName(C) 00072 00073
© Copyright 2008-2009 Vyper Logix Corp., All Right Reserved; If you reference this document or any part of this document you must use the citation verbatim (including the link) "© Copyright 2008-2009 Vyper Logix Corp., All Right Reserved."
Notice: This source code contained in this document is NOT open source and is NOT being distributed as open source.
122,241 lines of code and growing...