Commits

Ronald Oussoren committed 1649472

More test improvements

Comments (0)

Files changed (11)

pyobjc-core/Doc/conf.py

 # Add any paths that contain custom static files (such as style sheets) here,
 # relative to this directory. They are copied after the builtin static files,
 # so a file named "default.css" will overwrite the builtin "default.css".
-html_static_path = ['sphinx_static']
+html_static_path = [] # ['sphinx_static']
 
 # If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
 # using the given strftime format.

pyobjc-core/Doc/lib/module-objc.rst

    .. note::
       Sharing an ivar object between multiple class definitions is not supported.
 
+
+   Instances of :class:`ivar` have a number of attributes that help with introspection:
+   
+   * *__typestr__*: The type encoding of the Objective-C type of the variable
+
+   * *__name__*: The Objective-C name of the variable
+
+   * *__isOutlet__*: :data:`True` if the variable is an :func:`IBOutlet`
+
+   * *__isSlot__*: :data:`True` if the variable is a Python slot.
+
+   .. note::
+
+      You cannot access these attributes  through an Objective-C instance, you have to access
+      them through the class object. That's because :class:`ivar` is a data descriptor.
+
    .. seealso::
 
       Function :func:`IBOutlet`
 
       The example will also work without the decorator because 
       NSArray won't store a reference to the compare function that
-      is used after 'sortedArrayUsingFunction_context_' returns.
+      is used after 'sortedArrayUsingFunction_context\_' returns.
 
 .. function:: selectorFor(callable[, argIndex])
 

pyobjc-core/Doc/metadata/manual.rst

 API description
 ---------------
 
-For now see :doc:`the main API description <lib/module-objc` for the
+For now see :doc:`the main API description </lib/module-objc>` for the
 functions that are used to load metadata.
 
 The contains of the metadata dictionary argument for 

pyobjc-core/Lib/objc/_bridgesupport.py

 import re
 import warnings
 import functools
+import pkg_resources
+import os
 
 from objc import registerMetaDataForSelector, error
 
                 for nm, tp in fields:
                     if tp == b'?':
                         return True
+                    elif tp == b'^?':
+                        return True
                     elif tp.startswith(objc._C_STRUCT_B):
                         return has_embedded_function(tp)
 
 
             globals[entry[0]] = tp
 
-        for name, typestr, magic in prs.constants:
-            try:
-                value = objc._loadConstant(name, typestr, magic)
-            except AttributeError:
-                return
-
-            globals[name] = value
-
-        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)
 
             else:
                 globals[name] = value = objc.createStructType(name, typestr, None)
 
+
+        for name, typestr, magic in prs.constants:
+            try:
+                value = objc._loadConstant(name, typestr, magic)
+            except AttributeError:
+                continue
+
+            globals[name] = value
+
+        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, method_list in prs.informal_protocols:
             proto = objc.informal_protocol(name, method_list)
 
             # XXX: protocols submodule should be deprecated
             if "protocols" not in globals:
-                mod_name = "%s.protocols"%(self.frameworkName,)
-                m = protocols["protocols"] = type(objc)(mod_name)
+                mod_name = "%s.protocols"%(frameworkName,)
+                m = globals["protocols"] = type(objc)(mod_name)
                 sys.modules[mod_name] = m
 
             else:
 @functools.wraps(objc.createStructType)
 def createStructType(name, typestr, fieldnames, doc=None, pack=-1):
     result = _orig_createStructType(name, typestr, fieldnames, doc, pack)
-    _structConvenience(name, result)
+    _structConvenience(name, result.__typestr__)
     return result
 
 objc.createStructType = createStructType
 _orig_registerStructAlias = objc.registerStructAlias
 @functools.wraps(objc.registerStructAlias)
 def registerStructAlias(typestr, structType):
-    warning.warn("use createStructAlias instead", DeprecationWarning)
+    warnings.warn("use createStructAlias instead", DeprecationWarning)
     return _orig_registerStructAlias(typestr, structType)
 
 def createStructAlias(name, typestr, structType):
     result = _orig_registerStructAlias(typestr, structType)
