[pypy-svn] r49811 - in pypy/branch/clr-module-improvements/pypy/module/clr: . test

regmee at codespeak.net regmee at codespeak.net
Fri Dec 14 23:11:41 CET 2007


Author: regmee
Date: Fri Dec 14 23:11:39 2007
New Revision: 49811

Modified:
   pypy/branch/clr-module-improvements/pypy/module/clr/__init__.py
   pypy/branch/clr-module-improvements/pypy/module/clr/app_clr.py
   pypy/branch/clr-module-improvements/pypy/module/clr/app_importer.py
   pypy/branch/clr-module-improvements/pypy/module/clr/interp_clr.py
   pypy/branch/clr-module-improvements/pypy/module/clr/test/test_clr.py
Log:
Support for Generic classes with a single import for System.Collection.Generic, Few test cases, Import needs slight improvement

Modified: pypy/branch/clr-module-improvements/pypy/module/clr/__init__.py
==============================================================================
--- pypy/branch/clr-module-improvements/pypy/module/clr/__init__.py	(original)
+++ pypy/branch/clr-module-improvements/pypy/module/clr/__init__.py	Fri Dec 14 23:11:39 2007
@@ -14,7 +14,8 @@
         '_CliObject_internal': 'interp_clr.W_CliObject',
         'call_staticmethod': 'interp_clr.call_staticmethod',
         'load_cli_class': 'interp_clr.load_cli_class',
-        'load_valid_namespaces': 'interp_clr.load_valid_namespaces',
+        'list_of_valid_namespaces': 'interp_clr.list_of_valid_namespaces',
+        'list_of_generic_classes': 'interp_clr.list_of_generic_classes',
         'isDotNetType': 'interp_clr.isDotNetType',
         'load_assembly': 'interp_clr.load_assembly',
         'list_of_loadedAssemblies': 'interp_clr.list_of_loadedAssemblies',

Modified: pypy/branch/clr-module-improvements/pypy/module/clr/app_clr.py
==============================================================================
--- pypy/branch/clr-module-improvements/pypy/module/clr/app_clr.py	(original)
+++ pypy/branch/clr-module-improvements/pypy/module/clr/app_clr.py	Fri Dec 14 23:11:39 2007
@@ -78,6 +78,46 @@
     def __get__(self, obj, type_):
         return self.fget()
 
+class MetaGenericCliClassWrapper(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)
+
+    def __getitem__(cls,*args):
+        #cls.__cliclass__ ='System.Collections.Generic.Dictionary`2'
+        rightDot = cls.__cliclass__.rfind('.')
+        rightTilde = cls.__cliclass__.rfind('`')
+        load_cli_class_leftArg = cls.__cliclass__[:rightDot]
+        genClassName = cls.__cliclass__[rightDot+1: rightTilde] 
+        genClassNumArgs = int(cls.__cliclass__[rightTilde +1 :])
+        import clr
+        try:
+            ln = len(args[0])
+            # put a check for the number of arguments passed for the Generic class
+            if ln != genClassNumArgs:
+                raise "InvalidArgumentList"
+            else:
+                lindex = str(args[0][0]).find('\'')
+                rindex = str(args[0][0]).rfind('\'')
+                load_cli_class_rightArg = genClassName 
+                load_cli_class_rightArg += "`%s[%s"%(ln,str(args[0][0])[lindex+1:rindex])
+                for i in range(1,ln):
+                    lindex = str(args[0][i]).find('\'')
+                    rindex = str(args[0][i]).rfind('\'')
+                    load_cli_class_rightArg += ",%s"%str(args[0][i])[lindex+1:rindex]
+                load_cli_class_rightArg += "]"
+                return clr.load_cli_class(load_cli_class_leftArg,load_cli_class_rightArg)
+        except:
+            # it's a single arg passed
+            lindex = str(args[0]).find('\'')
+            rindex = str(args[0]).rfind('\'')
+            load_cli_class_rightArg = genClassName 
+            load_cli_class_rightArg += "`1[%s]"%(str(args[0])[lindex+1:rindex])
+            return clr.load_cli_class(load_cli_class_leftArg,load_cli_class_rightArg)
+
 class MetaCliClassWrapper(type):
     def __setattr__(cls, name, value):
         obj = cls.__dict__.get(name, None)
@@ -115,7 +155,7 @@
     obj.__cliobj__ = cliobj
     return obj
 
-def build_wrapper(namespace, classname, staticmethods, methods, properties, indexers, hasIEnumerable):
+def build_wrapper(namespace, classname, staticmethods, methods, properties, indexers, hasIEnumerable, isClassGeneric):
     fullname = '%s.%s' % (namespace, classname)
     d = {'__cliclass__': fullname,
          '__module__': namespace}
@@ -136,7 +176,10 @@
             d['__getitem__'] = d[getter]
         if setter:
             d['__setitem__'] = d[setter]
-    cls = MetaCliClassWrapper(classname, (CliClassWrapper,), d)
+    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

Modified: pypy/branch/clr-module-improvements/pypy/module/clr/app_importer.py
==============================================================================
--- pypy/branch/clr-module-improvements/pypy/module/clr/app_importer.py	(original)
+++ pypy/branch/clr-module-improvements/pypy/module/clr/app_importer.py	Fri Dec 14 23:11:39 2007
@@ -62,6 +62,13 @@
             # add it to the modules list
             sys.modules[fullname] = mod
 
