def descr__getattribute__(space, w_obj, w_name): name = get_attribute_name(space, w_obj, w_name) w_descr = space.lookup(w_obj, name) if w_descr is not None: if space.is_data_descr(w_descr): # Only override if __get__ is defined, too, for compatibility # with CPython. w_get = space.lookup(w_descr, "__get__") if w_get is not None: w_type = space.type(w_obj) return space.get_and_call_function(w_get, w_descr, w_obj, w_type) w_value = w_obj.getdictvalue(space, name) if w_value is not None: return w_value if w_descr is not None: typ = type(w_descr) if typ is Function or typ is FunctionWithFixedCode: # This shortcut is necessary if w_obj is None. Otherwise e.g. # None.__eq__ would return an unbound function because calling # __get__ with None as the first argument returns the attribute # as if it was accessed through the owner (type(None).__eq__). return Method(space, w_descr, w_obj) return space.get(w_descr, w_obj) raiseattrerror(space, w_obj, w_name)
def PyMethod_New(space, w_func, w_self, w_cls): """Return a new method object, with func being any callable object; this is the function that will be called when the method is called. If this method should be bound to an instance, self should be the instance and class should be the class of self, otherwise self should be NULL and class should be the class which provides the unbound method.""" return Method(space, w_func, w_self, w_cls)
def cmethod_descr_get(space, w_function, w_obj, w_cls=None): asking_for_bound = (space.is_none(w_cls) or not space.is_w(w_obj, space.w_None) or space.is_w(w_cls, space.type(space.w_None))) if asking_for_bound: return space.wrap(Method(space, w_function, w_obj, w_cls)) else: return w_function
def taint_atomic(space, w_callable): """decorator to make a callable "taint-atomic": if the function is called with tainted arguments, those are untainted. The result of the function is tainted again. All exceptions that the callable raises are turned into taint bombs.""" meth = Method(space, space.w_fn_taint_atomic_function, w_callable, space.type(w_callable)) return space.wrap(meth)
def getattr(self, w_obj, w_name): # an optional shortcut for performance w_type = self.type(w_obj) w_descr = w_type.getattribute_if_not_from_object() if w_descr is not None: return self._handle_getattribute(w_descr, w_obj, w_name) # fast path: XXX this is duplicating most of the logic # from the default __getattribute__ and the getattr() method... name = get_attribute_name(self, w_obj, w_name) w_descr = w_type.lookup(name) e = None if w_descr is not None: w_get = None is_data = self.is_data_descr(w_descr) if is_data: w_get = self.lookup(w_descr, "__get__") if w_get is None: w_value = w_obj.getdictvalue(self, name) if w_value is not None: return w_value if not is_data: w_get = self.lookup(w_descr, "__get__") typ = type(w_descr) if typ is Function or typ is FunctionWithFixedCode: # This shortcut is necessary if w_obj is None. Otherwise e.g. # None.__eq__ would return an unbound function because calling # __get__ with None as the first argument returns the attribute # as if it was accessed through the owner (type(None).__eq__). return Method(self, w_descr, w_obj) if w_get is not None: # __get__ is allowed to raise an AttributeError to trigger # use of __getattr__. try: return self.get_and_call_function(w_get, w_descr, w_obj, w_type) except OperationError as e: if not e.match(self, self.w_AttributeError): raise else: return w_descr else: w_value = w_obj.getdictvalue(self, name) if w_value is not None: return w_value w_descr = self.lookup(w_obj, '__getattr__') if w_descr is not None: return self.get_and_call_function(w_descr, w_obj, w_name) elif e is not None: raise e else: raiseattrerror(self, w_obj, w_name)
def setup(self): super(AppTestMethod, self).setup() instance = self.parent.obj w_instance = self.parent.w_instance space = instance.space for name in dir(instance): if name.startswith('w_'): if self.config.option.runappdirect: setattr(instance, name[2:], getattr(instance, name)) else: obj = getattr(instance, name) if isinstance(obj, types.MethodType): source = py.std.inspect.getsource(obj).lstrip() w_func = space.appexec([], textwrap.dedent(""" (): %s return %s """) % (source, name)) w_obj = Method(space, w_func, w_instance, space.w_None) else: w_obj = obj space.setattr(w_instance, space.wrap(name[2:]), w_obj)
def cclassmethod_descr_get(space, w_function, w_obj, w_cls=None): if not w_cls: w_cls = space.type(w_obj) return space.wrap(Method(space, w_function, w_cls, space.w_None))
def descr_get(self, space, w_obj, w_klass=None): if space.is_none(w_obj): return self.w_function return Method(space, self.w_function, w_obj)
def lazy(space, w_callable): """Decorator to make a callable return its results wrapped in a thunk.""" meth = Method(space, space.w_fn_thunk, w_callable, space.type(w_callable)) return space.wrap(meth)
def PyMethod_New(space, w_func, w_self): """Return a new method object, with func being any callable object and self the instance the method should be bound. func is the function that will be called when the method is called. self must not be NULL.""" return Method(space, w_func, w_self)
def cmethod_descr_get(space, w_function, w_obj, w_cls=None): if w_obj is None or space.is_w(w_obj, space.w_None): return w_function else: return Method(space, w_function, w_obj)