-    _structConvenience(name, result)
+    _structConvenience(name, result.__typestr__)
     return result
 
 objc.createStructAlias = createStructAlias

pyobjc-core/Modules/objc/instance-var.m

 "value is assigned to"
 );
 
+PyDoc_STRVAR(ivar_typestr_doc,
+		        "The Objective-C type encoding");
+static PyObject*
+ivar_get_typestr(PyObject* _self, void* closure __attribute__((__unused__)))
+{
+	PyObjCInstanceVariable* self = (PyObjCInstanceVariable*)_self;
+
+	return PyBytes_FromString(self->type);
+}
+
+PyDoc_STRVAR(ivar_name_doc,
+		        "The Objective-C name");
+static PyObject*
+ivar_get_name(PyObject* _self, void* closure __attribute__((__unused__)))
+{
+	PyObjCInstanceVariable* self = (PyObjCInstanceVariable*)_self;
+
+
+	if (self->name) {
+		return PyText_FromString(self->name);
+	} else {
+		Py_INCREF(Py_None);
+		return Py_None;
+	}
+}
+
+PyDoc_STRVAR(ivar_isOutlet_doc,
+		        "True if the instance variable is an IBOutlet");
+static PyObject*
+ivar_get_isOutlet(PyObject* _self, void* closure __attribute__((__unused__)))
+{
+	PyObjCInstanceVariable* self = (PyObjCInstanceVariable*)_self;
+	PyObject* result = self->isOutlet ? Py_True : Py_False;
+	Py_INCREF(result);
+	return result;
+}
+
+PyDoc_STRVAR(ivar_isSlot_doc,
+		        "True if the instance variable is a Python slot");
+static PyObject*
+ivar_get_isSlot(PyObject* _self, void* closure __attribute__((__unused__)))
+{
+	PyObjCInstanceVariable* self = (PyObjCInstanceVariable*)_self;
+	PyObject* result = self->isSlot ? Py_True : Py_False;
+	Py_INCREF(result);
+	return result;
+}
+
+
+static PyGetSetDef ivar_getset[] = {
+	{
+		"__typestr__",
+		ivar_get_typestr,
+		0,
+		ivar_typestr_doc,
+		0
+	},
+	{
+		"__name__",
+		ivar_get_name,
+		0,
+		ivar_name_doc,
+		0
+	},
+	{
+		"__isOutlet__",
+		ivar_get_isOutlet,
+		0,
+		ivar_isOutlet_doc,
+		0
+	},
+	{
+		"__isSlot__",
+		ivar_get_isSlot,
+		0,
+		ivar_isSlot_doc,
+		0
+	},
+	{ 0, 0, 0, 0, 0 }
+};
+
+
 PyTypeObject PyObjCInstanceVariable_Type = {
 	PyVarObject_HEAD_INIT(&PyType_Type, 0)             
 	"ivar",                             
 	0,                                      /* tp_iternext */
 	ivar_methods,                           /* tp_methods */
 	0,                                      /* tp_members */
-	0,                                      /* tp_getset */
+	ivar_getset,                            /* tp_getset */
 	0,                                      /* tp_base */
 	0,                                      /* tp_dict */
 	ivar_descr_get,           		/* tp_descr_get */

pyobjc-core/Modules/objc/module.m

 }
 
 PyDoc_STRVAR(registerMetaData_doc,
-	"registerMetaDataForSelector(class, selector, metaDataList) -> None\n"
+	"registerMetaDataForSelector(class, selector, metadata) -> None\n"
 	"\n"
 	"XXX: work out documentation.");
 static PyObject*

pyobjc-core/NEWS.txt

    Version 2.5 is currently in development and hasn't been released
    yet.
 
+- Instances of :class:`objc.ivar` now have slots for introspection:
+
+  - *__typestr__*: The type encoding
+
+  - *__name__*: The Objective-C name
+
+  - *__isOutlet__*: :data:`True` if the instance variable is an IBOutlet
+
+  - *__isSlot__*: :data:`True` if the instance variable is a Python slot
+
 - Added implementation of '==' and '!=' for selectors defined in Python
   that is slightly smarter than the default (identity based) implementation
   in Python. 

