[pypy-svn] r37336 - in pypy/dist/pypy/module/_dotnet: . test

antocuni at codespeak.net antocuni at codespeak.net
Thu Jan 25 16:19:20 CET 2007


Author: antocuni
Date: Thu Jan 25 16:19:19 2007
New Revision: 37336

Modified:
   pypy/dist/pypy/module/_dotnet/app_dotnet.py
   pypy/dist/pypy/module/_dotnet/interp_dotnet.py
   pypy/dist/pypy/module/_dotnet/test/test_dotnet.py
Log:
Added support for bound/unbound methods. Now it should be easy to
dynamically construct wrapper types.



Modified: pypy/dist/pypy/module/_dotnet/app_dotnet.py
==============================================================================
--- pypy/dist/pypy/module/_dotnet/app_dotnet.py	(original)
+++ pypy/dist/pypy/module/_dotnet/app_dotnet.py	Thu Jan 25 16:19:19 2007
@@ -1,15 +1,69 @@
 # NOT_RPYTHON
 
-class ArrayList(object):
-    __cliname__ = 'System.Collections.ArrayList'
-    ATTRS = ['Add']
+class MethodWrapper(object):
+    __slots__ = ('meth_name',)
+    
+    def __init__(self, meth_name):
+        self.meth_name = meth_name
+
+    def __get__(self, obj, type_):
+        if obj is None:
+            return UnboundMethod(type_, self.meth_name)
+        else:
+            return BoundMethod(self.meth_name, obj)
+
+    def __repr__(self):
+        return '%s(%s)' % (self.__class__.__name__, repr(self.meth_name))
+
+class UnboundMethod(object):
+    __slots__ = ('im_class', 'im_name')
+    
+    def __init__(self, im_class, im_name):
+        self.im_class = im_class
+        self.im_name = im_name
+
+    def __raise_TypeError(self, thing):
+        raise TypeError, 'unbound method %s() must be called with %s ' \
+              'instance as first argument (got %s instead)' % \
+              (self.im_name, self.im_class.__cliname__, thing)
+
+    def __call__(self, *args):
+        if len(args) == 0:
+            self.__raise_TypeError('nothing')
+        im_self = args[0]
+        if not isinstance(im_self, self.im_class):
+            self.__raise_TypeError('%s instance' % im_self.__class__.__name__)
+        return im_self.__cliobj__.call_method(self.im_name, args, 1) # ignore the first arg
+
+    def __repr__(self):
+        return '<unbound CLI method %s.%s>' % (self.im_class.__cliname__, self.im_name)
+
+
+class BoundMethod(object):
+    __slots__ = ('im_name', 'im_self')
+    
+    def __init__(self, im_name, im_self):
+        self.im_name = im_name
+        self.im_self = im_self
+
+    def __call__(self, *args):
+        return self.im_self.__cliobj__.call_method(self.im_name, args)
+
+    def __repr__(self):
+        return '<bound CLI method %s.%s of %s>' % (self.im_self.__class__.__cliname__, self.im_name, self.im_self)
+
+
+class CliClassWrapper(object):
+    __slots__ = ('__cliobj__',)
 
     def __init__(self):
         import _dotnet
-        self.obj = _dotnet._CliObject_internal(self.__cliname__)
+        self.__cliobj__ = _dotnet._CliObject_internal(self.__cliname__)
+
 
-    def Add(self, x):
-        return self.obj.call_method('Add', [x])
+class ArrayList(CliClassWrapper):
+    __cliname__ = 'System.Collections.ArrayList'
 
-    def get_Item(self, idx):
-        return self.obj.call_method('get_Item', [idx])
+    Add = MethodWrapper('Add')
+    get_Item = MethodWrapper('get_Item')
+    __getitem__ = get_Item

Modified: pypy/dist/pypy/module/_dotnet/interp_dotnet.py
==============================================================================
--- pypy/dist/pypy/module/_dotnet/interp_dotnet.py	(original)
+++ pypy/dist/pypy/module/_dotnet/interp_dotnet.py	Thu Jan 25 16:19:19 2007
@@ -16,10 +16,10 @@
         self.space = space
         self.b_obj = b_obj
 
-    def call_method(self, name, w_args):
+    def call_method(self, name, w_args, startfrom=0):
         b_type = self.b_obj.GetType()
         b_meth = b_type.GetMethod(name) # TODO: overloading!
-        b_args = self.rewrap_args(w_args)
+        b_args = self.rewrap_args(w_args, startfrom)
         try:
             # for an explanation of the box() call, see the log message for revision 35167
             b_res = box(b_meth.Invoke(self.b_obj, b_args))
@@ -29,13 +29,13 @@
             # TODO: use the appropriate exception, not StandardError
             raise OperationError(self.space.w_StandardError, self.space.wrap(message))
         return self.cli2py(b_res)
-    call_method.unwrap_spec = ['self', str, W_Root]
+    call_method.unwrap_spec = ['self', str, W_Root, int]
 
-    def rewrap_args(self, w_args):
+    def rewrap_args(self, w_args, startfrom):
         args = self.space.unpackiterable(w_args)
-        b_res = new_array(System.Object, len(args))
-        for i in range(len(args)):
-            b_res[i] = self.py2cli(args[i])
+        b_res = new_array(System.Object, len(args)-startfrom)
+        for i in range(startfrom, len(args)):
+            b_res[i-startfrom] = self.py2cli(args[i])
         return b_res
 
     def py2cli(self, w_obj):

Modified: pypy/dist/pypy/module/_dotnet/test/test_dotnet.py
==============================================================================
--- pypy/dist/pypy/module/_dotnet/test/test_dotnet.py	(original)
+++ pypy/dist/pypy/module/_dotnet/test/test_dotnet.py	Thu Jan 25 16:19:19 2007
@@ -31,3 +31,20 @@
         obj.Add(42.0)
         item = obj.get_Item(0)
         assert isinstance(item, float)
+
+    def test_getitem(self):
+        import _dotnet
+        obj = _dotnet.ArrayList()
+        obj.Add(42)
+        assert obj[0] == 42
+
+    def test_unboundmethod(self):
+        import _dotnet
+        obj = _dotnet.ArrayList()
+        _dotnet.ArrayList.Add(obj, 42)
+        assert obj.get_Item(0) == 42
+
+    def test_unboundmethod_typeerror(self):
+        import _dotnet
+        raises(TypeError, _dotnet.ArrayList.Add)
+        raises(TypeError, _dotnet.ArrayList.Add, 0)



More information about the Pypy-commit mailing list