# NOT_RPYTHON class StaticMethodWrapper(object): __slots__ = ('class_name', 'meth_name',) def __init__(self, class_name, meth_name): self.class_name = class_name self.meth_name = meth_name def __call__(self, *args): import clr return clr.call_staticmethod(self.class_name, self.meth_name, args) def __repr__(self): return '' % (self.class_name, self.meth_name) 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.__cliclass__, 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 '' % (self.im_class.__cliclass__, 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 '' % (self.im_self.__class__.__cliclass__, self.im_name, self.im_self) class StaticProperty(object): def __init__(self, fget=None, fset=None): self.fget = fget self.fset = fset def __get__(self, obj, type_): return self.fget() def _qualify(t): mscorlib = 'mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' return '%s, %s' % (t, mscorlib) class MetaGenericCliClassWrapper(type): _cli_types = { int: _qualify('System.Int32'), str: _qualify('System.String'), bool: _qualify('System.Boolean'), float: _qualify('System.Double'), } _System_Object = _qualify('System.Object') def _cli_name(cls, ttype): if isinstance(ttype, MetaCliClassWrapper): return '[%s]' % ttype.__fullyqualifiedname__ else: return '[%s]' % cls._cli_types.get(ttype, cls._System_Object) def __setattr__(cls, name, value): obj = cls.__dict__.get(name, None) if isinstance(obj, StaticProperty): obj.fset(value) else: type.__setattr__(cls, name, value) def __getitem__(cls, type_or_tuple): import clr if isinstance(type_or_tuple, tuple): types = type_or_tuple else: types = (type_or_tuple,) namespace, generic_class = cls.__cliclass__.rsplit('.', 1) generic_params = [cls._cli_name(t) for t in types] instance_class = '%s[%s]' % (generic_class, ','.join(generic_params)) try: return clr.load_cli_class(cls.__assemblyname__, namespace, instance_class) except ImportError: raise TypeError, "Cannot load type %s.%s" % (namespace, instance_class) class MetaCliClassWrapper(type): def __setattr__(cls, name, value): obj = cls.__dict__.get(name, None) if isinstance(obj, StaticProperty): obj.fset(value) else: type.__setattr__(cls, name, value) class CliClassWrapper(object): __slots__ = ('__cliobj__',) def __init__(self, *args): import clr self.__cliobj__ = clr._CliObject_internal(self.__fullyqualifiedname__, args) class IEnumeratorWrapper(object): def __init__(self, enumerator): self.__enumerator__ = enumerator def __iter__(self): return self def next(self): if not self.__enumerator__.MoveNext(): raise StopIteration return self.__enumerator__.Current # this method need to be attached only to classes that implements IEnumerable (see build_wrapper) def __iter__(self): return IEnumeratorWrapper(self.GetEnumerator()) def wrapper_from_cliobj(cls, cliobj): obj = cls.__new__(cls) obj.__cliobj__ = cliobj return obj def build_wrapper(namespace, classname, assemblyname, staticmethods, methods, properties, indexers, hasIEnumerable, isClassGeneric): fullname = '%s.%s' % (namespace, classname) assembly_qualified_name = '%s, %s' % (fullname, assemblyname) d = {'__cliclass__': fullname, '__fullyqualifiedname__': assembly_qualified_name, '__assemblyname__': assemblyname, '__module__': namespace} for name in staticmethods: d[name] = StaticMethodWrapper(assembly_qualified_name, name) for name in methods: d[name] = MethodWrapper(name) # check if IEnumerable is implemented if hasIEnumerable: d['__iter__'] = __iter__ assert len(indexers) <= 1 if indexers: name, getter, setter, is_static = indexers[0] assert not is_static if getter: d['__getitem__'] = d[getter] if setter: d['__setitem__'] = d[setter] if isClassGeneric: cls = MetaGenericCliClassWrapper(classname, (CliClassWrapper,), d) else: cls = MetaCliClassWrapper(classname, (CliClassWrapper,), d) # we must add properties *after* the class has been created # because we need to store UnboundMethods as getters and setters for (name, getter, setter, is_static) in properties: fget = None fset = None if getter: fget = getattr(cls, getter) if setter: fset = getattr(cls, setter) if is_static: prop = StaticProperty(fget, fset) else: prop = property(fget, fset) setattr(cls, name, prop) return cls