pyobjc-core/PyObjCTest/test_bridgesupport.py

         # (big/little endian,  32- en 64-bit)
         orig_byteorder = sys.byteorder
         orig_maxsize = sys.maxsize
+        orig_createStructType = bridgesupport._orig_createStructType
+        orig_registerStructAlias = bridgesupport._orig_registerStructAlias
 
         try:
             for is32bit in (True, False):
 
                     # Reload the bridgesupport module because
                     # it contains conditional definitions
+                    objc.createStructType = orig_createStructType
+                    objc.registerStructAlias = orig_registerStructAlias
                     imp.reload(bridgesupport)
 
                     self.verify_xml_structure()
             sys.maxsize = orig_maxsize
 
             # See above
+            objc.createStructType = orig_createStructType
+            objc.registerStructAlias = orig_registerStructAlias
             imp.reload(bridgesupport)
 
     def verify_xml_structure(self):
 
         return prs
 
+class Patcher (object):
+    def __init__(self):
+        self._changes = {}
+
+    def patch(self, path, value):
+        if path not in self._changes:
+            self._changes[path] = self.get(path)
+        self.set(path, value)
+
+    def get(self, path):
+        module, name = path.rsplit('.', 1)
+        m = __import__(module)
+        for p in module.split('.')[1:]:
+            m = getattr(m, p)
+
+        return getattr(m, name)
+
+    def set(self, path, value):
+        module, name = path.rsplit('.', 1)
+        m = __import__(module)
+        for p in module.split('.')[1:]:
+            m = getattr(m, p)
+
+        setattr(m, name, value)
+
+    def __enter__(self):
+        return self
+
+    def __exit__(self, type, value, tp):
+        for k in self._changes:
+            self.set(k, self._changes[k])
+
 class TestParseBridgeSupport (TestCase):
     def test_calls(self):
         # - Minimal XML with all types of metadata
         #   (with strict verification of arguments, based on C code)
         # - Verify changes to globals where possible
         # - Verify 'updatingmetadata' state
