from inspect import isfunction
import thread
class ThreadStack(object):
"An object that keeps a separate stack for each frame"
def __init__(self):
self.stacks = {}
def push(self, val):
key = thread.get_ident()
try:
stack = self.stacks[key]
except KeyError:
stack = self.stacks[key] = [None]
stack.append(val)
def pop(self):
return self.stacks[thread.get_ident()].pop()
def top(self):
return self.stacks[thread.get_ident()][-1]
__callerstack__ = ThreadStack()
class function(object):
"A function. It knows what class it is defined in"
def __init__(self, f, callerclass=None):
self.data = f, callerclass
def __call__(self, *args, **kwargs):
f, callerclass = self.data
try:
__callerstack__.push(callerclass)
return f(*args, **kwargs)
finally:
__callerstack__.pop()
class method(object):
"A normal class method, visible from outside the class"
def __init__(self, f):
self.f = f
def __get__(self, obj, objtype=None):
return function(self.f.__get__(obj, objtype), self.defclass)
class LocalMethodError(AttributeError):
pass
class localmethod(method):
"A method that cannot be seen from outside its definition class"
def __get__(self, obj, objtype=None):
defclass = self.defclass
callerclass = __callerstack__.top()
if callerclass is defclass:
return self.f.__get__(obj, objtype)
else:
mro = iter( (obj and type(obj) or objtype).mro() )
for c in mro:
if c == defclass: break
name = self.name
for base in mro:
try:
attr = base.__dict__[name]
if base is callerclass or not isinstance(attr, localmethod):
return attr.__get__(obj, objtype)
except KeyError:
continue
raise LocalMethodError, "method '%s' is local to '%s'" % (self.name, self.defclass.__name__)
class Type(type):
"Replaces type"
def __new__(self, name, bases, attrs):
for attr, val in attrs.items():
if isfunction(val):
attrs[attr] = method(val)
return type.__new__(self, name, bases, attrs)
def __init__(self, name, bases, attrs):
for attr, val in attrs.iteritems():
if isinstance(val, method):
val.defclass = self
if isinstance(val, localmethod):
val.name = attr
class Object(object):
"Replaces object"
__metaclass__ = Type