+            # treating System.Collections.Generic specially here.
+            # this treatment is done after the empty module insertion
+            if fullname == "System.Collections.Generic":
+                genericClassList = clr.list_of_generic_classes()
+                for genericClass in genericClassList:
+                    sys.modules[genericClass[: genericClass.find('`')]] = clr.load_cli_class("System.Collections.Generic", genericClass)
+
         return sys.modules[fullname]
 
 class importer(object):
@@ -78,7 +85,7 @@
     def __init__(self):
         import clr
         # this might not be the correct place to load the valid NameSpaces
-        self.ValidNameSpaces = clr.load_valid_namespaces()
+        self.ValidNameSpaces = clr.list_of_valid_namespaces()
         self.loader = loader()
 
     def find_module(self, fullname, path = None):

Modified: pypy/branch/clr-module-improvements/pypy/module/clr/interp_clr.py
==============================================================================
--- pypy/branch/clr-module-improvements/pypy/module/clr/interp_clr.py	(original)
+++ pypy/branch/clr-module-improvements/pypy/module/clr/interp_clr.py	Fri Dec 14 23:11:39 2007
@@ -185,7 +185,7 @@
         return self.cache.get(fullname, None)
 CliClassCache = _CliClassCache()
 
-def load_valid_namespaces(space):
+def list_of_valid_namespaces(space):
     """
     We use this function to play with reflection
     and then return useful data to the app_importer module
@@ -206,6 +206,36 @@
     w_listOfNamespaces = wrap_list_of_strings(space, listOfNamespaces)
     return w_listOfNamespaces
 
+def list_of_generic_classes(space):
+    """
+    use reflection to get a list of generic classes 
+
+    Return: List of generic classes
+    e.g. [Dictionary`2 , List`1 , IEnumerator`1 , IEnumerable`1]
+    """
+    listOfGenericTypes = []
+    currentDomain = System.AppDomain.get_CurrentDomain()
+    assems = currentDomain.GetAssemblies()
+    for loadedAssembly in assems:
+        typesInAssembly = loadedAssembly.GetTypes()
+        for type in typesInAssembly:
+            namespace = type.get_Namespace()
+            type_str = type.ToString()
+            if namespace == "System.Collections.Generic":
+                rightDot = type_str.rfind('.')
+                rightTilde = type_str.rfind('`')
+                firstSqBracket = type_str.find('[')
+                firstPlus = type_str.find('+')
+                if rightDot != -1 and rightTilde != -1:
+                    if firstPlus == -1:
+                        nameToPush = type_str[rightDot+1 : firstSqBracket] 
+                    else:
+                        nameToPush = type_str[rightDot+1 : firstPlus] 
+                    if nameToPush not in listOfGenericTypes:
+                        listOfGenericTypes.append(nameToPush) 
+    w_listOfGenericTypes = wrap_list_of_strings(space, listOfGenericTypes)
+    return w_listOfGenericTypes
+
 def isDotNetType(space, nameFromImporter):
     """
         determines if the string input is a DotNetType
@@ -302,6 +332,12 @@
         if interface.ToString() == "System.Collections.IEnumerable":
             hasIEnumerable = True
 
+    # this is where we test if the class is Generic 
+    # set the flag isClassGeneric 
+    isClassGeneric = False
+    if b_type.IsGenericType:
+        isClassGeneric = True
+
     w_staticmethods, w_methods = get_methods(space, b_type)
     w_properties, w_indexers = get_properties(space, b_type)
     return build_wrapper(space,
@@ -311,7 +347,8 @@
                          w_methods,
                          w_properties,
                          w_indexers,
-                         space.wrap(hasIEnumerable))
+                         space.wrap(hasIEnumerable),
+                         space.wrap(isClassGeneric))
 
 
 class W_CliObject(Wrappable):

Modified: pypy/branch/clr-module-improvements/pypy/module/clr/test/test_clr.py
==============================================================================
--- pypy/branch/clr-module-improvements/pypy/module/clr/test/test_clr.py	(original)
+++ pypy/branch/clr-module-improvements/pypy/module/clr/test/test_clr.py	Fri Dec 14 23:11:39 2007
@@ -160,7 +160,7 @@
         enum = x.GetEnumerator()
         assert enum.MoveNext() is False
 
-    def test_iteration(self):
+    def test_iteration_arrayList(self):
         import clr
         ArrayList = clr.load_cli_class('System.Collections', 'ArrayList')
         x = ArrayList()
@@ -215,3 +215,18 @@
         raises(TypeError, x.__setitem__, 4, 4.453)
         raises(TypeError, x.__setitem__, "test", 3)
 
+    def test_generic_class_with_single_import(self):
+        import clr
+        import System.Collections.Generic
+        import List
+        import System.Int32
+        l2 = List[System.Int32]()
+        l2.Add(3)
+        raises(TypeError, l2.Add, "test")
+
+        import Dictionary
+        import System.String
+        d1 = Dictionary[System.Int32,System.String]()
+        d1[1]="test"
+        raises(TypeError, d1.__setitem__, 3, 3)
+



More information about the Pypy-commit mailing list