-        self.fail()
+
+        class InlineTab (object): pass
+        def loadConstant(name, typestr, magic):
+            self.assertIsInstance(name, str)
+            self.assertIsInstance(typestr, bytes)
+            self.assertEqual(len(objc.splitSignature(typestr)), 1)
+            self.assertIsInstance(magic, bool)
+
+            if 'raise' in name:
+                raise AttributeError(name)
+
+            return '<constant %r>'%(name,)
+
+        SENTINEL=object()
+        def registerCFSignature(name, encoding, typeId, tollfreeName=SENTINEL):
+            self.assertIsInstance(name, str)
+            self.assertIsInstance(encoding, bytes);
+            self.assertIsInstance(typeId, (int, long, type(None)));
+            if tollfreeName is not SENTINEL:
+                self.assertIsInstance(tollfreeName, str)
+            
+            if typeId is None:
+                if tollfreeName is SENTINEL:
+                    raise ValueError("Must specify a typeid when not toll-free")
+
+            return "<cftype %r>"%(name,)
+
+        metadata_registry = {}
+        def registerMetaDataForSelector(class_, selector, metadata):
+            self.assertIsInstance(class_, str)
+            self.assertIsInstance(selector, str)
+            self.assertIsInstance(metadata, dict)
+
+            # XXX: It might be nice to validate the contents of
+            # metadata, but that can be added later.
+
+            metadata_registry[(class_, selector)] = metadata
+
+        def createOpaquePointerType(name, typestr, doc=None):
+            self.assertIsInstance(name, str)
+            self.assertIsInstance(typestr, bytes)
+            self.assertIsInstance(doc, (str, type(None)))
+            self.assertEqual(len(objc.splitSignature(typestr)), 1)
+            self.assertTrue(typestr.startswith(objc._C_PTR))
+            return '<pointer %r>'%(name,)
+
+        def createStructType(name, typestr, fieldnames, doc=None, pack=-1):
+            self.assertIsInstance(name, str)
+            self.assertIsInstance(typestr, bytes)
+            self.assertIsInstance(fieldnames, (list, tuple, type(None)))
+            self.assertIsInstance(doc, (str, type(None)))
+            self.assertIsInstance(pack, (int, long))
+            self.assertTrue(-1 <= pack <= 32)
+            if fieldnames is not None:
+                for nm in fieldnames:
+                    self.assertIsInstance(nm, (str, bytes))
+            return '<struct %r>'%(name,)
+
+        def createStructAlias(name, typestr, structType):
+            self.assertIsInstance(name, str)
+            self.assertIsInstance(typestr, bytes)
+
+        def informal_protocol(name, method_list):
+            self.assertIsInstance(name, str)
+            for item in method_list:
+                self.assertIsInstance(item, objc.selector)
+                self.assertIs(item.callable, None)
+
+            return '<informal_protocol %r>'%(name,)
+
+        def loadBundleFunctions(bundle, module_globals, functionInfo, skip_undefined=True):
+            self.assertIs(bundle, None)
+            self.assertIsInstance(module_globals, dict)
+            self.assertIsInstance(functionInfo, (list, tuple))
+            self.assertIsInstance(skip_undefined, bool)
+            for item in functionInfo:
+                self.assertIsInstance(item, (tuple, list))
+                self.assertTrue(2 <= len(item) <= 4)
+                self.assertIsInstance(item[0], str)
+                self.assertIsInstance(item[1], bytes)
+                if len(item) > 2:
+                    self.assertIsInstance(item[2], (str, type(None)))
+                if len(item) > 3:
+                    self.assertIsInstance(item[3], dict)
+
+                if 'inline' in item[0]:
+                    continue
+
+                module_globals[item[0]] = '<function %r>'%(item[0],)
+
+        def loadFunctionList(function_list, module_globals, functionInfo, skip_undefined=True):
+            self.assertIsInstance(function_list, InlineTab)
+            self.assertIsInstance(module_globals, dict)
+            self.assertIsInstance(functionInfo, (list, tuple))
+            self.assertIsInstance(skip_undefined, bool)
+            for item in functionInfo:
+                self.assertIsInstance(item, (tuple, list))
+                self.assertTrue(2 <= len(item) <= 4)
+                self.assertIsInstance(item[0], str)
+                self.assertIsInstance(item[1], bytes)
+                if len(item) > 2:
+                    self.assertIsInstance(item[2], (str, type(None)))
+                if len(item) > 3:
+                    self.assertIsInstance(item[3], dict)
+                if item[0] not in module_globals:
+                    module_globals[item[0]] = '<inline_function %r>'%(item[0],)
+
+
+        _meta_updates = []
+        def _updatingMetadata(flag):
+            self.assertIsInstance(flag, bool)
+            _meta_updates.append(flag)
+
+        with Patcher() as p:
+            p.patch('objc._updatingMetadata', _updatingMetadata)
+            p.patch('objc._loadConstant', loadConstant)
+            p.patch('objc.registerCFSignature', registerCFSignature)
+            p.patch('objc.registerMetaDataForSelector', registerMetaDataForSelector)
+            p.patch('objc.createOpaquePointerType', createOpaquePointerType)
+            p.patch('objc.createStructType', createStructType)
+            p.patch('objc.createStructAlias', createStructAlias)
+            p.patch('objc.informal_protocol', informal_protocol)
+            p.patch('objc.loadBundleFunctions', loadBundleFunctions)
+            p.patch('objc.loadFunctionList', loadFunctionList)
+            p.patch('sys.modules', sys.modules.copy())
+
+            # 1. Empty metadata
+            _meta_updates  = []
+            metadata_registry = {}
+            module_globals = {}
+
+            objc.parseBridgeSupport('''\
+            <signatures>
+            </signatures>
+            ''', module_globals, 'TestFramework')
+
+            self.assertEqual(_meta_updates, [True, False])
+            self.assertEqual(metadata_registry, {})
+            self.assertEqual(module_globals, {})
+
+            # 2. Various metadata
+            _meta_updates  = []
+            metadata_registry = {}
+            module_globals = {}
+            orig_libraries = list(bridgesupport._libraries)
+
+            xml = '''\
+            <signatures>
+              <opaque name='opaque_type' type='^{opaque}'/>
+              <struct name='OCPoint' type='{OCPoint=dd}' />
+              <struct name='OCPoint2' type='{OCPoint2=dd}' alias='distutils.sysconfig.get_config_var'/>
+              <enum name='enum_value' value='42' />
+              <constant name='const_value' type='@' />
+              <constant name='const_raise' type='@' />
+              <cftype name='cftype_value' type='^{cftype}' />
+              <class name='class1'>
+                <method selector='sel1:' class_method='false'>
+                  <arg index='0' null_accepted='false' type_modifier='o' />
+                </method>
+              </class>
+              <function name='function1'>
+                 <retval type='f' />
+                 <arg type='@' />
+                 <arg type='d' />
+              </function>
+              <function name='function2'>
+                 <retval type='d' />
+                 <arg type='d' />
+              </function>
+              <function name='inline_function'>
+                <retval type='i' />
+              </function>
+              <function_pointer name='function3' original='function2'/>
+              <function_pointer name='function4' original='no_such_function'/>
+              <informal_protocol name='protocol1'>
+                <method selector='sel1:' type='v@:@' />
+              </informal_protocol>
+              <informal_protocol name='protocol2'>
+                <method selector='sel2:' type='v@:@' />
+              </informal_protocol>
+            </signatures>
+            '''
+            objc.parseBridgeSupport(xml, module_globals, 'TestFramework')
+
+            self.assertEqual(_meta_updates, [True, False])
+            self.assertEqual(metadata_registry, {
+                (b'class1', 'sel1:'): {
+                    'arguments': {
+                        2: { 'null_accepted': False, 'type_modifier': b'o' }
+                    }
+                },
+            })
+
+            from distutils.sysconfig import get_config_var
+
+            self.assertIn('protocols', module_globals)
+            m = module_globals.pop('protocols')
+            self.assertIsInstance(m, type(objc))
+            self.assertEqual(m.__name__, 'TestFramework.protocols')
+            self.assertEqual(m.protocol1, "<informal_protocol 'protocol1'>")
+            self.assertEqual(m.protocol2, "<informal_protocol 'protocol2'>")
+            self.assertIs(sys.modules['TestFramework.protocols'], m)
+            self.assertEqual(module_globals, {
+                "enum_value":   42,
+                "const_value":  "<constant 'const_value'>",
+                "cftype_value":  "<cftype 'cftype_value'>",
+                "function1":     "<function 'function1'>",
+                "function2":     "<function 'function2'>",
+                "function3":     "<function 'function2'>",
+                "OCPoint":       "<struct 'OCPoint'>",
+                "OCPoint2":      get_config_var,
+                "opaque_type":   "<pointer 'opaque_type'>",
+            })
+            self.assertEqual(orig_libraries, bridgesupport._libraries)
+
+            # 3. inlineTab
+            _meta_updates  = []
+            metadata_registry = {}
+            module_globals = {}
+            orig_libraries = list(bridgesupport._libraries)
+
+            xml = '''\
+            <signatures>
+              <function name='function1'>
+                 <retval type='f' />
+                 <arg type='@' />
+                 <arg type='d' />
+              </function>
+              <function name='function2'>
+                 <retval type='d' />
+                 <arg type='d' />
+              </function>
+              <function name='inline_function_name'>
+                <retval type='i' />
+              </function>
+            </signatures>
+            '''
+            objc.parseBridgeSupport(xml, module_globals, 'TestFramework2', inlineTab=InlineTab())
+
+            self.assertEqual(_meta_updates, [True, False])
+            self.assertEqual(metadata_registry, {})
+            self.assertNotIn('protocols', module_globals)
+            self.assertNotIn('TestFramework2.protocols', sys.modules)
+            self.assertEqual(module_globals, {
+                "function1":     "<function 'function1'>",
+                "function2":     "<function 'function2'>",
+                "inline_function_name":     "<inline_function 'inline_function_name'>",
+            })
+            self.assertEqual(orig_libraries, bridgesupport._libraries)
+
+            # 4. dylib usage
+            _meta_updates  = []
+            metadata_registry = {}
+            module_globals = {}
+            orig_libraries = list(bridgesupport._libraries)
+
+            xml = '''\
+            <signatures>
+              <function name='function1'>
+                 <retval type='f' />
+                 <arg type='@' />
+                 <arg type='d' />
+              </function>
+              <function name='function2'>
+                 <retval type='d' />
+                 <arg type='d' />
+              </function>
+              <function name='inline_function_name'>
+                <retval type='i' />
+              </function>
+            </signatures>
+            '''
+            objc.parseBridgeSupport(xml, module_globals, 'TestFramework2', dylib_path='/usr/lib/libxml2.dylib')
+
+            self.assertEqual(_meta_updates, [True, False])
+            self.assertEqual(metadata_registry, {})
+            self.assertNotIn('protocols', module_globals)
+            self.assertNotIn('TestFramework2.protocols', sys.modules)
+            self.assertEqual(module_globals, {
+                "function1":     "<function 'function1'>",
+                "function2":     "<function 'function2'>",
+            })
+            self.assertEqual(len(orig_libraries)+1, len(bridgesupport._libraries))
+            self.assertIsInstance(bridgesupport._libraries[-1], ctypes.CDLL)
+            self.assertEqual(bridgesupport._libraries[-1]._name, '/usr/lib/libxml2.dylib')
+            
 
     def test_real_loader(self):
         # Use the real API in a subprocess and verify
 
 
 class TestInitFrameworkWrapper (TestCase):
