Commits

Ronald Oussoren committed 94399a9

Significant improvements to the new metadata system

Most Cocoa tests now pass with the new metadata system.

Also fixes some clang warnings

Comments (0)

Files changed (304)

pyobjc-core/Lib/PyObjCTools/_BSCompiler.py

+"""
+Helper script for compiling .brigesupport files into a more compact form
+
+Note: the format of the compiled data is unstable for now, new versions
+of PyObjC can and will use different formats.
+"""
+import getopt
+import sys
+from xml.etree import ElementTree
+import os
+import time
+import json
+
+import objc
+
+gUsage = "Usage: pyobjc-compile-bridgesupport --input=FILE --output=FILE"
+
+class bstr(str):
+    __slots__ = ()
+
+    def __repr__(self):
+        result = super(bstr, self).__repr__()
+        if result.startswith('b'):
+            return result
+        return 'b' + result
+
+class funccall (object):
+    def __init__(self, name, args=None, kwds=None):
+        self._name = name
+
+        self._args = ()
+        self._kwds = {}
+
+        if args is not None:
+            self._args = args
+        if kwds is not None:
+            self._kwds = kwds
+
+    def __call__(self, *args, **kwds):
+        self._args = args
+        self._kwds = kwds
+
+    def __repr__(self):
+        result = [self._name, '(']
+        for a in self._args:
+            if result[-1] != '(':
+                result.append(', ')
+            result.append(repr(a))
+
+        for k, v in self._kwds.iteritems():
+            if result[-1] != '(':
+                result.append(', ')
+            result.append(k)
+            result.append('=')
+            result.append(repr(v))
+        result.append(')')
+        return ''.join(result)
+
+def sel32or64(a, b):
+    return funccall('sel32or64', (a, b))
+
+def littleOrBig(a, b):
+    return funccall('littleOrBig', (a, b))
+
+
+def main():
+    try:
+        opts, args = getopt.getopt(sys.argv[1:], 'Vh?i:o:', ['version', 'help', 'input=', 'output='])
+
+    except getopt.error,  msg:
+        print >>sys.stderr, msg
+        print >>sys.stderr, gUsage
+        sys.exit(1)
+
+    input = None
+    output = None
+
+    if args:
+        print >>sys.stderr, "Additional arguments"
+        print >>sys.stderr, gUsage
+        sys.exit(1)
+
+    for k, v in opts:
+        if k in ('-V', '--version'):
+            print "pyobjc %s"%(objc.__version__,)
+            sys.exit(0)
+
+        elif k in ('-h', '-?', '--help'):
+            print gUsage
+            sys.exit(0)
+
+        elif k in ('-i', '--input'):
+            input = v
+
+        elif k in ('-o', '--output'):
+            output = v 
+
+        else:
+            raise RuntimeError("Unhandled command-line option")
+
+
+    if input is None or output is None:
+        print >>sys.stderr, "Specify input and output files"
+        print >>sys.stderr, gUsage
+        sys.exit(1)
+
+    try:
+        input_tree = ElementTree.parse(input)
+    except Exception, msg:
+        print >>sys.stderr, msg
+        sys.exit(1)
+
+    fp = open(output, 'w')
+    print >>fp, "# Generated file, don't edit"
+    print >>fp, "# Source: %s"%(input,)
+    print >>fp, "# Last update: %s"%(time.ctime(),)
+    print >>fp, ""
+    print >>fp, "import objc, sys"
+    print >>fp, ""
+    print >>fp, "if sys.maxint > 2 ** 32:"
+    print >>fp, "    def sel32or64(a, b): return b"
+    print >>fp, "else:"
+    print >>fp, "    def sel32or64(a, b): return a"
+    print >>fp, "if sys.byteorder == 'little':"
+    print >>fp, "    def littleOrBig(a, b): return a"
+    print >>fp, "else:"
+    print >>fp, "    def littleOrBig(a, b): return b"
+    print >>fp, ""
+
+    emit_misc(fp, input_tree)
+    emit_constants(fp, input_tree)
+    emit_enums(fp, input_tree)
+    emit_strconsts(fp, input_tree)
+    emit_functions(fp, input_tree)
+    emit_cftype(fp, input_tree)
+    emit_classes(fp, input_tree)
+    emit_informal_protocols(fp, input_tree)
+
+def rewrite_typecode(value):
+    result = []
+
+    while value and value[0] in (objc._C_PTR, objc._C_IN, objc._C_INOUT, objc._C_ONEWAY, objc._C_CONST):
+        result.append(value[0])
+        value = value[1:]
+
+    if value[0] == objc._C_BOOL:
+        result.append(objc._C_NSBOOL)
+        value = value[1:]
+
+    elif value[0] == objc._C_NSBOOL:
+        result.append(objc._C_BOOL)
+        value = value[1:]
+
+    elif value[0] == objc._C_STRUCT_B:
+        while value[0] != '=' and value[0] != objc._C_STRUCT_E:
+            result.append(value[0])
+            value = value[1:]
+
+        if value[0] == '=':
+            result.append(value[0])
+            value = value[1:]
+
+        while value[0] != objc._C_STRUCT_E:
+            if value[0] == '"':
+                # Embedded field name
+                result.append(value[0])
+                value = value[1:]
+                while value[0] != '"':
+                    result.append(value[0])
+                    value = value[1:]
+                result.append(value[0])
+                value = value[1:]
+
+            cur, value = rewrite_typecode(value)
+            result.append(cur)
+
+        result.append(objc._C_STRUCT_E)
+        value = value[1:]
+
+    elif value[0] == objc._C_UNION_B:
+        while value[0] != '=' and value[0] != objc._C_UNION_E:
+            result.append(value[0])
+            value = value[1:]
+
+        if value[0] == '=':
+            result.append(value[0])
+            value = value[1:]
+
+        while value[0] != objc._C_UNION_E:
+            if value[0] == '"':
+                # Embedded field name
+                result.append(value[0])
+                value = value[1:]
+                while value[0] != '"':
+                    result.append(value[0])
+                    value = value[1:]
+                result.append(value[0])
+                value = value[1:]
+
+            cur, value = rewrite_typecode(value)
+            result.append(cur)
+
+        result.append(objc._C_UNION_E)
+        value = value[1:]
+
+    elif value[0] == objc._C_ARY_B:
+        result.append(value[0])
+        value = value[1:]
+        while value[0].isdigit():
+            result.append(value[0])
+            value = value[1:]
+
+        while value[0] != objc._C_ARY_E:
+            cur, value = rewrite_typecode(value)
+            result.append(cur)
+
+        result.append(value[0])
+        value = value[1:]
+
+    else:
+        result.append(value[0])
+        value = value[1:]
+
+    return ''.join(result), value
+
+def rewrite_typestr(value):
+    if value is None: return value
+    result = []
+
+    cur, rest = rewrite_typecode(value)
+    result.append(cur)
+
+    while rest:
+        cur, rest = rewrite_typecode(rest)
+        result.append(cur)
+    return ''.join(result)
+
+def emit_misc(fp, tree):
+    fp.write("misc = {\n")
+
+    for node in tree.findall('.//opaque'):
+        if node.get('ignore', 'false') == 'true':
+            continue
+        name = node.get('name')
+        type = node.get('type')
+        type64 = node.get('type64')
+
+        if type64 is None or type == type64:
+            fp.write('    "%s": objc.createOpaquePointerType(%r, b%r),\n'%(
+                name, name, rewrite_typestr(type)))
+        else:
+            fp.write('    "%s": objc.createOpaquePointerType(%r, sel32or64(b%r, b%r)),\n'%(
+                name, name, rewrite_typestr(type), rewrite_typestr(type64)))
+
+    for node in tree.findall('.//struct'):
+        if node.get('ignore', 'false') == 'true':
+            continue
+        name = node.get('name')
+        type = node.get('type')
+        type64 = node.get('type64')
+
+
+        if type64 is None or type == type64:
+            fp.write('    "%s": objc.createStructType(%r, b%r, None),\n'%(
+                name, name, rewrite_typestr(type)))
+        else:
+            fp.write('    "%s": objc.createStructType(%r, sel32or64(b%r, b%r), None),\n'%(
+                name, name, rewrite_typestr(type), rewrite_typestr(type64)))
+
+
+    fp.write("}\n")
+
+def emit_constants(fp, tree):
+
+    fp.write("constants = '''$")
+    for node in tree.findall('.//constant'):
+        if node.get('ignore', 'false') == 'true':
+            continue
+        name = node.get("name")
+        type = rewrite_typestr(node.get("type", "@"))
+
+        if type[0] == '{':
+            _, rest = type.split('=', 1)
+            if '?' in rest:
+                # Skip structs with embedded function pointers and
+                # other unhandled types
+                continue
+
+        type = rewrite_typestr(type)
+
+        if node.get("magic_cookie", "false") == "true":
+            type = "=" + type
+
+        if type == "@":
+            fp.write(name)
+        else:
+            fp.write(name)
+            fp.write("@")
+            fp.write(type)
+        fp.write("$")
+    fp.write("'''\n")
+
+
+def emit_enums(fp, tree):
+    others = {}
+    fp.write("enums = '''$")
+    for node in tree.findall('.//enum'):
+        if node.get('ignore', 'false') == 'true':
+            continue
+        name = node.get("name")
+        value = node.get("value")
+        value64 = node.get("value64")
+
+        if value is None and value64 is not None:
+            value = value64
+
+        if value is None:
+            le_value = int(node.get("le_value"))
+            be_value = int(node.get("be_value"))
+            others[name] = littleOrBig(le_value, be_value)
+
+        elif value64 is None or value64 == value:
+            fp.write(name)
+            fp.write("@")
+            fp.write(value)
+            fp.write("$")
+
+        else:
+            others[name] = sel32or64(value, value64)
+
+    fp.write("'''\n")
+
+    if others:
+        fp.write("misc.update(%r)\n"%(others,))
+
+
+
+def emit_strconsts(fp, tree):
+    items = {}
+    for node in tree.findall('.//string_constant'):
+        if node.get('ignore', 'false') == 'true':
+            continue
+        nm = node.get('name')
+        value = node.get('value')
+        isstr = node.get('nsstring', 'false') == 'true'
+        if not isstr:
+            value = value.encode('ascii')
+        items[nm] = value
+
+    print >>fp, "string_constants = %s"%(items)
+
+def emit_functions(fp, tree):
+    items = {}
+    for node in tree.findall('.//function'):
+        if node.get('ignore', 'false') == 'true':
+            continue
+
+        name = node.get('name')
+        types = [b'v']
+        types64 = [b'v']
+        retval = None
+        arguments = []
+        meta = {}
+
+        if node.get('variadic', 'false') == 'true':
+            meta['variadic'] = 'true'
+            if node.get('c_array_delimited_by_null', 'false') == 'true':
+                meta['c_array_delimited_by_null'] = True
+
+            if node.get('c_array_delimited_by_null') is not None:
+                meta['c_array_length_in_arg'] =  \
+                        int(node.get('c_array_length_in_arg'))
+
+        for child in node:
+            if child.tag == 'retval':
+                retval = {}
+                convert_argnode(False, child, retval)
+
+                if child.get('type64') is not None:
+                    types64[0] = rewrite_typestr(child.get('type64'))
+                else:
+                    types64[0] = rewrite_typestr(child.get('type'))
+
+                types[0] = rewrite_typestr(child.get('type'))
+
+            elif child.tag == 'arg':
+                info = {}
+                convert_argnode(False, child, info)
+                arguments.append(info)
+                
+                if child.get('type64') is not None:
+                    types64.append(rewrite_typestr(child.get('type64')))
+                else:
+                    types64.append(rewrite_typestr(child.get('type')))
+
+                types.append(rewrite_typestr(child.get('type')))
+
+            else:
+                raise ValueError("Child node %s of function node"%(child.tag,))
+
+        if retval is not None:
+            k = list(retval.keys())
+            k.sort()
+            if k in (['type'], ['type', 'type64']):
+                # No additional information, no need to store meta information
+                pass
+
+            else:
+                meta['retval'] = retval
+
+        if arguments:
+            have_meta = False
+            for a in arguments:
+                k = list(a.keys())
+                k.sort()
+                if k in (['type'], ['type', 'type64']):
+                    # No additional information, no need to store meta 
+                    # information
+                    pass
+                else:
+                    have_meta = True
+
+            if have_meta:
+                meta['arguments'] = dict(zip(range(len(arguments)), arguments))
+
+        if meta == {}:
+            meta = None
+
+        if types[0] is None:
+            types[0] = 'v'
+
+        if types64[0] is None:
+            types64[0] = 'v'
+
+
+        types = ''.join(types)
+        types64 = ''.join(types64)
+
+        if types != types64:
+            if meta is None:
+                items[name] = (sel32or64(types, types64),)
+            else:
+                items[name] = (sel32or64(types, types64), "", meta)
+        else:
+            if meta is None:
+                items[name] = (types,)
+            else:
+                items[name] = (types, "", meta)
+
+
+    fp.write("functions = %r\n"%(items,))
+
+
+BOOLEAN_ATTRIBUTES=[
+    ("already_retained", False),
+    ("already_cfretained", False),
+    ("c_array_length_in_result", False),
+    ("c_array_delimited_by_null", False),
+    ("c_array_of_variable_length", False),
+    ("printf_format", False),
+    ("free_result", False),
+    ("null_accepted", True),
+]
+
+def parse_callable(isfunction, node, dct):
+    if node.get('function_pointer_retained', 'true') == 'false':
+        dct['callable_retained'] = False
+
+    meta = dct['callable'] = {}
+    meta['arguments'] = arguments = {}
+    idx = 0
+
+    if not isfunction:
+        # Blocks have an implicit first argument
+        arguments[idx] = {
+                'type': '^v',
+        }
+        idx += 1
+
+    for child in node:
+        if child.tag == 'retval':
+            retval = meta['retval'] = {}
+            convert_argnode(False, child, retval)
+
+        elif child.tag == 'arg':
+            info = {}
+            convert_argnode(False, child, info)
+            arguments[idx] = info
+            idx += 1
+
+        else:
+            raise ValueError("Child node %s of function node"%(child.tag,))
+
+    if meta.get('retval') is None:
+        meta['retval'] = {
+            'type': 'v',
+        }
+
+        
+
+def convert_argnode(ismethod, node, dct):
+    if ismethod:
+        argoffset = 2
+    else:
+        argoffset = 0
+
+    v = node.get('type_modifier')
+    if v is not None:
+        dct['type_modifier'] = bstr(v)
+
+    type = node.get('type')
+    type64 = node.get('type64')
+    if type is not None:
+        if type64 is None or type == type64:
+            dct['type'] = bstr(rewrite_typestr(type))
+        else:
+            dct['type'] = sel32or64(
+                    bstr(rewrite_typestr(type)),
+                    bstr(rewrite_typestr(type64)))
+
+    sel_of_type = node.get('sel_of_type')
+    sel_of_type64 = node.get('sel_of_type64')
+    if sel_of_type is not None:
+        if sel_of_type64 is None or sel_of_type == sel_of_type64:
+            dct['sel_of_type'] = bstr(rewrite_typestr(sel_of_type))
+        else:
+            dct['sel_of_type'] = sel32or64(
+                    bstr(rewrite_typestr(sel_of_type)),
+                    bstr(rewrite_typestr(sel_of_type64)))
+
+    v = node.get('c_array_of_fixed_length')
+    if v is not None:
+        dct['c_array_of_fixed_length'] = int(v)
+
+
+    v = node.get('c_array_length_in_arg')
+    if v is not None:
+        if ',' in v:
+            a, b = v.split(',')
+            a = a.strip()
+            b = b.strip()
+
+            dct['c_array_length_in_arg'] = int(a)+argoffset, int(b)+argoffset
+        else:
+            dct['c_array_length_in_arg'] = int(v)+argoffset
+
+
+    v = node.get('function_pointer')
+    if v == 'true':
+        parse_callable(True, node, dct)
+
+    v = node.get('block')
+    if v == 'true':
+        parse_callable(False, node, dct)
+
+
+    for attr, default in BOOLEAN_ATTRIBUTES:
+        v = node.get(attr)
+        if v is not None:
+            if v == 'true':
+                v = True
+            else:
+                v = False
+
+            if v != default:
+                dct[attr] = v
+
+
+def emit_classes(fp, tree):
+    print >>fp, "r = objc.registerMetaDataForSelector"
+    print >>fp, "objc._updatingMetadata(True)"
+    print >>fp, "try:"
+    print >>fp, "    pass"
+    for node in tree.findall('.//class'):
+        if node.get('ignore', 'false') == 'true':
+            continue
+        clsname = node.get('name')
+        for method in node:
+            if method.tag != 'method': continue
+
+            if method.get('ignore', 'false') == 'true':
+                continue
+            sel = bstr(method.get('selector'))
+            meta = {}
+            for info in method:
+                if info.tag == 'retval':
+                    n = meta['retval'] = {}
+                elif info.tag == 'arg':
+                    if 'arguments' not in meta:
+                        meta['arguments'] = {}
+
+                    n = meta['arguments'][int(info.get('index'))+2] = {}
+
+                convert_argnode(True, info, n)
+
+            print >>fp, '    r(%r, %r, %r)'%(clsname, sel, meta)
+
+    print >>fp, "finally:"
+    print >>fp, "    objc._updatingMetadata(False)"
+
+def emit_cftype(fp, tree):
+    print >>fp, "cftypes = []"
+    for node in tree.findall('.//cftype'):
+        name = node.get('name')
+        type = node.get('type')
+        type64= node.get('type64')
+        if type64 is not None and type64 != type:
+            type = sel32or64(type, type64)
+
+        gettypeid_func = node.get('gettypeid_func')
+        tollfree= node.get('tollfree')
+
+        print >>fp, "cftypes.append((%r, %r, %r, %r))"%(name, type, gettypeid_func, tollfree)
+
+
+
+
+def prot(name, methods):
+    return funccall('objc.informal_protocol', (name, methods))
+
+def sel(selector, type):
+    return funccall('objc.selector', (None, selector, type), {'isRequired': False})
+
+def emit_informal_protocols(fp, tree):
+    protocols = {
+    }
+    for node in tree.findall('.//informal_protocol'):
+        name = node.get('name')
+
+        methods = []
+
+        for method in node:
+            selector = method.get('selector')
+            type = rewrite_typestr(method.get('type'))
+            type64 = rewrite_typestr(method.get('type64'))
+
+            if type64 is not None and type != type64:
+                type = sel32or64(type, type64)
+
+            methods.append(sel(selector, type))
+
+        protocols[name] = prot(name, methods)
+
+    if protocols:
+        fp.write('protocols=%s\n'%(protocols))

