diff options
author | Guido van Rossum <guido@python.org> | 1998-09-14 16:44:15 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 1998-09-14 16:44:15 (GMT) |
commit | 4117e5428bf1ff3d26d23bd77472265412473ad9 (patch) | |
tree | d3a38e1c85eb46e5299cec0d5fb358cdc1db28fe /Demo/metaclasses | |
parent | f9a6d7d49425a04b10e4373077230c6cb93c5817 (diff) | |
download | cpython-4117e5428bf1ff3d26d23bd77472265412473ad9.zip cpython-4117e5428bf1ff3d26d23bd77472265412473ad9.tar.gz cpython-4117e5428bf1ff3d26d23bd77472265412473ad9.tar.bz2 |
nannified
Diffstat (limited to 'Demo/metaclasses')
-rw-r--r-- | Demo/metaclasses/Eiffel.py | 70 | ||||
-rw-r--r-- | Demo/metaclasses/Enum.py | 144 | ||||
-rw-r--r-- | Demo/metaclasses/Meta.py | 114 | ||||
-rw-r--r-- | Demo/metaclasses/Synch.py | 274 | ||||
-rw-r--r-- | Demo/metaclasses/Trace.py | 134 |
5 files changed, 368 insertions, 368 deletions
diff --git a/Demo/metaclasses/Eiffel.py b/Demo/metaclasses/Eiffel.py index 38ee6bc..d9c8a9a 100644 --- a/Demo/metaclasses/Eiffel.py +++ b/Demo/metaclasses/Eiffel.py @@ -4,19 +4,19 @@ For example, class C: def m1(self, arg): - require arg > 0 - return whatever + require arg > 0 + return whatever ensure Result > arg can be written (clumsily, I agree) as: class C(Eiffel): def m1(self, arg): - return whatever + return whatever def m1_pre(self, arg): - assert arg > 0 + assert arg > 0 def m1_post(self, Result, arg): - assert Result > arg + assert Result > arg Pre- and post-conditions for a method, being implemented as methods themselves, are inherited independently from the method. This gives @@ -28,10 +28,10 @@ post-condition with that defined in the derived class', for example: class D(C): def m1(self, arg): - return whatever**2 + return whatever**2 def m1_post(self, Result, arg): - C.m1_post(self, Result, arg) - assert Result < 100 + C.m1_post(self, Result, arg) + assert Result < 100 This gives derived classes more freedom but also more responsibility than in Eiffel, where the compiler automatically takes care of this. @@ -42,13 +42,13 @@ up to the derived class. For example, a derived class that takes away the requirement that arg > 0 could write: def m1_pre(self, arg): - pass + pass but one could equally write a derived class that makes a stronger requirement: def m1_pre(self, arg): - require arg > 50 + require arg > 50 It would be easy to modify the classes shown here so that pre- and post-conditions can be disabled (separately, on a per-class basis). @@ -66,27 +66,27 @@ from Meta import MetaClass, MetaHelper, MetaMethodWrapper class EiffelMethodWrapper(MetaMethodWrapper): def __init__(self, func, inst): - MetaMethodWrapper.__init__(self, func, inst) - # Note that the following causes recursive wrappers around - # the pre-/post-condition testing methods. These are harmless - # but inefficient; to avoid them, the lookup must be done - # using the class. - try: - self.pre = getattr(inst, self.__name__ + "_pre") - except AttributeError: - self.pre = None - try: - self.post = getattr(inst, self.__name__ + "_post") - except AttributeError: - self.post = None + MetaMethodWrapper.__init__(self, func, inst) + # Note that the following causes recursive wrappers around + # the pre-/post-condition testing methods. These are harmless + # but inefficient; to avoid them, the lookup must be done + # using the class. + try: + self.pre = getattr(inst, self.__name__ + "_pre") + except AttributeError: + self.pre = None + try: + self.post = getattr(inst, self.__name__ + "_post") + except AttributeError: + self.post = None def __call__(self, *args, **kw): - if self.pre: - apply(self.pre, args, kw) - Result = apply(self.func, (self.inst,) + args, kw) - if self.post: - apply(self.post, (Result,) + args, kw) - return Result + if self.pre: + apply(self.pre, args, kw) + Result = apply(self.func, (self.inst,) + args, kw) + if self.post: + apply(self.post, (Result,) + args, kw) + return Result class EiffelHelper(MetaHelper): __methodwrapper__ = EiffelMethodWrapper @@ -99,12 +99,12 @@ Eiffel = EiffelMetaClass('Eiffel', (), {}) def _test(): class C(Eiffel): - def m1(self, arg): - return arg+1 - def m1_pre(self, arg): - assert arg > 0, "precondition for m1 failed" - def m1_post(self, Result, arg): - assert Result > arg + def m1(self, arg): + return arg+1 + def m1_pre(self, arg): + assert arg > 0, "precondition for m1 failed" + def m1_post(self, Result, arg): + assert Result > arg x = C() x.m1(12) ## x.m1(-1) diff --git a/Demo/metaclasses/Enum.py b/Demo/metaclasses/Enum.py index e1ae695..13a3ed7 100644 --- a/Demo/metaclasses/Enum.py +++ b/Demo/metaclasses/Enum.py @@ -12,9 +12,9 @@ class EnumMetaClass: To define your own enumeration, do something like class Color(Enum): - red = 1 - green = 2 - blue = 3 + red = 1 + green = 2 + blue = 3 Now, Color.red, Color.green and Color.blue behave totally different: they are enumerated values, not integers. @@ -25,66 +25,66 @@ class EnumMetaClass: """ def __init__(self, name, bases, dict): - """Constructor -- create an enumeration. - - Called at the end of the class statement. The arguments are - the name of the new class, a tuple containing the base - classes, and a dictionary containing everything that was - entered in the class' namespace during execution of the class - statement. In the above example, it would be {'red': 1, - 'green': 2, 'blue': 3}. - - """ - for base in bases: - if base.__class__ is not EnumMetaClass: - raise TypeError, "Enumeration base class must be enumeration" - bases = filter(lambda x: x is not Enum, bases) - self.__name__ = name - self.__bases__ = bases - self.__dict = {} - for key, value in dict.items(): - self.__dict[key] = EnumInstance(name, key, value) + """Constructor -- create an enumeration. + + Called at the end of the class statement. The arguments are + the name of the new class, a tuple containing the base + classes, and a dictionary containing everything that was + entered in the class' namespace during execution of the class + statement. In the above example, it would be {'red': 1, + 'green': 2, 'blue': 3}. + + """ + for base in bases: + if base.__class__ is not EnumMetaClass: + raise TypeError, "Enumeration base class must be enumeration" + bases = filter(lambda x: x is not Enum, bases) + self.__name__ = name + self.__bases__ = bases + self.__dict = {} + for key, value in dict.items(): + self.__dict[key] = EnumInstance(name, key, value) def __getattr__(self, name): - """Return an enumeration value. + """Return an enumeration value. - For example, Color.red returns the value corresponding to red. + For example, Color.red returns the value corresponding to red. - XXX Perhaps the values should be created in the constructor? + XXX Perhaps the values should be created in the constructor? - This looks in the class dictionary and if it is not found - there asks the base classes. + This looks in the class dictionary and if it is not found + there asks the base classes. - The special attribute __members__ returns the list of names - defined in this class (it does not merge in the names defined - in base classes). + The special attribute __members__ returns the list of names + defined in this class (it does not merge in the names defined + in base classes). - """ - if name == '__members__': - return self.__dict.keys() + """ + if name == '__members__': + return self.__dict.keys() - try: - return self.__dict[name] - except KeyError: - for base in self.__bases__: - try: - return getattr(base, name) - except AttributeError: - continue + try: + return self.__dict[name] + except KeyError: + for base in self.__bases__: + try: + return getattr(base, name) + except AttributeError: + continue - raise AttributeError, name + raise AttributeError, name def __repr__(self): - s = self.__name__ - if self.__bases__: - s = s + '(' + string.join(map(lambda x: x.__name__, - self.__bases__), ", ") + ')' - if self.__dict: - list = [] - for key, value in self.__dict.items(): - list.append("%s: %s" % (key, int(value))) - s = "%s: {%s}" % (s, string.join(list, ", ")) - return s + s = self.__name__ + if self.__bases__: + s = s + '(' + string.join(map(lambda x: x.__name__, + self.__bases__), ", ") + ')' + if self.__dict: + list = [] + for key, value in self.__dict.items(): + list.append("%s: %s" % (key, int(value))) + s = "%s: {%s}" % (s, string.join(list, ", ")) + return s class EnumInstance: @@ -99,23 +99,23 @@ class EnumInstance: """ def __init__(self, classname, enumname, value): - self.__classname = classname - self.__enumname = enumname - self.__value = value + self.__classname = classname + self.__enumname = enumname + self.__value = value def __int__(self): - return self.__value + return self.__value def __repr__(self): - return "EnumInstance(%s, %s, %s)" % (`self.__classname`, - `self.__enumname`, - `self.__value`) + return "EnumInstance(%s, %s, %s)" % (`self.__classname`, + `self.__enumname`, + `self.__value`) def __str__(self): - return "%s.%s" % (self.__classname, self.__enumname) + return "%s.%s" % (self.__classname, self.__enumname) def __cmp__(self, other): - return cmp(self.__value, int(other)) + return cmp(self.__value, int(other)) # Create the base class for enumerations. @@ -126,9 +126,9 @@ Enum = EnumMetaClass("Enum", (), {}) def _test(): class Color(Enum): - red = 1 - green = 2 - blue = 3 + red = 1 + green = 2 + blue = 3 print Color.red print dir(Color) @@ -139,11 +139,11 @@ def _test(): print Color.red == 2 class ExtendedColor(Color): - white = 0 - orange = 4 - yellow = 5 - purple = 6 - black = 7 + white = 0 + orange = 4 + yellow = 5 + purple = 6 + black = 7 print ExtendedColor.orange print ExtendedColor.red @@ -151,11 +151,11 @@ def _test(): print Color.red == ExtendedColor.red class OtherColor(Enum): - white = 4 - blue = 5 + white = 4 + blue = 5 class MergedColor(Color, OtherColor): - pass + pass print MergedColor.red print MergedColor.white diff --git a/Demo/metaclasses/Meta.py b/Demo/metaclasses/Meta.py index 76193c1..771205c 100644 --- a/Demo/metaclasses/Meta.py +++ b/Demo/metaclasses/Meta.py @@ -9,33 +9,33 @@ import types class MetaMethodWrapper: def __init__(self, func, inst): - self.func = func - self.inst = inst - self.__name__ = self.func.__name__ + self.func = func + self.inst = inst + self.__name__ = self.func.__name__ def __call__(self, *args, **kw): - return apply(self.func, (self.inst,) + args, kw) + return apply(self.func, (self.inst,) + args, kw) class MetaHelper: __methodwrapper__ = MetaMethodWrapper # For derived helpers to override def __helperinit__(self, formalclass): - self.__formalclass__ = formalclass + self.__formalclass__ = formalclass def __getattr__(self, name): - # Invoked for any attr not in the instance's __dict__ - try: - raw = self.__formalclass__.__getattr__(name) - except AttributeError: - try: - ga = self.__formalclass__.__getattr__('__usergetattr__') - except KeyError: - raise AttributeError, name - return ga(self, name) - if type(raw) != types.FunctionType: - return raw - return self.__methodwrapper__(raw, self) + # Invoked for any attr not in the instance's __dict__ + try: + raw = self.__formalclass__.__getattr__(name) + except AttributeError: + try: + ga = self.__formalclass__.__getattr__('__usergetattr__') + except KeyError: + raise AttributeError, name + return ga(self, name) + if type(raw) != types.FunctionType: + return raw + return self.__methodwrapper__(raw, self) class MetaClass: @@ -45,49 +45,49 @@ class MetaClass: """ - __helper__ = MetaHelper # For derived metaclasses to override + __helper__ = MetaHelper # For derived metaclasses to override __inited = 0 def __init__(self, name, bases, dict): - try: - ga = dict['__getattr__'] - except KeyError: - pass - else: - dict['__usergetattr__'] = ga - del dict['__getattr__'] - self.__name__ = name - self.__bases__ = bases - self.__realdict__ = dict - self.__inited = 1 + try: + ga = dict['__getattr__'] + except KeyError: + pass + else: + dict['__usergetattr__'] = ga + del dict['__getattr__'] + self.__name__ = name + self.__bases__ = bases + self.__realdict__ = dict + self.__inited = 1 def __getattr__(self, name): - try: - return self.__realdict__[name] - except KeyError: - for base in self.__bases__: - try: - return base.__getattr__(name) - except AttributeError: - pass - raise AttributeError, name + try: + return self.__realdict__[name] + except KeyError: + for base in self.__bases__: + try: + return base.__getattr__(name) + except AttributeError: + pass + raise AttributeError, name def __setattr__(self, name, value): - if not self.__inited: - self.__dict__[name] = value - else: - self.__realdict__[name] = value + if not self.__inited: + self.__dict__[name] = value + else: + self.__realdict__[name] = value def __call__(self, *args, **kw): - inst = self.__helper__() - inst.__helperinit__(self) - try: - init = inst.__getattr__('__init__') - except AttributeError: - init = lambda: None - apply(init, args, kw) - return inst + inst = self.__helper__() + inst.__helperinit__(self) + try: + init = inst.__getattr__('__init__') + except AttributeError: + init = lambda: None + apply(init, args, kw) + return inst Meta = MetaClass('Meta', (), {}) @@ -95,18 +95,18 @@ Meta = MetaClass('Meta', (), {}) def _test(): class C(Meta): - def __init__(self, *args): - print "__init__, args =", args - def m1(self, x): - print "m1(x=%s)" %`x` + def __init__(self, *args): + print "__init__, args =", args + def m1(self, x): + print "m1(x=%s)" %`x` print C x = C() print x x.m1(12) class D(C): - def __getattr__(self, name): - if name[:2] == '__': raise AttributeError, name - return "getattr:%s" % name + def __getattr__(self, name): + if name[:2] == '__': raise AttributeError, name + return "getattr:%s" % name x = D() print x.foo print x._foo diff --git a/Demo/metaclasses/Synch.py b/Demo/metaclasses/Synch.py index 1fb9160..df70337 100644 --- a/Demo/metaclasses/Synch.py +++ b/Demo/metaclasses/Synch.py @@ -40,64 +40,64 @@ class Lock: """ def __init__(self): - """Constructor. Initialize all instance variables.""" - self.__mutex = thread.allocate_lock() - self.__wait = thread.allocate_lock() - self.__tid = None - self.__count = 0 + """Constructor. Initialize all instance variables.""" + self.__mutex = thread.allocate_lock() + self.__wait = thread.allocate_lock() + self.__tid = None + self.__count = 0 def acquire(self, flag=1): - """Acquire the lock. - - If the optional flag argument is false, returns immediately - when it cannot acquire the __wait lock without blocking (it - may still block for a little while in order to acquire the - __mutex lock). - - The return value is only relevant when the flag argument is - false; it is 1 if the lock is acquired, 0 if not. - - """ - self.__mutex.acquire() - try: - if self.__tid == thread.get_ident(): - self.__count = self.__count + 1 - return 1 - finally: - self.__mutex.release() - locked = self.__wait.acquire(flag) - if not flag and not locked: - return 0 - try: - self.__mutex.acquire() - assert self.__tid == None - assert self.__count == 0 - self.__tid = thread.get_ident() - self.__count = 1 - return 1 - finally: - self.__mutex.release() + """Acquire the lock. + + If the optional flag argument is false, returns immediately + when it cannot acquire the __wait lock without blocking (it + may still block for a little while in order to acquire the + __mutex lock). + + The return value is only relevant when the flag argument is + false; it is 1 if the lock is acquired, 0 if not. + + """ + self.__mutex.acquire() + try: + if self.__tid == thread.get_ident(): + self.__count = self.__count + 1 + return 1 + finally: + self.__mutex.release() + locked = self.__wait.acquire(flag) + if not flag and not locked: + return 0 + try: + self.__mutex.acquire() + assert self.__tid == None + assert self.__count == 0 + self.__tid = thread.get_ident() + self.__count = 1 + return 1 + finally: + self.__mutex.release() def release(self): - """Release the lock. + """Release the lock. - If this thread doesn't currently have the lock, an assertion - error is raised. + If this thread doesn't currently have the lock, an assertion + error is raised. - Only allow another thread to acquire the lock when the count - reaches zero after decrementing it. + Only allow another thread to acquire the lock when the count + reaches zero after decrementing it. - """ - self.__mutex.acquire() - try: - assert self.__tid == thread.get_ident() - assert self.__count > 0 - self.__count = self.__count - 1 - if self.__count == 0: - self.__tid = None - self.__wait.release() - finally: - self.__mutex.release() + """ + self.__mutex.acquire() + try: + assert self.__tid == thread.get_ident() + assert self.__count > 0 + self.__count = self.__count - 1 + if self.__count == 0: + self.__tid = None + self.__wait.release() + finally: + self.__mutex.release() def _testLock(): @@ -105,23 +105,23 @@ def _testLock(): done = [] def f2(lock, done=done): - lock.acquire() - print "f2 running in thread %d\n" % thread.get_ident(), - lock.release() - done.append(1) + lock.acquire() + print "f2 running in thread %d\n" % thread.get_ident(), + lock.release() + done.append(1) def f1(lock, f2=f2, done=done): - lock.acquire() - print "f1 running in thread %d\n" % thread.get_ident(), - try: - f2(lock) - finally: - lock.release() - done.append(1) + lock.acquire() + print "f1 running in thread %d\n" % thread.get_ident(), + try: + f2(lock) + finally: + lock.release() + done.append(1) lock = Lock() lock.acquire() - f1(lock) # Adds 2 to done + f1(lock) # Adds 2 to done lock.release() lock.acquire() @@ -134,8 +134,8 @@ def _testLock(): lock.release() import time while len(done) < 9: - print len(done) - time.sleep(0.001) + print len(done) + time.sleep(0.001) print len(done) @@ -147,19 +147,19 @@ from Meta import MetaClass, MetaHelper, MetaMethodWrapper class LockingMethodWrapper(MetaMethodWrapper): def __call__(self, *args, **kw): - if self.__name__[:1] == '_' and self.__name__[1:] != '_': - return apply(self.func, (self.inst,) + args, kw) - self.inst.__lock__.acquire() - try: - return apply(self.func, (self.inst,) + args, kw) - finally: - self.inst.__lock__.release() + if self.__name__[:1] == '_' and self.__name__[1:] != '_': + return apply(self.func, (self.inst,) + args, kw) + self.inst.__lock__.acquire() + try: + return apply(self.func, (self.inst,) + args, kw) + finally: + self.inst.__lock__.release() class LockingHelper(MetaHelper): __methodwrapper__ = LockingMethodWrapper def __helperinit__(self, formalclass): - MetaHelper.__helperinit__(self, formalclass) - self.__lock__ = Lock() + MetaHelper.__helperinit__(self, formalclass) + self.__lock__ = Lock() class LockingMetaClass(MetaClass): __helper__ = LockingHelper @@ -169,73 +169,73 @@ Locking = LockingMetaClass('Locking', (), {}) def _test(): # For kicks, take away the Locking base class and see it die class Buffer(Locking): - def __init__(self, initialsize): - assert initialsize > 0 - self.size = initialsize - self.buffer = [None]*self.size - self.first = self.last = 0 - def put(self, item): - # Do we need to grow the buffer? - if (self.last+1) % self.size != self.first: - # Insert the new item - self.buffer[self.last] = item - self.last = (self.last+1) % self.size - return - # Double the buffer size - # First normalize it so that first==0 and last==size-1 - print "buffer =", self.buffer - print "first = %d, last = %d, size = %d" % ( - self.first, self.last, self.size) - if self.first <= self.last: - temp = self.buffer[self.first:self.last] - else: - temp = self.buffer[self.first:] + self.buffer[:self.last] - print "temp =", temp - self.buffer = temp + [None]*(self.size+1) - self.first = 0 - self.last = self.size-1 - self.size = self.size*2 - print "Buffer size doubled to", self.size - print "new buffer =", self.buffer - print "first = %d, last = %d, size = %d" % ( - self.first, self.last, self.size) - self.put(item) # Recursive call to test the locking - def get(self): - # Is the buffer empty? - if self.first == self.last: - raise EOFError # Avoid defining a new exception - item = self.buffer[self.first] - self.first = (self.first+1) % self.size - return item + def __init__(self, initialsize): + assert initialsize > 0 + self.size = initialsize + self.buffer = [None]*self.size + self.first = self.last = 0 + def put(self, item): + # Do we need to grow the buffer? + if (self.last+1) % self.size != self.first: + # Insert the new item + self.buffer[self.last] = item + self.last = (self.last+1) % self.size + return + # Double the buffer size + # First normalize it so that first==0 and last==size-1 + print "buffer =", self.buffer + print "first = %d, last = %d, size = %d" % ( + self.first, self.last, self.size) + if self.first <= self.last: + temp = self.buffer[self.first:self.last] + else: + temp = self.buffer[self.first:] + self.buffer[:self.last] + print "temp =", temp + self.buffer = temp + [None]*(self.size+1) + self.first = 0 + self.last = self.size-1 + self.size = self.size*2 + print "Buffer size doubled to", self.size + print "new buffer =", self.buffer + print "first = %d, last = %d, size = %d" % ( + self.first, self.last, self.size) + self.put(item) # Recursive call to test the locking + def get(self): + # Is the buffer empty? + if self.first == self.last: + raise EOFError # Avoid defining a new exception + item = self.buffer[self.first] + self.first = (self.first+1) % self.size + return item def producer(buffer, wait, n=1000): - import time - i = 0 - while i < n: - print "put", i - buffer.put(i) - i = i+1 - print "Producer: done producing", n, "items" - wait.release() + import time + i = 0 + while i < n: + print "put", i + buffer.put(i) + i = i+1 + print "Producer: done producing", n, "items" + wait.release() def consumer(buffer, wait, n=1000): - import time - i = 0 - tout = 0.001 - while i < n: - try: - x = buffer.get() - if x != i: - raise AssertionError, \ - "get() returned %s, expected %s" % (x, i) - print "got", i - i = i+1 - tout = 0.001 - except EOFError: - time.sleep(tout) - tout = tout*2 - print "Consumer: done consuming", n, "items" - wait.release() + import time + i = 0 + tout = 0.001 + while i < n: + try: + x = buffer.get() + if x != i: + raise AssertionError, \ + "get() returned %s, expected %s" % (x, i) + print "got", i + i = i+1 + tout = 0.001 + except EOFError: + time.sleep(tout) + tout = tout*2 + print "Consumer: done consuming", n, "items" + wait.release() pwait = thread.allocate_lock() pwait.acquire() diff --git a/Demo/metaclasses/Trace.py b/Demo/metaclasses/Trace.py index a5b765a..86e199d 100644 --- a/Demo/metaclasses/Trace.py +++ b/Demo/metaclasses/Trace.py @@ -20,38 +20,38 @@ class TraceMetaClass: __inited = 0 def __init__(self, name, bases, dict): - self.__name__ = name - self.__bases__ = bases - self.__dict = dict - # XXX Can't define __dict__, alas - self.__inited = 1 + self.__name__ = name + self.__bases__ = bases + self.__dict = dict + # XXX Can't define __dict__, alas + self.__inited = 1 def __getattr__(self, name): - try: - return self.__dict[name] - except KeyError: - for base in self.__bases__: - try: - return base.__getattr__(name) - except AttributeError: - pass - raise AttributeError, name + try: + return self.__dict[name] + except KeyError: + for base in self.__bases__: + try: + return base.__getattr__(name) + except AttributeError: + pass + raise AttributeError, name def __setattr__(self, name, value): - if not self.__inited: - self.__dict__[name] = value - else: - self.__dict[name] = value + if not self.__inited: + self.__dict__[name] = value + else: + self.__dict[name] = value def __call__(self, *args, **kw): - inst = TracingInstance() - inst.__meta_init__(self) - try: - init = inst.__getattr__('__init__') - except AttributeError: - init = lambda: None - apply(init, args, kw) - return inst + inst = TracingInstance() + inst.__meta_init__(self) + try: + init = inst.__getattr__('__init__') + except AttributeError: + init = lambda: None + apply(init, args, kw) + return inst __trace_output__ = None @@ -59,52 +59,52 @@ class TracingInstance: """Helper class to represent an instance of a tracing class.""" def __trace_call__(self, fp, fmt, *args): - fp.write((fmt+'\n') % args) + fp.write((fmt+'\n') % args) def __meta_init__(self, klass): - self.__class = klass + self.__class = klass def __getattr__(self, name): - # Invoked for any attr not in the instance's __dict__ - try: - raw = self.__class.__getattr__(name) - except AttributeError: - raise AttributeError, name - if type(raw) != types.FunctionType: - return raw - # It's a function - fullname = self.__class.__name__ + "." + name - if not self.__trace_output__ or name == '__trace_call__': - return NotTracingWrapper(fullname, raw, self) - else: - return TracingWrapper(fullname, raw, self) + # Invoked for any attr not in the instance's __dict__ + try: + raw = self.__class.__getattr__(name) + except AttributeError: + raise AttributeError, name + if type(raw) != types.FunctionType: + return raw + # It's a function + fullname = self.__class.__name__ + "." + name + if not self.__trace_output__ or name == '__trace_call__': + return NotTracingWrapper(fullname, raw, self) + else: + return TracingWrapper(fullname, raw, self) class NotTracingWrapper: def __init__(self, name, func, inst): - self.__name__ = name - self.func = func - self.inst = inst + self.__name__ = name + self.func = func + self.inst = inst def __call__(self, *args, **kw): - return apply(self.func, (self.inst,) + args, kw) + return apply(self.func, (self.inst,) + args, kw) class TracingWrapper(NotTracingWrapper): def __call__(self, *args, **kw): - self.inst.__trace_call__(self.inst.__trace_output__, - "calling %s, inst=%s, args=%s, kw=%s", - self.__name__, self.inst, args, kw) - try: - rv = apply(self.func, (self.inst,) + args, kw) - except: - t, v, tb = sys.exc_info() - self.inst.__trace_call__(self.inst.__trace_output__, - "returning from %s with exception %s: %s", - self.__name__, t, v) - raise t, v, tb - else: - self.inst.__trace_call__(self.inst.__trace_output__, - "returning from %s with value %s", - self.__name__, rv) - return rv + self.inst.__trace_call__(self.inst.__trace_output__, + "calling %s, inst=%s, args=%s, kw=%s", + self.__name__, self.inst, args, kw) + try: + rv = apply(self.func, (self.inst,) + args, kw) + except: + t, v, tb = sys.exc_info() + self.inst.__trace_call__(self.inst.__trace_output__, + "returning from %s with exception %s: %s", + self.__name__, t, v) + raise t, v, tb + else: + self.inst.__trace_call__(self.inst.__trace_output__, + "returning from %s with value %s", + self.__name__, rv) + return rv Traced = TraceMetaClass('Traced', (), {'__trace_output__': None}) @@ -112,13 +112,13 @@ Traced = TraceMetaClass('Traced', (), {'__trace_output__': None}) def _test(): global C, D class C(Traced): - def __init__(self, x=0): self.x = x - def m1(self, x): self.x = x - def m2(self, y): return self.x + y - __trace_output__ = sys.stdout + def __init__(self, x=0): self.x = x + def m1(self, x): self.x = x + def m2(self, y): return self.x + y + __trace_output__ = sys.stdout class D(C): - def m2(self, y): print "D.m2(%s)" % `y`; return C.m2(self, y) - __trace_output__ = None + def m2(self, y): print "D.m2(%s)" % `y`; return C.m2(self, y) + __trace_output__ = None x = C(4321) print x print x.x |