-    def test_calls(self):
+    def test_calls_parse_helper(self):
         # Test functionality of initFrameworkWrapper and _parseBridgeSupport
-        # by mocking 'parseBridgeSupport'. 
-        self.fail()
+        # by mocking 'parseBridgeSupport' (and the location of the caller)
+        with Patcher() as p:
+            calls = []
+            raise_exception = None
+            update_globals = None
+
+            def parseBridgeSupport(xmldata, globals, frameworkName, dylib_path=None, inlineTab=None):
+                calls.append((xmldata, globals, frameworkName, dylib_path, inlineTab))
+                if update_globals is not None:
+                    globals.update(update_globals)
+
+                if raise_exception is not None:
+                    raise raise_exception()
+
+            class MockModule (object):
+                pass
+
+
+            p.patch('objc.parseBridgeSupport', parseBridgeSupport)
+
+
+            # 1. Verify that failures to load bridgesupport emit a warning
+            calls = []
+            raise_exception = objc.internal_error
+            update_globals = None
+
+            with filterWarnings("error", RuntimeWarning):
+                self.assertRaises(RuntimeWarning, bridgesupport._parseBridgeSupport, '', {}, 'TestFramework')
+
+            calls = []
+
+            with filterWarnings("ignore", RuntimeWarning):
+                g = {}
+                update_globals = {'foo': 42, 'bar': 33,  'protocols': MockModule() }
+                bridgesupport._parseBridgeSupport('', g, 'TestFramework')
+                self.assertEqual(g, update_globals)
+                self.assertEqual(calls, [('', g, 'TestFramework', None, None)])
+
+                self.assertNotEqual(len(g['protocols'].__dict__), 0)
+                for v in g['protocols'].__dict__.values():
+                    self.assertIsInstance(v, objc.formal_protocol)
+
+
+            # 2. Run without problems, without 'protocols' in dictionary
+            raise_exception = None
+            update_globals = {'foo': 42, 'bar': 33,  }
+
+            calls = []
+            g = {}
+            bridgesupport._parseBridgeSupport('', g, 'TestFramework', 'a', 'b')
+            self.assertEqual(g, update_globals)
+            self.assertEqual(calls, [('', g, 'TestFramework', 'a', 'b')])
+            self.assertNotIn('protocols', g)
+
+            calls = []
+            g = {}
+            bridgesupport._parseBridgeSupport('', g, 'TestFramework', inlineTab='a')
+            self.assertEqual(g, update_globals)
+            self.assertEqual(calls, [('', g, 'TestFramework', None, 'a')])
+            self.assertNotIn('protocols', g)
+
+            # 3. Run witout problems, with 'protocols' in dictionary
+            calls = []
+            raise_exception = None
+            update_globals = {'foo': 42, 'bar': 33,  'protocols': MockModule() }
+
+            g = {}
+            bridgesupport._parseBridgeSupport('', g, 'TestFramework', 'a', 'b')
+            self.assertEqual(g, update_globals)
+            self.assertEqual(calls, [('', g, 'TestFramework', 'a', 'b')])
+            self.assertNotEqual(len(g['protocols'].__dict__), 0)
+            for v in g['protocols'].__dict__.values():
+                self.assertIsInstance(v, objc.formal_protocol)
+
+            calls = []
+            g = {}
+            bridgesupport._parseBridgeSupport('', g, 'TestFramework', inlineTab='a')
+            self.assertEqual(g, update_globals)
+            self.assertEqual(calls, [('', g, 'TestFramework', None, 'a')])
+            self.assertNotEqual(len(g['protocols'].__dict__), 0)
+            for v in g['protocols'].__dict__.values():
+                self.assertIsInstance(v, objc.formal_protocol)
+
+
+    def test_calls_initwrappper(self):
+       self.fail()
+
 
     def test_real_loader(self):
         # Load framework in subprocess and verify that
         # the right metadata is loaded.
         self.fail()
 
