[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