1. Pypy
  2. Untitled project
  3. pypy

Commits

Amaury Forgeot d'Arc  committed 6cb72bc

cpyext: implement PyInstanceMethod type and functions.

  • Participants
  • Parent commits 21d4c1b
  • Branches py3k

Comments (0)

Files changed (4)

File pypy/module/cpyext/__init__.py

View file
  • Ignore whitespace
 import pypy.module.cpyext.weakrefobject
 import pypy.module.cpyext.funcobject
 import pypy.module.cpyext.frameobject
+import pypy.module.cpyext.classobject
 import pypy.module.cpyext.pypyintf
 import pypy.module.cpyext.exception
 import pypy.module.cpyext.memoryobject

File pypy/module/cpyext/api.py

View file
  • Ignore whitespace
         'Slice': 'space.gettypeobject(W_SliceObject.typedef)',
         'StaticMethod': 'space.gettypeobject(StaticMethod.typedef)',
         'CFunction': 'space.gettypeobject(cpyext.methodobject.W_PyCFunctionObject.typedef)',
-        'WrapperDescr': 'space.gettypeobject(cpyext.methodobject.W_PyCMethodObject.typedef)'
+        'WrapperDescr': 'space.gettypeobject(cpyext.methodobject.W_PyCMethodObject.typedef)',
+        'InstanceMethod': 'space.gettypeobject(cpyext.classobject.InstanceMethod.typedef)',
         }.items():
         GLOBALS['Py%s_Type#' % (cpyname, )] = ('PyTypeObject*', pypyexpr)
 

File pypy/module/cpyext/classobject.py

View file
  • Ignore whitespace
+from pypy.rpython.lltypesystem import rffi, lltype
+from pypy.module.cpyext.api import cpython_api, CANNOT_FAIL
+from pypy.module.cpyext.pyobject import PyObject
+from pypy.interpreter.baseobjspace import Wrappable
+from pypy.interpreter.function import Method
+from pypy.interpreter.typedef import TypeDef, interp_attrproperty_w
+from pypy.interpreter.gateway import interp2app
+
+
+class InstanceMethod(Wrappable):
+    """The instancemethod facade."""
+    _immutable_fields_ = ['w_function']
+
+    def __init__(self, w_function):
+        self.w_function = w_function
+
+    @staticmethod
+    def descr_new(space, w_subtype, w_function):
+        # instancemethod is not subclassable
+        return space.wrap(InstanceMethod(w_function))
+
+    def descr_get(self, space, w_obj, w_klass=None):
+        if space.is_none(w_obj):
+            return self.w_function
+        return space.wrap(Method(space, self.w_function, w_obj))
+
+    def descr_call(self, space, __args__):
+        return space.call_args(self.w_function, __args__)
+
+    def descr_repr(self, space):
+        name = space.str_w(
+            space.getattr(self.w_function, space.wrap('__name__')))
+        return self.getrepr(space, '<instancemethod %s>' % (name,))
+
+InstanceMethod.typedef = TypeDef("instancemethod",
+    __new__ = interp2app(InstanceMethod.descr_new),
+    __call__ = interp2app(InstanceMethod.descr_call,
+                          descrmismatch='__call__'),
+    __get__ = interp2app(InstanceMethod.descr_get),
+    __repr__ = interp2app(InstanceMethod.descr_repr,
+                          descrmismatch='__repr__'),
+    __func__= interp_attrproperty_w('w_function', cls=InstanceMethod),
+)
+InstanceMethod.typedef.acceptable_as_base_class = False
+
+@cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL)
+def PyInstanceMethod_Check(space, w_o):
+    """Return true if o is an instance method object (has type
+    PyInstanceMethod_Type).  The parameter must not be NULL."""
+    return space.isinstance_w(w_o,
+                              space.gettypeobject(InstanceMethod.typedef))
+    
+
+@cpython_api([PyObject], PyObject)
+def PyInstanceMethod_New(space, w_func):
+    """Return a new instance method object, with func being any
+    callable object func is the function that will be called when the
+    instance method is called."""
+    return space.wrap(InstanceMethod(w_func))
+    
+
+@cpython_api([PyObject], PyObject)
+def PyInstanceMethod_Function(space, w_im):
+    """Return the function object associated with the instance method im."""
+    return space.interp_w(InstanceMethod, w_im).w_function
+    
+
+@cpython_api([PyObject], PyObject)
+def PyInstanceMethod_GET_FUNCTION(space, w_im):
+    """Macro version of PyInstanceMethod_Function() which avoids error
+    checking."""
+    return space.interp_w(InstanceMethod, w_im).w_function
+    
+

File pypy/module/cpyext/test/test_classobject.py

View file
  • Ignore whitespace
+from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
+
+class AppTestInstanceMethod(AppTestCpythonExtensionBase):
+    def test_instancemethod(self):
+        module = self.import_extension('foo', [
+            ("instancemethod", "METH_O",
+             """
+                 return PyInstanceMethod_New(args);
+             """)])
+
+        def testfunction(self):
+            """some doc"""
+            return self
+
+        class InstanceMethod:
+            id = module.instancemethod(id)
+            testmethod = module.instancemethod(testfunction)
+
+        inst = InstanceMethod()
+        assert id(inst) == inst.id()
+        assert inst.testmethod() is inst
+        assert InstanceMethod.testmethod(inst) is inst
+        assert InstanceMethod.__dict__['testmethod'](inst) is inst
+        assert inst.testmethod.__doc__ == testfunction.__doc__
+        assert InstanceMethod.testmethod.__doc__ == testfunction.__doc__
+
+        InstanceMethod.testmethod.attribute = "test"
+        assert testfunction.attribute == "test"
+        raises(AttributeError, setattr, inst.testmethod, "attribute", "test")