+class TestMisc (TestCase):
+    def test_struct_alias(self):
+        tp1 = objc.createStructType('TestStruct1', b'{TestStruct1="f1"d"f2"d}', None)
+
+        with filterWarnings("error", DeprecationWarning):
+            self.assertRaises(DeprecationWarning, objc.registerStructAlias, b'{TestStruct2=dd}', tp1)
+
+        with filterWarnings("ignore", DeprecationWarning):
+            tp2 = objc.registerStructAlias(b'{TestStruct2=dd}', tp1)
+            self.assertIs(tp1, tp2)
+
+        self.assertHasAttr(objc.ivar, 'TestStruct1')
+        self.assertNotHasAttr(objc.ivar, 'TestStruct2')
+
+        tp3 = objc.createStructAlias('TestStruct3', b'{TestStruct3=dd}', tp1)
+        self.assertIs(tp1, tp3)
+        self.assertHasAttr(objc.ivar, 'TestStruct3')
+
 
 if __name__ == "__main__":
     main()

pyobjc-core/PyObjCTest/test_bundleFunctions.py

         self.bundle = Foundation.NSBundle.bundleForClass_(Foundation.NSBundle)
 
     def testSimple(self):
-        d = {}
-        objc.loadBundleFunctions(self.bundle, d, FUNCTIONS)
+        for bundle in (None, self.bundle):
+            d = {}
+            objc.loadBundleFunctions(self.bundle, d, FUNCTIONS)
 