pyobjc-core/Lib/objc/__init__.py

 from objc._locking import *
 from objc._context import *
 from objc._properties import *
+from objc._lazyimport import *
 
 import objc._pycoder as _pycoder
 

pyobjc-core/Lib/objc/_bridgesupport.py

 
 XXX: This file needs to be rewritten in C for optimal speed.
 """
-__all__ = ('initFrameworkWrapper', )
+#__all__ = ('initFrameworkWrapper', )
+__all__ = ()
 
 import objc
 import pkg_resources
 import sys, os, struct
 import textwrap
+import warnings
 
 from objc import function, registerMetaDataForSelector
 
                 retval=dict(already_retained=True),
             ))
 
-def _parseBridgeSupport(data, globals, frameworkName, *args, **kwds):
-    try:
+if 0:
+    def _parseBridgeSupport(data, globals, frameworkName, *args, **kwds):
         try:
-            objc.parseBridgeSupport(data, globals, frameworkName, *args, **kwds)
-        except objc.internal_error, e:
-            import warnings
-            warnings.warn("Error parsing BridgeSupport data for %s: %s" % (frameworkName, e), RuntimeWarning)
-    finally:
-        # Add formal protocols to the protocols submodule, for backward
-        # compatibility with earlier versions of PyObjC
-        if 'protocols' in globals:
-            for p in objc.protocolsForProcess():
-                setattr(globals['protocols'], p.__name__, p)
+            try:
+                objc.parseBridgeSupport(data, globals, frameworkName, *args, **kwds)
+            except objc.internal_error, e:
+                import warnings
+                warnings.warn("Error parsing BridgeSupport data for %s: %s" % (frameworkName, e), RuntimeWarning)
+        finally:
+            # Add formal protocols to the protocols submodule, for backward
+            # compatibility with earlier versions of PyObjC
+            if 'protocols' in globals:
+                for p in objc.protocolsForProcess():
+                    setattr(globals['protocols'], p.__name__, p)
 
-def initFrameworkWrapper(frameworkName,
-        frameworkPath, frameworkIdentifier, globals, inlineTab=None, 
-        scan_classes=None, frameworkResourceName=None):
-    """
-    Load the named framework, using the identifier if that has result otherwise
-    using the path. Also loads the information in the bridgesupport file (
-    either one embedded in the framework or one in a BrigeSupport library
-    directory).
-    """
-    if frameworkResourceName is None:
-        frameworkResourceName = frameworkName
+    def initFrameworkWrapper(frameworkName,
+            frameworkPath, frameworkIdentifier, globals, inlineTab=None, 
+            scan_classes=None, frameworkResourceName=None):
+        """
+        Load the named framework, using the identifier if that has result otherwise
+        using the path. Also loads the information in the bridgesupport file (
+        either one embedded in the framework or one in a BrigeSupport library
+        directory).
+        """
+        warnings.warn("objc.initFrameworkWrapper is deprecated", DeprecationWaring)
 
-    if frameworkIdentifier is None:
-        if scan_classes is None:
-            bundle = objc.loadBundle(
-                frameworkName,
-                globals,
-                bundle_path=frameworkPath)
-        else:
-            bundle = objc.loadBundle(
-                frameworkName,
-                globals,
-                bundle_path=frameworkPath,
-                scan_classes=scan_classes)
+        if frameworkResourceName is None:
+            frameworkResourceName = frameworkName
 
-    else:
-        try:
-            if scan_classes is None:
-                bundle = objc.loadBundle(
-                    frameworkName,
-                    globals,
-                    bundle_identifier=frameworkIdentifier)
-
-            else:
-                bundle = objc.loadBundle(
-                    frameworkName,
-                    globals,
-                    bundle_identifier=frameworkIdentifier,
-                    scan_classes=scan_classes)
-        
-        except ImportError:
+        if frameworkIdentifier is None:
             if scan_classes is None:
                 bundle = objc.loadBundle(
                     frameworkName,
                     bundle_path=frameworkPath,
                     scan_classes=scan_classes)
 
+        else:
+            try:
+                if scan_classes is None:
+                    bundle = objc.loadBundle(
+                        frameworkName,
+                        globals,
+                        bundle_identifier=frameworkIdentifier)
 
-    # Make the objc module available, because it contains a lot of useful
-    # functionality.
-    globals['objc'] = objc
+                else:
+                    bundle = objc.loadBundle(
+                        frameworkName,
+                        globals,
+                        bundle_identifier=frameworkIdentifier,
+                        scan_classes=scan_classes)
+            
+            except ImportError:
+                if scan_classes is None:
+                    bundle = objc.loadBundle(
+                        frameworkName,
+                        globals,
+                        bundle_path=frameworkPath)
+                else:
+                    bundle = objc.loadBundle(
+                        frameworkName,
+                        globals,
+                        bundle_path=frameworkPath,
+                        scan_classes=scan_classes)
 
-    # Explicitly push objc.super into the globals dict, that way super
-    # calls will behave as expected in all cases.
-    globals['super'] = objc.super
 
-    if 1:
-        # Look for metadata in the Python wrapper and prefer that over the
-        # data in the framework or in system locations. 
-        # Needed because the system bridgesupport files are buggy.
-        try:
-            exists = pkg_resources.resource_exists(
-                    frameworkResourceName, "PyObjC.bridgesupport")
-        
-        except ImportError:
-            pass
+        # Make the objc module available, because it contains a lot of useful
+        # functionality.
+        globals['objc'] = objc
 
-        else:
-            if exists:
-                data = pkg_resources.resource_string(frameworkResourceName,
-                    "PyObjC.bridgesupport")
-                if data:
-                    _parseBridgeSupport(data, globals, frameworkName, inlineTab=inlineTab)
-                return bundle
+        # Explicitly push objc.super into the globals dict, that way super
+        # calls will behave as expected in all cases.
+        globals['super'] = objc.super
 
-    # Look for metadata in the framework bundle
-    path = bundle.pathForResource_ofType_inDirectory_(frameworkName, 'bridgesupport', 'BridgeSupport')
-    if path is not None:
-        dylib_path = bundle.pathForResource_ofType_inDirectory_(frameworkName, 'dylib', 'BridgeSupport')
-        data = open(path, 'rb').read()
-        if dylib_path is not None:
-            _parseBridgeSupport(data, globals, frameworkName, dylib_path)
-        else:
-            _parseBridgeSupport(data, globals, frameworkName)
+        if 1:
+            # Look for metadata in the Python wrapper and prefer that over the
+            # data in the framework or in system locations. 
+            # Needed because the system bridgesupport files are buggy.
+            try:
+                exists = pkg_resources.resource_exists(
+                        frameworkResourceName, "PyObjC.bridgesupport")
+            
+            except ImportError:
+                pass
 
-        # Check if we have additional metadata bundled with PyObjC
-        try:
-            exists = pkg_resources.resource_exists(
-                frameworkResourceName, "PyObjCOverrides.bridgesupport")
-        
-        except ImportError:
-            pass
+            else:
+                if exists:
+                    data = pkg_resources.resource_string(frameworkResourceName,
+                        "PyObjC.bridgesupport")
+                    if data:
+                        _parseBridgeSupport(data, globals, frameworkName, inlineTab=inlineTab)
+                    return bundle
 
-        else:
-            if exists:
-                data = pkg_resources.resource_string(frameworkResourceName,
-                    "PyObjCOverrides.bridgesupport")
-                if data:
-                    _parseBridgeSupport(data, globals, frameworkName, inlineTab=inlineTab)
-
-        return bundle
-    
-    # If there is no metadata there look for metadata in the standard Library
-    # locations
-    fn = frameworkName + '.bridgesupport'
-    for dn in _gBridgeSupportDirectories:
-        path = os.path.join(dn, fn)
-        if os.path.exists(path):
+        # Look for metadata in the framework bundle
+        path = bundle.pathForResource_ofType_inDirectory_(frameworkName, 'bridgesupport', 'BridgeSupport')
+        if path is not None:
+            dylib_path = bundle.pathForResource_ofType_inDirectory_(frameworkName, 'dylib', 'BridgeSupport')
             data = open(path, 'rb').read()
-
-            dylib_path = os.path.join(dn, frameworkName + '.dylib')
-            if os.path.exists(dylib_path):
+            if dylib_path is not None:
                 _parseBridgeSupport(data, globals, frameworkName, dylib_path)
             else:
                 _parseBridgeSupport(data, globals, frameworkName)
-            
+
             # Check if we have additional metadata bundled with PyObjC
             try:
                 exists = pkg_resources.resource_exists(
                     frameworkResourceName, "PyObjCOverrides.bridgesupport")
-
+            
             except ImportError:
                 pass
 
                         "PyObjCOverrides.bridgesupport")
                     if data:
                         _parseBridgeSupport(data, globals, frameworkName, inlineTab=inlineTab)
+
             return bundle
-    
-    # And if that fails look for the metadata in the framework wrapper
-    if pkg_resources.resource_exists(
-            frameworkName, "PyObjC.bridgesupport"):
-        data = pkg_resources.resource_string(frameworkResourceName,
-            "PyObjC.bridgesupport")
-        if data:
-            _parseBridgeSupport(data, globals, frameworkName, inlineTab=inlineTab)
-        return bundle
-    
-    return bundle
+        
+        # If there is no metadata there look for metadata in the standard Library
+        # locations
+        fn = frameworkName + '.bridgesupport'
+        for dn in _gBridgeSupportDirectories:
+            path = os.path.join(dn, fn)
+            if os.path.exists(path):
+                data = open(path, 'rb').read()
 
-def _setupCFClasses(globalDict, cftypes):
-    """
-    Foundation types have a fully procedural C-interface, but that can
-    easily be transformed into an OO interface. This function performs that
-    transformation.
-    
-    Function are transformed into methods by looking for functions whose name
-    starts with the type and and whose first argument is of the type. As a
-    special case 'Create' functions are transformed into class methods.
-    
-    Note that this function *adds* an OO-interface, the fully procedural API
-    won't be removed.
-    
-    Example:
-        
-        url = CFURL.createWithFileSystemPath("/tmp")
-        print url.copyHostName()
-    
-    In the procedural API:
-        url = CFURLCreateWithFileSystemPath(None, "/tmp")
-        print CFURLCopyHostName(url)
-    
-    XXX: need to add information about this feature to the documentation
-    """
-    for name, encoding in cftypes:
-        if name.endswith('Ref'):
-            name = name[:-3]
-        tp = globalDict[name + 'Ref']
+                dylib_path = os.path.join(dn, frameworkName + '.dylib')
+                if os.path.exists(dylib_path):
+                    _parseBridgeSupport(data, globals, frameworkName, dylib_path)
+                else:
+                    _parseBridgeSupport(data, globals, frameworkName)
+                
+                # Check if we have additional metadata bundled with PyObjC
+                try:
+                    exists = pkg_resources.resource_exists(
+                        frameworkResourceName, "PyObjCOverrides.bridgesupport")
 
-        for funcname in globalDict:
-            if not funcname.startswith(name):
-                continue
-            f = globalDict[funcname]
-            if not isinstance(f, function):
-                continue
-            metadata = f.__metadata__()
-
-            rest = funcname[len(name):]
-            if not rest[0].isupper():
-                continue
-            
-            rest = rest[0].lower() + rest[1:]
-            
-            if rest.startswith('create') and metadata['retval']['type'] == encoding:
-                if len(metadata['arguments']) >= 1 and metadata['arguments'][0]['type'] == '^{__CFAllocator=}':
-                    argcount = len(metadata['arguments']) - 1
-                    argPrefix= 'None, '
-                    decorator = classmethod
+                except ImportError:
+                    pass
 
                 else:
-                    argcount = len(metadata['arguments'])
-                    argPrefix = ''
-                    decorator = classmethod
-           
+                    if exists:
+                        data = pkg_resources.resource_string(frameworkResourceName,
+                            "PyObjCOverrides.bridgesupport")
+                        if data:
+                            _parseBridgeSupport(data, globals, frameworkName, inlineTab=inlineTab)
+                return bundle
+        
+        # And if that fails look for the metadata in the framework wrapper
+        if pkg_resources.resource_exists(
+                frameworkName, "PyObjC.bridgesupport"):
+            data = pkg_resources.resource_string(frameworkResourceName,
+                "PyObjC.bridgesupport")
+            if data:
+                _parseBridgeSupport(data, globals, frameworkName, inlineTab=inlineTab)
+            return bundle
+        
+        return bundle
+
+    _ivar_dict = objc._ivar_dict()
+    del objc._ivar_dict
+    def _structConvenience(structname, structencoding):
+        def makevar(self, name=None):
+            if name is None:
+                return objc.ivar(type=structencoding)
             else:
-                argcount = len(metadata['arguments']) - 1
-                argPrefix= 'self, '
-                decorator = lambda x: x
+                return objc.ivar(name=name, type=structencoding)
+        _ivar_dict[structname] = classmethod(makevar)
 
-                if 'arguments' not in metadata or len(metadata['arguments']) == 0:
-                    if metadata['retval']['type'] == encoding:
-                        argPrefix = ''
-                        decorator = classmethod
-                        argcount = 0
-                    
-                    else:
-                        continue
-                
-                elif metadata['arguments'][0]['type'] != encoding:
-                    continue
-            
-            # We don't have argument names, therefore just count the
-            # arguments...
-            argList = ', '.join([ 'x%d'%(i) for i in range(argcount)])
-            funcdef = textwrap.dedent('''\
-                def %(rest)s(self, %(argList)s):
-                    return %(funcname)s(%(argPrefix)s%(argList)s)
-                ''')
-            funcdef = funcdef % locals()
-            g = {}
-            g.update(globalDict)
-            exec funcdef in g
-            func = g[rest]
-            
-            setattr(tp, rest, decorator(func))
-            
-            # XXX: for compatibility with MacPython we migth want to add
-            # `funcname` as a method as well (although preferably a version
-            # that gives a DeprecationWarning)
 
+    # Fake it for basic C types
+    _structConvenience("bool", objc._C_BOOL)
+    _structConvenience("char", objc._C_CHR)
+    _structConvenience("int", objc._C_INT)
+    _structConvenience("short", objc._C_SHT)
+    _structConvenience("long", objc._C_LNG)
+    _structConvenience("long_long", objc._C_LNG_LNG)
+    _structConvenience("unsigned_char", objc._C_UCHR)
+    _structConvenience("unsigned_int", objc._C_UINT)
+    _structConvenience("unsigned_short", objc._C_USHT)
+    _structConvenience("unsigned_long", objc._C_ULNG)
+    _structConvenience("unsigned_long_long", objc._C_ULNG_LNG)
+    _structConvenience("float", objc._C_FLT)
+    _structConvenience("double", objc._C_DBL)
+    _structConvenience("BOOL", objc._C_NSBOOL)
+    _structConvenience("UniChar", objc._C_UNICHAR)
+    _structConvenience("char_text", objc._C_CHAR_AS_TEXT)
+    _structConvenience("char_int", objc._C_CHAR_AS_INT)
 
-_ivar_dict = objc._ivar_dict()
-del objc._ivar_dict
-def _structConvenience(structname, structencoding):
-    def makevar(self, name=None):
-        if name is None:
-            return objc.ivar(type=structencoding)
-        else:
-            return objc.ivar(name=name, type=structencoding)
-    _ivar_dict[structname] = classmethod(makevar)
-
-
-# Fake it for basic C types
-_structConvenience("bool", objc._C_BOOL)
-_structConvenience("char", objc._C_CHR)
-_structConvenience("int", objc._C_INT)
-_structConvenience("short", objc._C_SHT)
-_structConvenience("long", objc._C_LNG)
-_structConvenience("long_long", objc._C_LNG_LNG)
-_structConvenience("unsigned_char", objc._C_UCHR)
-_structConvenience("unsigned_int", objc._C_UINT)
-_structConvenience("unsigned_short", objc._C_USHT)
-_structConvenience("unsigned_long", objc._C_ULNG)
-_structConvenience("unsigned_long_long", objc._C_ULNG_LNG)
-_structConvenience("float", objc._C_FLT)
-_structConvenience("double", objc._C_DBL)
-_structConvenience("BOOL", objc._C_NSBOOL)
-_structConvenience("UniChar", objc._C_UNICHAR)
-_structConvenience("char_text", objc._C_CHAR_AS_TEXT)
-_structConvenience("char_int", objc._C_CHAR_AS_INT)
-
-objc._setStructConvenience(_structConvenience)
-del objc._setStructConvenience
-
-
-# XXX: this is a nice-to-have, but adds a full second to the 
-# load time of importing Quartz.
-#objc._setSetupCFClasses(_setupCFClasses)
-#del objc._setSetupCFClasses
+    objc._setStructConvenience(_structConvenience)
+    del objc._setStructConvenience

pyobjc-core/Lib/objc/_lazyimport.py

+"""
+Helper module that will enable lazy imports of Cocoa wrapper items.
+
+This should improve startup times and memory usage, at the cost
+of not being able to use 'from Cocoa import *'
+"""
+__all__ = ('ObjCLazyModule',)
+
+import sys
+import re
+
+from objc import lookUpClass, getClassList, nosuchclass_error, loadBundle
+import objc
+module = type(sys)
+
+def _loadBundle(frameworkName, frameworkIdentifier, frameworkPath):
+    if frameworkIdentifier is None:
+        bundle = loadBundle(
+            frameworkName,
+            {},
+            bundle_path=frameworkPath,
+            scan_classes=False)
+
+    else:
+        try:
+            bundle = loadBundle(
+                frameworkName,
+                {},
+                bundle_identifier=frameworkIdentifier,
+                scan_classes=False)
+        
+        except ImportError:
+            bundle = loadBundle(
+                frameworkName,
+                {},
+                bundle_path=frameworkPath,
+                scan_classes=False)
+
+        return bundle
+
+class ObjCLazyModule (module):
+
+    # Define slots for all attributes, that way they don't end up it __dict__.
+    __slots__ = (
+                '_ObjCLazyModule__bundle', '_ObjCLazyModule__enummap', '_ObjCLazyModule__funcmap', 
+                '_ObjCLazyModule__parents', '_ObjCLazyModule__varmap', '_ObjCLazyModule__inlinelist',
+            )
+
+    def __init__(self, name, frameworkIdentifier, frameworkPath, metadict, inline_list, initialdict={}, parents=()):
+        super(ObjCLazyModule, self).__init__(name)
+
+        if frameworkIdentifier is not None or frameworkPath is not None:
+            self.__bundle = self.__dict__['__bundle__'] = _loadBundle(name, frameworkIdentifier, frameworkPath)
+
+        pfx = name + '.'
+        for nm in sys.modules:
+            if nm.startswith(pfx):
+                rest = nm[len(pfx):]
+                if '.' in rest: continue
+                if sys.modules[nm] is not None:
+                    self.__dict__[rest] = sys.modules[nm]
+
+        self.__dict__.update(initialdict)
+        self.__dict__.update(metadict.get('misc', {}))
+        self.__parents = parents
+        self.__varmap = metadict.get('constants')
+        self.__enummap = metadict.get('enums')
+        self.__funcmap = metadict.get('functions')
+        self.__inlinelist = inline_list
+
+        self.__load_cftypes(metadict.get('cftypes'))
+
+    def __dir__(self):
+        return self.__all__
+
+    def __getattr__(self, name):
+        if name == "__all__":
+            # Load everything immediately
+            value = self.__calc_all()
+            self.__dict__[name] = value
+            return value
+
+        # First try parent module, as we had done
+        # 'from parents import *'
+        for p in self.__parents:
+            try:
+                value = getattr(p, name)
+            except AttributeError:
+                pass
+
+            else:
+                self.__dict__[name] = value
+                return value
+        
+        # Check if the name is a constant from
+        # the metadata files
+        try:
+            value = self.__get_constant(name)
+        except AttributeError:
+            pass
+        else:
+            self.__dict__[name] = value
+            return value
+
+        # Then check if the name is class
+        try:
+            value = lookUpClass(name)
+        except nosuchclass_error:
+            pass
+
+        else:
+            self.__dict__[name] = value
+            return value
+
+        # Finally give up and raise AttributeError
+        raise AttributeError(name)
+
+    def __calc_all(self):
+        all = set()
+
+        # Ensure that all dynamic entries get loaded
+        if self.__varmap:
+            for nm in re.findall(r"\$([A-Z0-9a-z_]*)(?:@[^$]*)?(?=\$)", self.__varmap):
+                try:
+                    getattr(self, nm)
+                except AttributeError:
+                    pass
+
+        if self.__enummap:
+            for nm in re.findall(r"\$([A-Z0-9a-z_]*)@[^$]*(?=\$)", self.__enummap):
+                try:
+                    getattr(self, nm)
+                except AttributeError:
+                    pass
+
+        if self.__funcmap:
+            for nm in self.__funcmap:
+                try:
+                    getattr(self, nm)
+                except AttributeError:
+                    pass
+
+
+        # Add all names that are already in our __dict__
+        all.update(self.__dict__)
+
+        # Merge __all__of parents ('from parent import *')
+        for p in self.__parents:
+            all.update(getattr(p, '__all__', ()))
+
+        # Add all class names
+        all.update(cls.__name__ for cls in getClassList())
+
+
+        return [ v for v in all if not v.startswith('_') ]
+
+        return list(all)
+
+    def __get_constant(self, name):
+        # FIXME: Loading variables and functions requires too much
+        # code at the moment, the objc API can be adjusted for
+        # this later on.
+        if self.__varmap:
+            m = re.search(r"\$%s(@[^$]*)?\$"%(name,), self.__varmap)
+            if m is not None:
+                tp = m.group(1)
+                if tp is None:
+                    tp = '@'
+                else:
+                    tp = tp[1:]
+
+                d = {}
+                if tp.startswith('='):
+                    tp = tp[1:]
+                    magic = True
+                else:
+                    magic = False
+
+                return objc._loadConstant(name, tp, magic)
+
+        if self.__enummap:
+            m = re.search(r"\$%s@([^$]*)\$"%(name,), self.__enummap)
+            if m is not None:
+                val = m.group(1)
+
+                if '.' in val:
+                    val = float(val)
+                else:
+                    val = int(val)
+
+                return val
+
+        if self.__funcmap:
+            if name in self.__funcmap:
+                info = self.__funcmap[name]
+
+                func_list = [ (name,) + info ]
+
+                d = {}
+                objc.loadBundleFunctions(self.__bundle, d, func_list)
+                if name in d:
+                    return d[name]
+
+                if self.__inlinelist is not None:
+                    objc._loadFunctionList(
+                            self.__inlinelist, d, func_list, skip_undefined=False)
+                    if name in d:
+                        return d[name]
+
+
+
+        raise AttributeError(name)
+
+    def __load_cftypes(self, cftypes):
+        if not cftypes: return
+
+        for name, type, gettypeid_func, tollfree in cftypes:
+            if tollfree:
+                v = objc.registerCFSignature(name, type, None, tollfree)
+                if v is not None:
+                    self.__dict__[name] = v
+                    continue
+            try:
+                func = getattr(self, gettypeid_func)
+            except AttributeError:
+                # GetTypeID function not found, this is either 
+                # a CFType that isn't present on the current
+                # platform, or a CFType without a public GetTypeID
+                # function. Proxy using the generic CFType
+                if tollfree is None:
+                    v = objc.registerCFSignature(name, type, None, 'NSCFType')
+                    if v is not None:
+                        self.__dict__[name] = v
+                continue
+
+            if tollfree:
+                v = objc.registerCFSignature(name, type, func(), tollfree)
+            else:
+                v = objc.registerCFSignature(name, type, func())
+            if v is not None:
+                self.__dict__[name] = v

pyobjc-core/Modules/objc/bundle-variables.m

 		PyErr_SetString(PyExc_TypeError, "function_list not a PyCapsule");
 		return NULL;
 	}
-	function_list = PyCapsule_GetPointer(pyFunctionsList, "objc.__functionlist__");
+	function_list = PyCapsule_GetPointer(pyFunctionsList, "objc.__inline__");
 	if (function_list == NULL) {
 		PyErr_SetString(PyExc_ValueError, "no function list\n");
 		return NULL;
 			return NULL;
 		}
 
+
 		value = find_function(function_list, name);
 		if (value == NULL) {
 			if (!skip_undefined) {

pyobjc-core/Modules/objc/method-signature.m

 	PyObject* metadata;
 
 	metadata = PyObjC_FindInRegistry(registry, cls, sel);
+
 	methinfo =  PyObjCMethodSignature_WithMetaData(signature, metadata, is_native);
 	if (isClassMethod) {
 		const char* nm  = sel_getName(sel);

pyobjc-core/Modules/objc/module.m

 	return NULL;
 }
 
+#if 0
 PyDoc_STRVAR(parseBridgeSupport_doc,
  "parseBridgeSupport(xmldata, globals, framework [, dylib_path] [, inlineTab]) -> None\n"
  "\n"
 	Py_INCREF(Py_None);
 	return Py_None;
 }
+#endif
 
 
 PyDoc_STRVAR(_makeClosure_doc,
 		METH_VARARGS, "private function" },
 	{ "_sockaddrToPython", (PyCFunction)PyObjC_SockAddrToPython,
 		METH_VARARGS, "private function" },
+#if 0
 	{ "parseBridgeSupport", (PyCFunction)parseBridgeSupport,
 		METH_VARARGS|METH_KEYWORDS, parseBridgeSupport_doc },
 	{ "_setSetupCFClasses", (PyCFunction)PyObjC_SetSetupCFClasses, 
 		METH_O, "private function" },
 	{ "_setStructConvenience", (PyCFunction)PyObjC_SetStructConvenience, 
 		METH_O, "private function" },
+#endif
 	{ "_ivar_dict", (PyCFunction)ivar_dict, METH_NOARGS, "private functions" },
 
 	{ "_objc_sync_enter", (PyCFunction)PyObjC_objc_sync_enter,
 	if (PyObjCCFType_Setup() == -1) {
 		PyObjC_INITERROR();
 	}
+
+#if 0
 	if (PyObjCXML_Init() == -1) {
 		PyObjC_INITERROR();
 	}
+#endif
 
 	m = PyObjC_MODULE_CREATE(_objc);
 	if (m == 0) {

pyobjc-core/Modules/objc/objc_util.m

 
 int PyObjC_is_ascii_string(PyObject* unicode_string, const char* ascii_string)
 {
+#if PY_MAJOR_VERSION == 2
+	if (PyString_Check(unicode_string)) {
+		return strcmp(PyString_AsString(unicode_string), ascii_string) == 0;
+	} else {
+#endif
+
 	size_t uni_sz = PyUnicode_GetSize(unicode_string);
 	size_t i;
 	Py_UNICODE* code_points = PyUnicode_AsUnicode(unicode_string);
 		return 0;
 	}
 	return 1;
+#if PY_MAJOR_VERSION == 2
+	}
+#endif
 }
 
 int PyObjC_is_ascii_prefix(PyObject* unicode_string, const char* ascii_string, size_t n)

pyobjc-core/Modules/objc/parsexml.m

+#if 0
 /*
  * A fast parser for BridgeSupport files.
  *
 		return 0;
 	}
 }
+#endif

pyobjc-core/Modules/objc/test/cfsocket.m

 #include <CoreFoundation/CoreFoundation.h>
 
 @interface OC_TestCFSocket : NSObject
--(id)create;
+-(id)newSocket;
 @end
 
 @implementation OC_TestCFSocket

pyobjc-core/Modules/objc/test/copying.m

 
 @interface OC_CopyHelper : NSObject
 { }
-+(NSObject*)doCopySetup:(Class)aClass;
++(NSObject<NSCopying>*)doCopySetup:(Class)aClass;
 +(NSObject*)newObjectOfClass:(Class)aClass;
 @end
 
 @implementation OC_CopyHelper
-+(NSObject*)doCopySetup:(Class)aClass
++(NSObject<NSCopying>*)doCopySetup:(Class)aClass
 {
 	NSObject<NSCopying>* tmp;
 	NSObject* retval;

pyobjc-core/Modules/objc/test/corefoundation.m

 	return @encode(CFUUIDRef);
 }
 
-+(CFTypeID)typeidForCFUUIDRef;
++(CFTypeID)typeidForCFUUIDRef
 {
 	return CFUUIDGetTypeID();
 }
 
 
 
-+(char*)signatureForCFDateRef;
++(char*)signatureForCFDateRef
 {
 	return @encode(CFDateRef);
 }
 
-+(CFTypeID)typeidForCFDateRef;
++(CFTypeID)typeidForCFDateRef
 {
 	return CFDateGetTypeID();
 }
 
-+(CFDateRef)today;
++(CFDateRef)today
 {
 	CFDateRef result;
 

pyobjc-core/Modules/objc/test/ctests.m

  *
  * The PyObjC unittest objc.test.test_ctests executes the tests in this file.
  */
+#include "Python.h"
 #include "pyobjc-api.h"
 #include "pyobjc-compat.h"
 
 	input = PyTuple_New(2);
 	FAIL_IF(input == NULL);
 
-	PyTuple_SET_ITEM(input, 0, PyInt_FromLong(1));
-	PyTuple_SET_ITEM(input, 1, PyFloat_FromDouble(2));
+	PyTuple_SetItem(input, 0, PyInt_FromLong(1));
+	PyTuple_SetItem(input, 1, PyFloat_FromDouble(2));
 	
 	r = PyObjC_PythonToObjC(@encode(struct Struct1), input, &output);
 	FAIL_IF(r < 0);
 	FAIL_IF(input == NULL);
 
 	v = PyTuple_New(5);
-	PyTuple_SET_ITEM(v, 0, PyInt_FromLong(10));
-	PyTuple_SET_ITEM(v, 1, PyInt_FromLong(11));
-	PyTuple_SET_ITEM(v, 2, PyInt_FromLong(12));
-	PyTuple_SET_ITEM(v, 3, PyInt_FromLong(13));
-	PyTuple_SET_ITEM(v, 4, PyInt_FromLong(14));
+	PyTuple_SetItem(v, 0, PyInt_FromLong(10));
+	PyTuple_SetItem(v, 1, PyInt_FromLong(11));
+	PyTuple_SetItem(v, 2, PyInt_FromLong(12));
+	PyTuple_SetItem(v, 3, PyInt_FromLong(13));
+	PyTuple_SetItem(v, 4, PyInt_FromLong(14));
 
-	PyTuple_SET_ITEM(input, 0, PyInt_FromLong(1));
-	PyTuple_SET_ITEM(input, 1, PyFloat_FromDouble(2));
-	PyTuple_SET_ITEM(input, 2, v);
+	PyTuple_SetItem(input, 0, PyInt_FromLong(1));
+	PyTuple_SetItem(input, 1, PyFloat_FromDouble(2));
+	PyTuple_SetItem(input, 2, v);
 	
 	r = PyObjC_PythonToObjC(@encode(struct Struct2), input, &output);
 	FAIL_IF(r < 0);
 	input = PyTuple_New(2);
 	FAIL_IF(input == NULL);
 
-	PyTuple_SET_ITEM(input, 0,  PyBytes_FromStringAndSize("\001", 1));
-	PyTuple_SET_ITEM(input, 1, PyInt_FromLong(2));
+	PyTuple_SetItem(input, 0,  PyBytes_FromStringAndSize("\001", 1));
+	PyTuple_SetItem(input, 1, PyInt_FromLong(2));
 	
 	r = PyObjC_PythonToObjC(@encode(struct Struct3), input, &output);
 	FAIL_IF(r < 0);
 	input = PyTuple_New(2);
 	FAIL_IF(input == NULL);
 
-	PyTuple_SET_ITEM(input, 0,  PyBytes_FromStringAndSize("\001", 1));
-	PyTuple_SET_ITEM(input, 1, PyInt_FromLong(500000));
+	PyTuple_SetItem(input, 0,  PyBytes_FromStringAndSize("\001", 1));
+	PyTuple_SetItem(input, 1, PyInt_FromLong(500000));
 	
 	r = PyObjC_PythonToObjC(@encode(struct Struct4), input, &output);
 	FAIL_IF(r < 0);
 	FAIL_IF(input == NULL);
 
 	v = PyTuple_New(2);
-	PyTuple_SET_ITEM(v, 0, PyInt_FromLong(500000));
-	PyTuple_SET_ITEM(v, 1,  PyBytes_FromStringAndSize("\001", 1));
-	PyTuple_SET_ITEM(input, 0, v);
+	PyTuple_SetItem(v, 0, PyInt_FromLong(500000));
+	PyTuple_SetItem(v, 1,  PyBytes_FromStringAndSize("\001", 1));
+	PyTuple_SetItem(input, 0, v);
 
 	v = PyTuple_New(2);
-	PyTuple_SET_ITEM(v, 0, PyInt_FromLong(1000000));
-	PyTuple_SET_ITEM(v, 1,  PyBytes_FromStringAndSize("\002", 1));
-	PyTuple_SET_ITEM(input, 1, v);
+	PyTuple_SetItem(v, 0, PyInt_FromLong(1000000));
+	PyTuple_SetItem(v, 1,  PyBytes_FromStringAndSize("\002", 1));
+	PyTuple_SetItem(input, 1, v);
 	
 	r = PyObjC_PythonToObjC(@encode(Struct5Array), input, &output);
 	FAIL_IF(r < 0);
 	ASSERT_ISINSTANCE(output, Tuple);	
 	ASSERT_EQUALS(PyTuple_GET_SIZE(output), 2, "%d");
 #if PY_VERSION_HEX < 0x03000000
-	ASSERT_ISINSTANCE(PyTuple_GET_ITEM(output, 0), Int);
+	ASSERT_ISINSTANCE(PyTuple_GetItem(output, 0), Int);
 #else
-	ASSERT_ISINSTANCE(PyTuple_GET_ITEM(output, 0), Long);
+	ASSERT_ISINSTANCE(PyTuple_GetItem(output, 0), Long);
 #endif
-	ASSERT_ISINSTANCE(PyTuple_GET_ITEM(output, 1), Float);
-	ASSERT_EQUALS(PyInt_AsLong(PyTuple_GET_ITEM(output, 0)), 1, "%d");
-	ASSERT_EQUALS(PyFloat_AsDouble(PyTuple_GET_ITEM(output, 1)), 2.0, "%g");
+	ASSERT_ISINSTANCE(PyTuple_GetItem(output, 1), Float);
+	ASSERT_EQUALS(PyInt_AsLong(PyTuple_GetItem(output, 0)), 1, "%d");
+	ASSERT_EQUALS(PyFloat_AsDouble(PyTuple_GetItem(output, 1)), 2.0, "%g");