Commits

Ronald Oussoren committed c2a8a10

More work on bridgesupport tests (with some bugfixes)

Comments (0)

Files changed (2)

pyobjc-core/Lib/objc/_bridgesupport.py

     '/System/Library/BridgeSupport',
 ]
 
+_SENTINEL=object()
 _DEFAULT_SUGGESTION="don't use this method"
 _BOOLEAN_ATTRIBUTES=[
     "already_retained",
         result = {}
 
         if is_arg:
-            argIdx = int(self.attribute_string(node, "index", None))
+            argIdx = self.attribute_string(node, "index", None)
+            if argIdx is None:
+                return None, None
+            argIdx = int(argIdx)
 
         s = self.attribute_string(node, "type", "type64")
         if s:
             c_array  = self.attribute_bool(  method, "c_array_delimited_by_null", None, False)
             c_length = self.attribute_string(method, "c_array_length_in_arg", None)
             ignore   = self.attribute_bool(  method, "ignore", None, False)
+
+            is_class = self.attribute_bool(method, "classmethod", None, _SENTINEL)
+            if is_class is _SENTINEL:
+                # Manpage says 'class_method', older PyObjC used 'classmethod' 
+                is_class = self.attribute_bool(method, "class_method", None, False)
             
             if sel_name is None:
                 continue
                     suggestion = _DEFAULT_SUGGESTION
 
                 metadata['suggestion'] = suggestion
-            metadata['variadic'] = variadic
+
+                # Force minimal metadata for ignored methods
+                self.meta[(_as_bytes(class_name), _as_bytes(sel_name), is_class)] = metadata
+                continue
+
             if variadic:
+                metadata['variadic'] = True
                 if c_array:
                     metadata['c_array_delimited_by_null'] = c_array
 
             for al in method:
                 if al.tag == "arg":
                     arg_idx, meta = self.xml_to_arg(al, True, True)
-                    arguments[arg_idx+2] = meta
+                    if arg_idx is not None and meta:
+                        arguments[arg_idx+2] = meta
 
                 elif al.tag == "retval":
                     _, meta = self.xml_to_arg(al, True, False)
-                    metadata['retval'] = meta
+                    if meta:
+                        metadata['retval'] = meta
 
-            self.meta[(_as_bytes(class_name), _as_bytes(sel_name))] = metadata
+            if not arguments:
+                # No argument metadata after all.
+                del metadata['arguments']
+
+            if metadata:
+                self.meta[(_as_bytes(class_name), _as_bytes(sel_name), is_class)] = metadata
 
 
     def do_enum(self, node):
         for al in node:
             if al.tag == "arg":
                 _, d = self.xml_to_arg(al, False, False)
+                if "type" not in d:
+                    # Ignore functions without type info
+                    return
                 siglist.append(d["type"])
 
                 arguments[len(siglist)-2] = d
 
             elif al.tag == "retval":
                 _, d = self.xml_to_arg(al, False, False)
+                if "type" not in d:
+                    # Ignore functions without type info
+                    return
                 siglist[0] = d["type"]
                 meta["retval"] = d
 
         for method in node:
             sel_name = self.attribute_string(method, "selector", None)
             typestr  = self.attribute_string(method, "type", "type64")
-            is_class = self.attribute_bool(method, "classmethod", None, False)
+            is_class = self.attribute_bool(method, "classmethod", None, _SENTINEL)
+            if is_class is _SENTINEL:
+                # Manpage says 'class_method', older PyObjC used 'classmethod' 
+                is_class = self.attribute_bool(method, "class_method", None, False)
 
             if not sel_name or not typestr:
                 continue
 
             globals[name] = value
 
-        for class_name, sel_name in prs.meta:
-            objc.registerMetaDataForSelector(class_name, sel_name, prs.meta[(class_name, sel_name)])
+        for class_name, sel_name, is_class in prs.meta:
+            objc.registerMetaDataForSelector(class_name, sel_name, prs.meta[(class_name, sel_name, is_class)])
 
         for name, typestr in prs.opaque:
             globals[name] = objc.createOpaquePointerType(name, typestr)
     
     return bundle
 
-_ivar_dict = objc._ivar_dict()
-del objc._ivar_dict
+_ivar_dict = objc._objc._ivar_dict()
+if hasattr(objc, '_ivar_dict'):
+    del objc._ivar_dict
 def _structConvenience(structname, structencoding):
     def makevar(self, name=None):
         if name is None:

pyobjc-core/PyObjCTest/test_bridgesupport.py

 import objc._bridgesupport as bridgesupport
 import os
 import re
+import sys
+import imp
+import ctypes
 
 import xml.etree.ElementTree as ET 
 
 
 IDENTIFIER=re.compile(r"^[A-Za-z_][A-Za-z0-9_]*$")
 
-# XXX: add all supported metadata to TEST_XML, validate in test_xml_structure
 TEST_XML="""\
 <signatures>
   <unknown><!-- ignore -->
   <opaque name='opaque2' type='^{opaque2=f}' type64='^{opaque2=d}' />
   <opaque type='^{opaque2=f}' type64='^{opaque2=d}' /><!-- ignore -->
   <opaque name='opaque3' /><!-- ignore -->
-  <opaque name='opaque4' type64='^{opaque2=d}' /><!-- ignore 32-bit -->
+  <opaque name='opaque4' type64='^{opaque4=d}' /><!-- ignore 32-bit -->
   <opaque /><!-- ignore -->
   <constant name='constant1' type='@'/>
   <constant name='constant2' type='I' type64='Q' />
   <constant type='@'/><!-- ignore -->
   <constant name='constant3' /><!-- ignore -->
-  <constant name='constant2' type64='Q' /><!-- ignore 32-bit -->
+  <constant name='constant4' type64='Q' /><!-- ignore 32-bit -->
+  <constant name='constant5' type='B' /><!-- NSBOOL -->
+  <constant name='constant6' type='Z' /><!-- bool -->
+  <constant name='constant7' type='@' magic_cookie='false' />
+  <constant name='constant8' type='@' magic_cookie='true' />
   <constant /><!-- ignore -->
   <string_constant name='strconst1' value='string constant1' />
   <string_constant name='strconst2' value='string constant 2' value64='string constant two' />
   <string_constant name='strconst3' /><!-- ignore -->
   <string_constant name='strconst4' nsstring='true' /><!-- ignore -->
   <string_constant name='strconst5' value64='string five' /><!-- ignore 32-bit -->
-  <string_constant name='strconst5' value64='string five unicode' nsstring='true' /><!-- ignore 32-bit -->
+  <string_constant name='strconst6' value64='string five unicode' nsstring='true' /><!-- ignore 32-bit -->
   <string_constant /><!-- ignore -->
   <enum name='enum1' value='1' />
   <enum name='enum2' value='3' value64='4'/>
   <enum name='enum6' value64='4'/><!-- ignore 32-bit -->
   <enum name='enum7' be_value64='6' /><!-- ignore intel -->
   <enum name='enum8' le_value='5' /><!-- ignore ppc -->
+  <enum name='enum9' value='2.5' />
+  <enum name='enum10' value='0x1.5p+3' />
   <enum /><!-- ignore -->
-  <null_constant name='null1' />
-  <null_constant /><!-- ignore -->
-  <function_pointer name='func1' orginal='orig_function' />
+  <null_const name='null1' />
+  <null_const /><!-- ignore -->
+  <function_pointer name='func1' original='orig_function' />
   <function_pointer name='func2' /><!-- ignore -->
   <function_pointer original='func3' /><!-- ignore -->
   <function_pointer /><!-- ignore -->
   <cftype name='CFProxy3Ref' type='^{CFProxy3}' tollfree='NSProxy' gettypeid_func='CFArrayGetTypeID' />
   <cftype name='CFProxy4Ref' type='^{CFProxy4}' tollfree='NSProxy2' />
   <cftype name='CFProxy5Ref' type='^{CFProxy}' gettypeid_func='NoSuchFunction' /><!-- tollfree to CFTypeRef -->
-  <cftype name='CFProxy6Ref' type='^{CFProxy}' /><!-- ignore: no typeid -->
-  <cftype name='CFProxy7Ref' type='^{CFProxy32}' type64='^{CFProxy64}' /><!-- ignore: no typeid -->
+  <cftype name='CFProxy6Ref' type='^{CFProxy}' />
+  <cftype name='CFProxy7Ref' type='^{CFProxy32}' type64='^{CFProxy64}' />
   <cftype type='^{CFProxy}' gettypeid_func='CFArrayGetTypeID' /><!-- ignore -->
   <cftype name='CFProxy8Ref' gettypeid_func='CFArrayGetTypeID' /><!-- ignore -->
   <cftype name='CFProxy9Ref' type64='^{CFProxy64}' gettypeid_func='CFArrayGetTypeID' /><!-- ignore 32-bit -->
   <class name='MyClass1'></class>
   <class /><!-- ignore -->
   <class name='MyClass2'>
-    <method selector='method1'></method>
+    <method selector='method1' classmethod='true' ></method>
     <method selector='method2' variadic='true' ></method>
     <method selector='method3' variadic='true' c_array_delimited_by_null='true'></method>
     <method selector='method4' variadic='true' c_array_length_in_arg='4'></method>
     <method selector='method10'>
        <retval type='d'/>
     </method>
-    <method selector='method11'>
+    <method selector='method11' classmethod='false'>
        <retval type='f' type64='d' />
     </method>
-    <method selector='method12'>
+    <method selector='method12' classmethod='true'>
        <retval/><!-- ignore -->
     </method>
-    <method selector='method13'>
+    <method selector='method13' class_method='true'>
        <retval type_modifier='n' />
     </method>
-    <method selector='method13'>
+    <method selector='method13b' class_method='false'>
        <retval sel_of_type='v@:f' c_array_of_fixed_length='4'/>
     </method>
     <method selector='method14'>
        <retval sel_of_type='v@:f' sel_of_type64='v@:d' />
     </method>
     <method selector='method15'>
-       <retval null_accepted='false' already_retained='true' already_cfretained='false' c_array_length_in_result='true' />
+       <retval null_accepted='false' already_retained='true' c_array_length_in_result='true' />
     </method>
     <method selector='method16'>
-       <retval c_array_delimited_by_null='true' c_array_of_variable_length='false' printf_format='true' free_result='true' />
+       <retval c_array_delimited_by_null='true' already_cfretained='true' c_array_of_variable_length='true' printf_format='true' free_result='true' />
     </method>
     <method selector='method17'>
-       <retval c_array_lenght_in_arg='1'/>
+       <retval c_array_length_in_arg='1'/>
     </method>
     <method selector='method18'>
-       <retval c_array_lenght_in_arg='1,2'/>
+       <retval c_array_length_in_arg='1,2'/>
     </method>
     <method selector='method19'>
-       <retval c_array_lenght_in_arg='4, 5'/>
+       <retval c_array_length_in_arg='4, 5'/>
     </method>
     <method selector='method20'>
        <retval function_pointer_retained='true'/><!-- ignored, no function data -->
           <arg type='d' />
        </retval>
     </method>
-    <!-- TODO: 'argument' and 'retval' nodes -->
     <method ></method><!-- ignore -->
     <method variadic='true'></method><!-- ignore -->
     <method ignore='true'></method><!-- ignore -->
   </class>
-  <function/><!-- TODO -->
-  <informal_protocol/><!-- TODO: no name, empty, methods -->
-  <struct/><!-- TODO -->
+  <class name='MyClass3'>
+    <method selector='method7'>
+       <retval type='q' />
+       <arg index='1' type='f'/>
+       <arg index='2' type='d'/>
+    </method>
+    <method selector='method8'>
+       <arg index='1' type='d'/>
+       <arg index='2' type='d'/>
+    </method>
+    <method selector='method9'>
+       <arg type='d'/><!-- ignored: no index -->
+    </method>
+    <method selector='method10'>
+       <arg index='1' type='d'/>
+    </method>
+    <method selector='method11'>
+       <arg index='1' type='f' type64='d' />
+    </method>
+    <method selector='method12'>
+       <arg index='1'/><!-- ignore -->
+    </method>
+    <method selector='method13'>
+       <arg index='1' type_modifier='n' />
+    </method>
+    <method selector='method13b'>
+       <arg index='1' sel_of_type='v@:f' c_array_of_fixed_length='4'/>
+    </method>
+    <method selector='method14'>
+       <arg index='1' sel_of_type='v@:f' sel_of_type64='v@:d' />
+    </method>
+    <method selector='method15'>
+       <arg index='1' null_accepted='false' already_retained='true' c_array_length_in_result='true' />
+    </method>
+    <method selector='method16'>
+       <arg index='1' c_array_delimited_by_null='true' already_cfretained='true' c_array_of_variable_length='true' printf_format='true' free_result='true' />
+    </method>
+    <method selector='method17'>
+       <arg index='1' c_array_length_in_arg='1'/>
+    </method>
+    <method selector='method18'>
+       <arg index='1' c_array_length_in_arg='1,2'/>
+    </method>
+    <method selector='method19'>
+       <arg index='1' c_array_length_in_arg='4, 5'/>
+    </method>
+    <method selector='method20'>
+       <arg index='1' function_pointer_retained='true'/><!-- ignored, no function data -->
+    </method>
+    <method selector='method21'>
+       <arg index='1' function_pointer_retained='true' function_pointer='true'>
+          <retval type='v' />
+          <arg type='@' />
+          <arg type='d' />
+       </arg>
+    </method>
+    <method selector='method22'>
+       <arg index='1' function_pointer_retained='true' block='true'>
+          <retval type='v' />
+          <arg type='@' />
+          <arg type='d' />
+       </arg>
+    </method>
+    <method selector='method23'>
+       <arg index='1' function_pointer='true'>
+          <retval type='v' />
+          <arg type='@' />
+          <arg type='d' />
+       </arg>
+    </method>
+    <method selector='method24'>
+       <arg index='1' block='true' classmethod='true'>
+          <retval type='v' />
+          <arg type='@' />
+          <arg type='d' />
+       </arg>
+    </method>
+  </class>
+  <function /><!-- ignored -->
+  <function><!-- ignored -->
+    <arg type="f" />
+    <retval type="@" />
+  </function>
+  <function name='function1' ignore='true' ><!-- ignore -->
+    <arg type="f" />
+    <retval type="@" />
+  </function>
+  <function name='function2' variadic='true' ></function>
+  <function name='function3' variadic='true' c_array_delimited_by_null='true'></function>
+  <function name='function4' variadic='true' c_array_length_in_arg='4'></function>
+  <function name='function5' c_array_delimited_by_null='true'><retval type='d'/></function><!-- c_array... ignored -->
+  <function name='function6' c_array_length_in_arg='4'><retval type='d' /></function><!-- c_array... ignored -->
+  <function name='function7' ignore='true'></function>
+  <function name='function8' ignore='true' suggestion='ignore me'></function>
+  <function name='function9' suggestion='ignore me'><retval type='d'/></function><!-- suggestion ignored -->
+  <function name='function10'>
+    <retval type='d'/>
+  </function>
+  <function name='function11'>
+     <retval type='f' type64='d' />
+  </function>
+  <function name='function12'>
+     <retval/><!-- ignore -->
+  </function>
+  <function name='function13'>
+     <retval type_modifier='n' />
+  </function>
+  <function name='function14'>
+     <retval sel_of_type='v@:f' c_array_of_fixed_length='4'/>
+  </function>
+  <function name='function15'>
+     <retval sel_of_type='v@:f' sel_of_type64='v@:d' />
+  </function>
+  <function name='function16'>
+     <retval null_accepted='false' already_retained='true' already_cfretained='true' c_array_length_in_result='true' />
+  </function>
+  <function name='function17'>
+     <retval c_array_delimited_by_null='true' c_array_of_variable_length='true' printf_format='true' free_result='true' />
+  </function>
+  <function name='function18'>
+     <retval c_array_length_in_arg='1'/>
+  </function>
+  <function name='function19'>
+     <retval c_array_length_in_arg='1,2'/>
+  </function>
+  <function name='function20'>
+     <retval c_array_length_in_arg='4, 5'/>
+  </function>
+  <function name='function21'>
+     <retval function_pointer_retained='true'/><!-- ignored, no function data -->
+  </function>
+  <function name='function22'>
+     <retval function_pointer_retained='true' function_pointer='true'>
+        <retval type='v' />
+        <arg type='@' />
+        <arg type='d' />
+     </retval>
+  </function>
+  <function name='function23'>
+     <retval function_pointer_retained='true' block='true'>
+        <retval type='v' />
+        <arg type='@' />
+        <arg type='d' />
+     </retval>
+  </function>
+  <function name='function24'>
+     <retval function_pointer='true'>
+        <retval type='v' />
+        <arg type='@' />
+        <arg type='d' />
+     </retval>
+  </function>
+  <function name='function25'>
+     <retval block='true'>
+        <retval type='v' />
+        <arg type='@' />
+        <arg type='d' />
+     </retval>
+  </function>
+  <function name='function26'>
+     <retval type='q' />
+     <arg index='1' type='f'/>
+     <arg index='2' type='d'/>
+  </function>
+  <function name='function27'>
+     <arg index='1' type='d'/>
+     <arg index='2' type='d'/>
+  </function>
+  <function name='function28'>
+     <arg type='d'/><!-- ignored: no index -->
+  </function>
+  <function name='function29'>
+     <arg index='1' type='d'/>
+  </function>
+  <function name='function30'>
+     <arg index='1' type='f' type64='d' />
+  </function>
+  <function name='function31'>
+     <arg index='1'/><!-- ignore -->
+  </function>
+  <function name='function32'>
+     <arg index='1' type_modifier='n' />
+  </function>
+  <function name='function33'>
+     <arg index='1' sel_of_type='v@:f' c_array_of_fixed_length='4'/>
+  </function>
+  <function name='function34'>
+     <arg index='1' sel_of_type='v@:f' sel_of_type64='v@:d' />
+  </function>
+  <function name='function35'>
+     <arg index='1' null_accepted='false' already_retained='true' already_cfretained='true' c_array_length_in_result='true' />
+  </function>
+  <function name='function36'>
+     <arg index='1' c_array_delimited_by_null='true' c_array_of_variable_length='true' printf_format='true' free_result='true' />
+  </function>
+  <function name='function37'>
+     <arg index='1' c_array_length_in_arg='1'/>
+  </function>
+  <function name='function38'>
+     <arg index='1' c_array_length_in_arg='1,2'/>
+  </function>
+  <function name='function39'>
+     <arg index='1' c_array_length_in_arg='4, 5'/>
+  </function>
+  <function name='function40'>
+     <arg index='1' function_pointer_retained='true'/><!-- ignored, no function data -->
+  </function>
+  <function name='function41'>
+     <arg index='1' function_pointer_retained='true' function_pointer='true'>
+        <retval type='v' />
+        <arg type='@' />
+        <arg type='d' />
+     </arg>
+  </function>
+  <function name='function42'>
+     <arg index='1' function_pointer_retained='true' block='true'>
+        <retval type='v' />
+        <arg type='@' />
+        <arg type='d' />
+     </arg>
+  </function>
+  <function name='function43'>
+     <arg index='1' function_pointer='true'>
+        <retval type='v' />
+        <arg type='@' />
+        <arg type='d' />
+     </arg>
+  </function>
+  <function name='function44'>
+     <arg index='1' block='true'>
+        <retval type='v' />
+        <arg type='@' />
+        <arg type='d' />
+     </arg>
+  </function>
   <!-- TODO: type rewriting (_C_BOOL, _C_NSBOOL)-->
+  <informal_protocol/><!-- ignore -->
+  <informal_protocol name='protocol1' />
+  <informal_protocol name='protocol1' >
+    <method selector='selector1' type='v@:f' type64='v@:d' />
+    <method selector='selector2' type='v@:f' type64='v@:d' classmethod='false' />
+    <method selector='selector3' type='v@:f' type64='v@:d' classmethod='true' />
+    <method selector='selector4' type='v@:f' type64='v@:d' variadic='true' /><!-- 'variadic' is ignored -->
+    <method selector='selector5' /><!-- ignore: no type -->
+    <method selector='selector6' type64='v@:@' /><!-- ignore 32-bit -->
+    <method selector='selector7' type='v@:f' type64='v@:d' class_method='false' /><!-- manpage: class_method, pyobjc 2.3: classmethod -->
+    <method selector='selector8' type='v@:f' type64='v@:d' class_method='true' />
+  </informal_protocol>
+  <struct/><!-- ignore -->
+  <struct type='{foo=dd}' /><!--ignore-->
+  <struct name='struct1' /><!-- ignore -->
+  <struct name='struct2' alias='module.struct3' /><!-- ignore -->
+  <struct name='struct3' type='{struct3=@@}' />
+  <struct name='struct4' type='{struct3=ff}' type64='{struct4=dd}' />
+  <struct name='struct5' type='{struct3=@@}' alias='module2.struct'/>
+  <struct name='struct6' type='{struct6=BB}' /><!-- _C_NSBOOL -->
+  <struct name='struct7' type='{struct7=Z@}' /><!-- _C_BOOL -->
 </signatures>
 """
 
-# XXX: add unsupported variants
-
 class TestBridgeSupport (TestCase):
     def testInvalidToplevel(self):
         self.assertRaises(objc.error, bridgesupport._BridgeSupportParser, '<signatures2></signatures2>', 'Cocoa')
 
                 self.assert_valid_bridgesupport(os.path.basename(fn).split('.')[0], xmldata)
 
-    def test_xml_structure(self):
+    def _test_xml_structure_variants(self):
+        # Run 'verify_xml_structure' for all cpu variant 
+        # (big/little endian,  32- en 64-bit)
+        orig_byteorder = sys.byteorder
+        orig_maxsize = sys.maxsize
+
+        try:
+            for is32bit in (True, False):
+                for endian in ('little', 'big'):
+                    sys.maxsize = 2**63-1 if endian == 'big' else 2**32-1
+                    sys.byteorder = endian
+
+                    # Reload the bridgesupport module because
+                    # it contains conditional definitions
+                    imp.reload(bridgesupport)
+
+                    self.verify_xml_structure()
+
+        finally:
+            sys.byteorder = orig_byteorder 
+            sys.maxsize = orig_maxsize
+
+            # See above
+            imp.reload(bridgesupport)
+
+    def test_verify_xml_structure(self):
         prs = self.assert_valid_bridgesupport('TestXML', TEST_XML)
 
+        all_constants = [
+            ('constant1', b'@', False,),
+            ('constant2', b'I' if sys.maxsize < 2**32 else 'Q' , False,),
+            ('constant5', objc._C_NSBOOL, False,),
+            ('constant6', objc._C_BOOL, False,),
+            ('constant7', b'@', False,),
+            ('constant8', b'@', True,),
+        ]
+        if sys.maxsize > 2**32:
+            all_constants.append(
+                ('constant4', b'Q', False)
+            )
+
+        all_values = {
+            'strconst1': b'string constant1',
+            'strconst2': b'string constant 2' if sys.maxsize < 2**32 else b'string constant two',
+            'strconst1u': b'string constant1 unicode'.decode('ascii'),
+            'strconst2u': b'string constant 2 unicode'.decode('ascii') if sys.maxsize < 2**32 else b'string constant two unicode'.decode('ascii'),
+            'enum1': 1,
+            'enum2': 3 if sys.maxsize < 2**32 else 4,
+            'enum3': 5 if sys.byteorder == 'little' else 6,
+            'enum4': 7,
+            'enum9': 2.5,
+            'enum10': 10.5,
+            'null1': None,
+        }
+        if sys.maxsize > 2**32:
+            all_values['strconst5'] = b'string five'
+            all_values['strconst6'] = b'string five unicode'.decode('ascii')
+            all_values['enum6'] = 4
+
+        if sys.byteorder == 'little':
+            all_values['enum8'] = 5
+        else:
+            all_values['enum7'] = 6
+
+        all_opaque = [
+            ('opaque1', b'^{opaque1}'),
+            ('opaque2', b'^{opaque2=f}' if sys.maxsize < 2**32 else b'^{opaque2=d}'),
+        ]
+        if sys.maxsize > 2**32:
+          all_opaque.append(
+              ('opaque4', b'^{opaque4=d}'),
+          )
+
+        all_func_aliases = [
+            ('func1', 'orig_function'),
+        ]
+
+        a = objc.lookUpClass('NSArray').alloc().init()
+        CFArrayTypeID = a._cfTypeID()
+        all_cftypes = [
+            ( 'CFProxy1Ref', b'^{CFProxy}', CFArrayTypeID),
+            ( 'CFProxy2Ref', b'^{CFProxy32}' if sys.maxint < 2**32 else b'^{CFProxy64}', CFArrayTypeID),
+            ( 'CFProxy3Ref', b'^{CFProxy3}', None, 'NSProxy'),
+            ( 'CFProxy4Ref', b'^{CFProxy4}', None, 'NSProxy2'),
+            ( 'CFProxy5Ref', b'^{CFProxy}', None, 'NSCFType'),
+            ( 'CFProxy6Ref', b'^{CFProxy}', None, 'NSCFType'),
+            ( 'CFProxy7Ref',  b'^{CFProxy32}' if sys.maxint < 2**32 else b'^{CFProxy64}', None, 'NSCFType' ),
+        ]
+        if sys.maxsize > 2**32:
+            all_cftypes.append(
+                ( 'CFProxy9Ref',  b'^{CFProxy64}', CFArrayTypeID),
+            )
+
+
+        all_methods = {
+            (b'MyClass2', b'method2', False): { 'variadic': True },
+            (b'MyClass2', b'method3', False): { 'variadic': True,  'c_array_delimited_by_null': True },
+            (b'MyClass2', b'method4', False): { 'variadic': True,  'c_array_length_in_arg': 4+2 },
+            (b'MyClass2', b'method5', False): { 'retval': { 'type': b'd' } },
+            (b'MyClass2', b'method6', False): { 'retval': { 'type': b'd' } },
+            (b'MyClass2', b'method7', False): { 'suggestion': "don't use this method" },
+            (b'MyClass2', b'method8', False): { 'suggestion': 'ignore me' },
+            (b'MyClass2', b'method9', False): { 'suggestion': 'ignore me' },
+            (b'MyClass2', b'method10', False ): { 'retval': { 'type': b'd' } },
+            (b'MyClass2', b'method11', False ): {
+                'retval': { 
+                    'type': b'f' if sys.maxsize < 2**32 else b'd'
+                }
+            },
+            (b'MyClass2', b'method13', True): { 'retval': { 'type_modifier': b'n' } },
+            (b'MyClass2', b'method13b', False): {
+                'retval': { 'sel_of_type': b'v@:f', 'c_array_of_fixed_length': 4 },
+            },
+            (b'MyClass2', b'method14', False): {
+                'retval': { 'sel_of_type': b'v@:f' if sys.maxsize < 2**32 else b'v@:d' }
+            },
+            (b'MyClass2', b'method15', False): {
+                'retval': { 'null_accepted': False, 'already_retained': True,  }
+            },
+            (b'MyClass2', b'method16', False): {
+                'retval': { 'c_array_delimited_by_null': True, 'c_array_of_variable_length': True, 'printf_format': True,  
+                            'free_result': True, 'already_cfretained': True }
+            },
+            (b'MyClass2', b'method17', False): {
+                'retval': { 'c_array_length_in_arg': 1+2 }
+            },
+            (b'MyClass2', b'method18', False): {
+                'retval': { 'c_array_length_in_arg': (1+2, 2+2) }
+            },
+            (b'MyClass2', b'method19', False): {
+                'retval': { 'c_array_length_in_arg': (4+2, 5+2) }
+            },
+            (b'MyClass2', b'method21', False): {
+                'retval': { 'function_pointer_retained': True, 'callable': {
+                    'retval': { 'type': b'v' },
+                    'arguments': { 
+                        0: b'@',
+                        1: b'd',
+                    }
+                }}
+            },
+            (b'MyClass2', b'method22', False): {
+                'retval': { 'function_pointer_retained': True, 'callable': {
+                    'retval': { 'type': b'v' },
+                    'arguments': { 
+                        0: { 'type': b'@' },
+                        1: { 'type': b'd' },
+                    }
+                }}
+            },
+            (b'MyClass2', b'method23', False): {
+                'retval': { 'callable': {
+                    'retval': { 'type': b'v' },
+                    'arguments': {
+                        0: { 'type': b'@' },
+                        1: { 'type': b'd' },
+                    }
+                }}
+            },
+            (b'MyClass2', b'method24', False): {
+                'retval': { 'callable': {
+                    'retval': { 'type': b'v' },
+                    'arguments': {
+                        0: { 'type': b'@' },
+                        1: { 'type': b'd' },
+                    }
+                }}
+            },
+            (b'MyClass3', b'method7', False): {
+                'retval': { 'type': b'q' },
+                'arguments': {
+                    2+1: { 'type': b'f' },
+                    2+2: { 'type': b'd' },
+                }
+            },
+            (b'MyClass3', b'method8', False): {
+                'arguments': {
+                    2+1: { 'type': b'd' },
+                    2+2: { 'type': b'd' },
+                }
+            },
+            (b'MyClass3', b'method10', False): {
+                'arguments': {
+                    2+1: { 'type': b'd' }
+                }
+            },
+            (b'MyClass3', b'method11', False): {
+                'arguments': {
+                    2+1: { 'type': b'f' if sys.maxsize < 2**32 else b'd' }
+                }
+            },
+            (b'MyClass3', b'method13', False): {
+                'arguments': {
+                    2+1: { 'type_modifier': b'n' },
+                }
+            },
+            (b'MyClass3', b'method13b', False): {
+                'arguments': {
+                    2+1: { 'sel_of_type': b'v@:f', 'c_array_of_fixed_lengt': 4 }
+                }
+            },
+            (b'MyClass3', b'method14', False): {
+                'arguments': {
+                    2+1: { 'sel_of_type': b'v@:f' if sys.maxsize < 2**32 else b'v@:d' }
+                }
+            },
+            (b'MyClass3', b'method15', False): {
+                'arguments': {
+                    2+1: { 'null_accepted': False, 'already_retained': True, 
+                           'c_array_length_in_result': True }
+                }
+            },
+            (b'MyClass3', b'method16', False): {
+                'arguments': {
+                    2+1: { 'c_array_delimited_by_null': True, 'c_array_of_variable_length': True, 
+                           'printf_format': True, 'free_result': True, 'already_cfretained': True }
+                }
+            },
+            (b'MyClass3', b'method17', False): {
+                'arguments': {
+                    2+1:  { 'c_array_length_in_arg': 1+2 },
+                }
+            },
+            (b'MyClass3', b'method18', False): {
+                'arguments': {
+                    2+1:  { 'c_array_length_in_arg': (1+2, 2+2) }
+                }
+            },
+            (b'MyClass3', b'method19', False): {
+                'arguments': {
+                    2+1:  { 'c_array_length_in_arg': (4+2, 5+2) }
+                }
+            },
+            (b'MyClass3', b'method21', False): {
+                'arguments': {
+                    2+1: { 'callable_retained': True, 'callable': {
+                        'retval': { 'type': b'v' },
+                        'arguments': {
+                            0:  { 'type': b'@' },
+                            1:  { 'type': b'd' },
+                        }
+                    }}
+                }
+            },
+            (b'MyClass3', b'method22', False): {
+                'arguments': {
+                    2+1: { 'callable_retained': True, 'callable': {
+                        'retval': { 'type': b'v' },
+                        'arguments': {
+                            0:  { 'type': b'@' },
+                            1:  { 'type': b'd' },
+                        }
+                    }}
+                }
+            },
+            (b'MyClass3', b'method23', False): {
+                'arguments': {
+                    2+1: { 'callable': {
+                        'retval': { 'type': b'v' },
+                        'arguments': {
+                            0:  { 'type': b'@' },
+                            1:  { 'type': b'd' },
+                        }
+                    }}
+                }
+            },
+            (b'MyClass3', b'method23', False): {
+                'arguments': {
+                    2+1: { 'callable': {
+                        'retval': { 'type': b'v' },
+                        'arguments': {
+                            0:  { 'type': b'@' },
+                            1:  { 'type': b'd' },
+                        }
+                    }}
+                }
+            },
+        }      
+
+        self.assertItemsEqual(prs.constants,    all_constants)
+        self.assertEqual(prs.values,            all_values)
+        self.assertItemsEqual(prs.opaque,       all_opaque)
+        self.assertItemsEqual(prs.func_aliases, all_func_aliases)
+        self.assertItemsEqual(prs.cftypes,      all_cftypes)
+
+        self.maxDiff = None
+        self.assertEqual(prs.meta,              all_methods)
         self.fail("validate the metadata from TEST_XML")
 
-    def assertIsIdenfier(self, value):
+        '''
+  <function /><!-- ignored -->
+  <function><!-- ignored -->
+    <arg type="f" />
+    <retval type="@" />
+  </function>
+  <function name='function1' ignore='true' ><!-- ignore -->
+    <arg type="f" />
+    <retval type="@" />
+  </function>
+  <function name='function2' variadic='true' ></function>
+  <function name='function3' variadic='true' c_array_delimited_by_null='true'></function>
+  <function name='function4' variadic='true' c_array_length_in_arg='4'></function>
+  <function name='function5' c_array_delimited_by_null='true'><retval type='d'/></function><!-- c_array... ignored -->
+  <function name='function6' c_array_length_in_arg='4'><retval type='d' /></function><!-- c_array... ignored -->
+  <function name='function7' ignore='true'></function>
+  <function name='function8' ignore='true' suggestion='ignore me'></function>
+  <function name='function9' suggestion='ignore me'><retval type='d'/></function><!-- suggestion ignored -->
+  <function name='function10'>
+    <retval type='d'/>
+  </function>
+  <function name='function11'>
+     <retval type='f' type64='d' />
+  </function>
+  <function name='function12'>
+     <retval/><!-- ignore -->
+  </function>
+  <function name='function13'>
+     <retval type_modifier='n' />
+  </function>
+  <function name='function14'>
+     <retval sel_of_type='v@:f' c_array_of_fixed_length='4'/>
+  </function>
+  <function name='function15'>
+     <retval sel_of_type='v@:f' sel_of_type64='v@:d' />
+  </function>
+  <function name='function16'>
+     <retval null_accepted='false' already_retained='true' already_cfretained='true' c_array_length_in_result='true' />
+  </function>
+  <function name='function17'>
+     <retval c_array_delimited_by_null='true' c_array_of_variable_length='true' printf_format='true' free_result='true' />
+  </function>
+  <function name='function18'>
+     <retval c_array_length_in_arg='1'/>
+  </function>
+  <function name='function19'>
+     <retval c_array_length_in_arg='1,2'/>
+  </function>
+  <function name='function20'>
+     <retval c_array_length_in_arg='4, 5'/>
+  </function>
+  <function name='function21'>
+     <retval function_pointer_retained='true'/><!-- ignored, no function data -->
+  </function>
+  <function name='function22'>
+     <retval function_pointer_retained='true' function_pointer='true'>
+        <retval type='v' />
+        <arg type='@' />
+        <arg type='d' />
+     </retval>
+  </function>
+  <function name='function23'>
+     <retval function_pointer_retained='true' block='true'>
+        <retval type='v' />
+        <arg type='@' />
+        <arg type='d' />
+     </retval>
+  </function>
+  <function name='function24'>
+     <retval function_pointer='true'>
+        <retval type='v' />
+        <arg type='@' />
+        <arg type='d' />
+     </retval>
+  </function>
+  <function name='function25'>
+     <retval block='true'>
+        <retval type='v' />
+        <arg type='@' />
+        <arg type='d' />
+     </retval>
+  </function>
+  <function name='function26'>
+     <retval type='q' />
+     <arg index='1' type='f'/>
+     <arg index='2' type='d'/>
+  </function>
+  <function name='function27'>
+     <arg index='1' type='d'/>
+     <arg index='2' type='d'/>
+  </function>
+  <function name='function28'>
+     <arg type='d'/><!-- ignored: no index -->
+  </function>
+  <function name='function29'>
+     <arg index='1' type='d'/>
+  </function>
+  <function name='function30'>
+     <arg index='1' type='f' type64='d' />
+  </function>
+  <function name='function31'>
+     <arg index='1'/><!-- ignore -->
+  </function>
+  <function name='function32'>
+     <arg index='1' type_modifier='n' />
+  </function>
+  <function name='function33'>
+     <arg index='1' sel_of_type='v@:f' c_array_of_fixed_length='4'/>
+  </function>
+  <function name='function34'>
+     <arg index='1' sel_of_type='v@:f' sel_of_type64='v@:d' />
+  </function>
+  <function name='function35'>
+     <arg index='1' null_accepted='false' already_retained='true' already_cfretained='true' c_array_length_in_result='true' />
+  </function>
+  <function name='function36'>
+     <arg index='1' c_array_delimited_by_null='true' c_array_of_variable_length='true' printf_format='true' free_result='true' />
+  </function>
+  <function name='function37'>
+     <arg index='1' c_array_length_in_arg='1'/>
+  </function>
+  <function name='function38'>
+     <arg index='1' c_array_length_in_arg='1,2'/>
+  </function>
+  <function name='function39'>
+     <arg index='1' c_array_length_in_arg='4, 5'/>
+  </function>
+  <function name='function40'>
+     <arg index='1' function_pointer_retained='true'/><!-- ignored, no function data -->
+  </function>
+  <function name='function41'>
+     <arg index='1' function_pointer_retained='true' function_pointer='true'>
+        <retval type='v' />
+        <arg type='@' />
+        <arg type='d' />
+     </arg>
+  </function>
+  <function name='function42'>
+     <arg index='1' function_pointer_retained='true' block='true'>
+        <retval type='v' />
+        <arg type='@' />
+        <arg type='d' />
+     </arg>
+  </function>
+  <function name='function43'>
+     <arg index='1' function_pointer='true'>
+        <retval type='v' />
+        <arg type='@' />
+        <arg type='d' />
+     </arg>
+  </function>
+  <function name='function44'>
+     <arg index='1' block='true'>
+        <retval type='v' />
+        <arg type='@' />
+        <arg type='d' />
+     </arg>
+  </function>
+  <!-- TODO: type rewriting (_C_BOOL, _C_NSBOOL)-->
+  <informal_protocol/><!-- ignore -->
+  <informal_protocol name='protocol1' />
+  <informal_protocol name='protocol1' >
+    <method selector='selector1' type='v@:f' type64='v@:d' />
+    <method selector='selector2' type='v@:f' type64='v@:d' classmethod='false' />
+    <method selector='selector3' type='v@:f' type64='v@:d' classmethod='true' />
+    <method selector='selector4' type='v@:f' type64='v@:d' variadic='true' /><!-- 'variadic' is ignored -->
+    <method selector='selector5' /><!-- ignore: no type -->
+    <method selector='selector6' type64='v@:@' /><!-- ignore 32-bit -->
+    <method selector='selector7' type='v@:f' type64='v@:d' class_method='false' /><!-- manpage: class_method, pyobjc 2.3: classmethod -->
+    <method selector='selector8' type='v@:f' type64='v@:d' class_method='true' />
+  </informal_protocol>
+  <struct/><!-- ignore -->
+  <struct type='{foo=dd}' /><!--ignore-->
+  <struct name='struct1' /><!-- ignore -->
+  <struct name='struct2' alias='module.struct3' /><!-- ignore -->
+  <struct name='struct3' type='{struct3=@@}' />
+  <struct name='struct4' type='{struct3=ff}' type64='{struct4=dd}' />
+  <struct name='struct5' type='{struct3=@@}' alias='module2.struct'/>
+  <struct name='struct6' type='{struct6=BB}' /><!-- _C_NSBOOL -->
+  <struct name='struct7' type='{struct7=Z@}' /><!-- _C_BOOL -->
+</signatures>
+'''
+
+    def assertIsIdentifier(self, value):
         m = IDENTIFIER.match(value)
         if m is None:
             self.fail("'%s' is not an identifier"%(value,))
             if "free_result" in meta["retval"]:
                 self.assertIsInstance(meta["retval"]["free_result"], bool)
 
-            for key in ("c_array_length_in_arg", "c_array_of_fixed_length"):
-                if key in meta["retval"]:
+            key = "c_array_of_fixed_length"
+            if key in meta["retval"]:
+                self.assertIsInstance(meta["retval"][key], (int, long))
+
+            key = "c_array_length_in_arg"
+            if key in meta["retval"]:
+                if isinstance(meta["retval"][key], tuple):
+                    self.assertEqual(len(meta["retval"][key]), 2)
+                    self.assertTrue(all(isinstance(x, (int, long)) for x in meta["retval"][key]))
+                else:
                     self.assertIsInstance(meta["retval"][key], (int, long))
 
             for key in ("c_array_delimited_by_null", "printf_format", "c_array_of_variable_length", "null_accepted"):
             self.assertNotIn("c_array_length_in_result", meta["retval"])
             self.assertEqual(set(meta["retval"]) - valid_keys, set())
 
-        for idx in meta["arguments"]:
+        if 'arguments' in meta:
+          for idx in meta["arguments"]:
             self.assertIsInstance(idx, (int, long))
             arg = meta["arguments"][idx]
 
             self.assertIsInstance(meta["variadic"], bool)
 
         if "variadic" in meta and meta["variadic"]:
-            self.assertEqual(set(meta.keys()) - {"arguments", "retval", "variadic", 
+            self.assertEqual(set(meta.keys()) - {"arguments", "retval", "variadic", "classmethod",
                     "c_array_length_in_arg", "c_array_delimited_by_null", "suggestion"}, set())
 
             found = False
             #    self.fail("meta for variadic without method for determining size: %s"%(meta,))
 
         else:
-            self.assertEqual(set(meta.keys()) - {"arguments", "retval", "variadic", "suggestion" }, set())
+            self.assertEqual(set(meta.keys()) - {"arguments", "retval", "variadic", "suggestion", "classmethod" }, set())
 
     def assert_valid_bridgesupport(self, framework_name, xmldata):
         prs = bridgesupport._BridgeSupportParser(xmldata, framework_name)
                 self.assertIsInstance(sel, objc.selector)
                 self.assertIs(sel.callable, None)
 
-        for clsname, selname in prs.meta:
-            meta = prs.meta[(clsname, selname)]
+        for clsname, selname, is_class in prs.meta:
+            meta = prs.meta[(clsname, selname, is_class)]
             self.assertIsInstance(clsname, bytes)
+            self.assertIsInstance(is_class, bool)
             self.assertIsInstance(selname, bytes)
             self.assertIsInstance(meta, dict)
             self.assert_valid_callable(meta, function=False)
             self.assertEqual(len(objc.splitSignature(typestr)), 1)
 
         for name in prs.values:
-            self.assertIsInstance(prs.values[name], (basestring, long, int, float, bytes))
+            self.assertIsInstance(prs.values[name], (basestring, long, int, float, bytes, type(None)))
 
         return prs
 
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.