-        self.assertIn('NSIsFreedObject', d)
-        self.assertIn('NSCountFrames', d)
-        self.assertIn('NSHomeDirectory', d)
+            self.assertIn('NSIsFreedObject', d)
+            self.assertIn('NSCountFrames', d)
+            self.assertIn('NSHomeDirectory', d)
 
-        # Don't use this API, it is unsupported and causes warnings.
-        #fn = d[u'NSIsFreedObject']
-        #obj = NSObject.alloc().init()
-        #value = fn(obj)
-        #self.assertTrue(not value)
+            # Don't use this API, it is unsupported and causes warnings.
+            #fn = d[u'NSIsFreedObject']
+            #obj = NSObject.alloc().init()
+            #value = fn(obj)
+            #self.assertTrue(not value)
 
-        fn = d['NSHomeDirectory']
-        value = fn()
-        self.assertEqual(value, os.path.expanduser('~'))
+            fn = d['NSHomeDirectory']
+            value = fn()
+            self.assertEqual(value, os.path.expanduser('~'))
 
-        fn = d['NSClassFromString']
-        value = fn('NSObject')
-        self.assertIs(value, NSObject)
+            fn = d['NSClassFromString']
+            value = fn('NSObject')
+            self.assertIs(value, NSObject)
 
-        # Need to look for a different example, NSCountFrames crashes
-        # (that is the actual function, not the dynamic wrapper)
-        #fn = d[u'NSCountFrames']
-        #import Foundation
-        #fn = Foundation.NSCountFrames
-        #value = fn()
-        #self.assertIsInstance(value, int)
+            # Need to look for a different example, NSCountFrames crashes
+            # (that is the actual function, not the dynamic wrapper)
+            #fn = d[u'NSCountFrames']
+            #import Foundation
+            #fn = Foundation.NSCountFrames
+            #value = fn()
+            #self.assertIsInstance(value, int)
 
 
 if __name__ == "__main__":
     main()
-
-

pyobjc-core/PyObjCTest/test_ivar.py

             var2 = objc.ivar(type=objc._C_DBL)
 
             outlet = objc.IBOutlet()
+            self.assertTrue(outlet.__isOutlet__)
+            self.assertFalse(outlet.__isSlot__)
 
         o = AnonIvarClass.alloc().init()
         o.var = NSObject.alloc().init()
         self.assertTrue(hasattr(o, 'outlet1'))
         self.assertTrue(hasattr(o, 'outlet2'))
 
+class TestStructConvenience (TestCase):
+    def test_using_convenience(self):
+        for name, typestr in [
+                ('bool', objc._C_BOOL),
+                ('char', objc._C_CHR),
+                ('int', objc._C_INT),
+                ('short', objc._C_SHT),
+                ('long', objc._C_LNG),
+                ('long_long', objc._C_LNG_LNG),
+                ('unsigned_char', objc._C_UCHR),
+                ('unsigned_int', objc._C_UINT),
+                ('unsigned_short', objc._C_USHT),
+                ('unsigned_long', objc._C_ULNG),
+                ('unsigned_long_long', objc._C_ULNG_LNG),
+                ('float', objc._C_FLT),
+                ('double', objc._C_DBL),
+                ('BOOL', objc._C_NSBOOL),
+                ('UniChar', objc._C_UNICHAR),
+                ('char_text', objc._C_CHAR_AS_TEXT),
+                ('char_int', objc._C_CHAR_AS_INT),
+            ]:
+            self.assertHasAttr(objc.ivar, name)
+            v = getattr(objc.ivar, name)()
+            self.assertIsInstance(v, objc.ivar)
+            self.assertEqual(v.__typestr__, typestr)
+            self.assertEqual(v.__name__, None)
+            self.assertFalse(v.__isOutlet__)
+            self.assertFalse(v.__isSlot__)
+
+            v = getattr(objc.ivar, name)('my_var')
+            self.assertIsInstance(v, objc.ivar)
+            self.assertEqual(v.__typestr__, typestr)
+            self.assertEqual(v.__name__, 'my_var')
+            self.assertFalse(v.__isOutlet__)
+            self.assertFalse(v.__isSlot__)
 
 if __name__ == '__main__':
     main()

pyobjc-core/PyObjCTest/test_structs.py

         self.assertHasAttr(o, 'c')
         self.assertHasAttr(o, 'd')
 
+        self.assertHasAttr(objc.ivar, 'FooStruct')
+        v = objc.ivar.FooStruct()
+        self.assertIsInstance(v, objc.ivar)
+        self.assertEqual(v.__typestr__, tp.__typestr__)
 
 
     def testNamedTupleAPI(self):
         self.assertHasAttr(o, 'h')
 
     def testEmbeddedFields(self):
-        tp = objc.createStructType("FooStruct", b'{FooStruct="first"i"second"i}', None)
+        tp = objc.createStructType("BarStruct", b'{FooStruct="first"i"second"i}', None)
 
         v = OC_StructTest.createWithFirst_andSecond_(1, 2)
         self.assertIsInstance(v, tp)
         self.assertEqual(v.first, 1)
         self.assertEqual(v.second, 2)
 
+        self.assertHasAttr(objc.ivar, 'BarStruct')
+        v = objc.ivar.BarStruct()
+        self.assertEqual(v.__typestr__, b'{FooStruct=ii}')
+
     def testStructCallback(self):
         """
         Regression test for an issue reported on the PyObjC mailinglist.