[PyObjC-svn] r2606 - in trunk/pyobjc: build-support pyobjc-core/Lib/PyObjCTools pyobjc-core/PyObjCTest pyobjc-framework-PreferencePanes/Examples/EnvironmentPrefs pyobjc-metadata/Doc pyobjc-metadata/Lib/PyObjCMetaData

[email protected] Mon, 25 Apr 2011 05:07:59 -0500
Newsgroups gmane.comp.python.pyobjc.cvs
Message-ID <[email protected]>
Author: ronaldoussoren
Date: Mon Apr 25 05:07:59 2011
New Revision: 2606

Log:
Some minor changes that have been on my machine without getting checked in for a long while now.


Modified:
   trunk/pyobjc/build-support/   (props changed)
   trunk/pyobjc/build-support/ReadMe.txt
   trunk/pyobjc/build-support/build_frameworks.py
   trunk/pyobjc/build-support/run_tests.py
   trunk/pyobjc/pyobjc-core/Lib/PyObjCTools/KeyValueCoding.py
   trunk/pyobjc/pyobjc-core/Lib/PyObjCTools/Signals.py
   trunk/pyobjc/pyobjc-core/Lib/PyObjCTools/TestSupport.py
   trunk/pyobjc/pyobjc-core/PyObjCTest/fnd.py
   trunk/pyobjc/pyobjc-core/PyObjCTest/keyvaluehelper.py
   trunk/pyobjc/pyobjc-core/PyObjCTest/loader.py
   trunk/pyobjc/pyobjc-core/PyObjCTest/test2_dict_interface.py
   trunk/pyobjc/pyobjc-core/PyObjCTest/test3_dict_interface.py
   trunk/pyobjc/pyobjc-core/PyObjCTest/test_allocatebuffer.py
   trunk/pyobjc/pyobjc-core/PyObjCTest/test_archive_python.py
   trunk/pyobjc/pyobjc-core/PyObjCTest/test_bundleFunctions.py
   trunk/pyobjc/pyobjc-core/PyObjCTest/test_bundleVariables.py
   trunk/pyobjc/pyobjc-core/PyObjCTest/test_conversion.py
   trunk/pyobjc/pyobjc-core/PyObjCTest/test_copying.py
   trunk/pyobjc/pyobjc-core/PyObjCTest/test_corefoundation.py
   trunk/pyobjc/pyobjc-core/PyObjCTest/test_ctests.py
   trunk/pyobjc/pyobjc-core/PyObjCTest/test_exceptions.py
   trunk/pyobjc/pyobjc-core/PyObjCTest/test_methodedits.py
   trunk/pyobjc/pyobjc-framework-PreferencePanes/Examples/EnvironmentPrefs/ShellEnv.py
   trunk/pyobjc/pyobjc-framework-PreferencePanes/Examples/EnvironmentPrefs/setup.py
   trunk/pyobjc/pyobjc-metadata/Doc/xmlformat.txt
   trunk/pyobjc/pyobjc-metadata/Lib/PyObjCMetaData/genwrapper.py
   trunk/pyobjc/pyobjc-metadata/Lib/PyObjCMetaData/lint.py
   trunk/pyobjc/pyobjc-metadata/Lib/PyObjCMetaData/scanframework.py
   trunk/pyobjc/pyobjc-metadata/Lib/PyObjCMetaData/tokenize_header.py

Modified: trunk/pyobjc/build-support/ReadMe.txt
==============================================================================
--- trunk/pyobjc/build-support/ReadMe.txt	(original)
+++ trunk/pyobjc/build-support/ReadMe.txt	Mon Apr 25 05:07:59 2011
@@ -1,18 +1,18 @@
-This directory contains a number of scripts
-that help in testing PyObjC on a number 
-of platforms.
+TestSupport scripts
+===================
 
-All scripts are python3 scripts.
+This directory contains a number of scripts and related files that make it
+easier to thorougly test PyObjC with a number of different Python release and
+build flavours.
 
-WARNING: The scripts are a work-in-progress and don't 
-work right now.
+All scripts are python3 scripts.
 
 * build_frameworks.py:
   This script creates a couple of framework
   builds of Python for various Python
   releases:
 
-  - 32-bit (i386, ppc) and intel (i386, x86)
+  - 32-bit (i386, ppc), 3-way (i386, ppc, x86_64) and intel (i386, x86)
   - 2.6, 2.7, 3.1 and 3.2
 
   All builds are with '--with-pydebug' and
@@ -20,25 +20,84 @@
   name to avoid messing with an already existing
   install.
 
-  TODO: also install distribute and virtualenv
-
 * run_tests.py
 
   Uses the frameworks installed by build_frameworks.py
   to run all PyObjC tests with all supported Python
   variants.
 
-  TODO:
-  - create virtual env and install PyObjC dependencies
-  - install pyobjc-core, pyobjc-framework-Cocoa and
-    pyobjc-framework-Quartz
-  - run tests for pyobjc-core and all framework wrappers
-  - collect the results and create an HTML page with
-    the summary and details.
-  - send e-mail with the result to an e-mail address
-
-* TODO: run_distributed_tests.py
-
-  This script will do something simular to run_tests,
-  but builds on a 10.6 machine and runs the tests on
-  a number of different machines (10.4, 10.5)
+
+Both scripts have arguments to select what gets build or
+tested:
+
+* ``--help``
+
+  Show the support command-line options
+
+* ``--archs=3-way,32-bit``
+
+  Select the architecture variants
+
+* ``--versions=2.6,2.7``
+
+  Select the python versions
+
+* ``--only-setup``
+
+  For run_tests: don't actually run the tests, just do
+  the initial setup of pyobjc-core, pyobjc-framework-Cocoa
+  and pyobjc-framework-Quartz
+
+* ``--skip-quartz``
+
+  For run_tests: do not run the tests for pyobjc-framework-Quartz
+  (this makes it possible to run most of the testsuite in the
+  background, the Quartz tests mess up the display while running)
+
+* ``--index=index.html``
+
+  For run_tests: select the filename for the report file that 
+  gets generated, defaults to "index.html"
+
+Managment tools
+---------------
+
+* ``set-version.py``
+
+  This script has a single argument: a version number. The script updates
+  the pyobjc version number to that version throught the project.
+
+Support files
+-------------
+
+* ``checkout``
+
+  This directory gets created by the scripts and contains checkouts of
+  python releases.
+
+* ``distribute-0.6.12-patched``
+
+  A slightly patched version of distribute-0.6.12 that enables running with
+  a older alpha of python 3.2
+
+* ``templates``
+
+  Contains Jinja2 template files for the run_tests script.
+
+* ``testresults``
+
+  This directory gets created by the run_tests script and contains the 
+  raw results as well as the HTML summary report.
+
+* ``topsort.py``
+
+  An implementation of a topological sort function.
+
+* ``virtualenv-src``, ``virtualenv3-src``
+
+  Checkouts of virtualenv for python2 and python3, slightly patched to
+  work better.
+
+* ``virtualenvs``
+
+  Contains the virtualenvs used during testing.

Modified: trunk/pyobjc/build-support/build_frameworks.py
==============================================================================
--- trunk/pyobjc/build-support/build_frameworks.py	(original)
+++ trunk/pyobjc/build-support/build_frameworks.py	Mon Apr 25 05:07:59 2011
@@ -18,18 +18,20 @@
 
 import subprocess, getopt, logging, os, shutil
 from urllib.request import urlopen
+import pprint
 
 
 gUsage="""\
-build_frameworks.py [-v versions] [--versions=versions] [-a archs] [--arch archs]
+build_frameworks.py [-v versions] [--versions=versions] [-a archs] [--arch=archs] [-f flavours] [--flavours=flavours]
 
 - versions: comma seperated list of python versiosn, defaults to "2.6,2.7,3.1,3.2"
-- archs: comma seperated list of build variations, defaults to "32-bit,3-way"
+- archs: comma seperated list of build architectures, defaults to "32-bit,3-way"
+- flavours: comma separated list of build variants, defaults to "release,debug"
 """
 
 gBaseDir = os.path.dirname(os.path.abspath(__file__))
 
-gArchs = ("32-bit", "3-way")
+gArchs = ("32-bit", "3-way", "intel")
 
 
 # Name of the Python framework and any additional arguments
@@ -42,12 +44,12 @@
                 "--with-pydebug",
             ],
         ),
-#        dict(
-#            name="release",
-#            template="ReleasePython-{archs}",
-#            flags=[
-#            ],
-#        ),
+        dict(
+            name="release",
+            template="ReleasePython-{archs}",
+            flags=[
+            ],
+        ),
 ]
 
 
@@ -75,7 +77,14 @@
     '32-bit': '10.3',
     #'32-bit': '10.5',
     '3-way':  '10.5',
-    'intel':  '10.5',
+    'intel':  '10.6',
+}
+
+gArchMap = {
+    '2.6': {'32-bit'},
+    '2.7': {'32-bit', 'intel', '3-way'},
+    '3.1': {'32-bit'},
+    '3.2': {'32-bit', 'intel', '3-way'},
 }
 
 class ShellError (Exception):
@@ -99,16 +108,20 @@
         lg.debug("Update checkout")
         p = subprocess.Popen([
             'svn', 'up'],
-            cwd=checkoutdir)
+            cwd=checkoutdir, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
+            env=os.environ)
     else:
         lg.debug("Initial checkout checkout")
         p = subprocess.Popen([
-            'svn', 'co', gURLMap[version], checkoutdir])
+            'svn', 'co', gURLMap[version], checkoutdir], stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
+            env=os.environ)
 
+    data = p.communicate()[0]
     xit = p.wait()
     if xit == 0:
         lg.info("Checkout for %s is now up-to-date", version)
     else:
+        print(data.decode('utf-8').rstrip())
         lg.warn("Checkout for %s failed", version)
         raise ShellError(xit)
 
@@ -140,20 +153,25 @@
             "--with-universal-archs={0}".format(archs),
             ] + flavour["flags"] + [
             "MACOSX_DEPLOYMENT_TARGET={0}".format(gDeploymentTargetMap[archs]),
-            ], cwd=builddir)
+            ], cwd=builddir, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=os.environ)
+
+    data = p.communicate()[0]
 
     xit = p.wait()
     if xit != 0:
+        print(data.decode('utf-8').rstrip())
         lg.debug("Configure failed for %s", version)
         raise ShellError(xit)
     
     lg.debug("Running 'make'")
     p = subprocess.Popen([
             "make",
-        ], cwd=builddir)
+        ], cwd=builddir, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=os.environ)
+    data = p.communicate()[0]
 
     xit = p.wait()
     if xit != 0:
+        print(data.decode('utf-8').rstrip())
         lg.debug("Make failed for %s", version)
         raise ShellError(xit)
 
@@ -161,10 +179,12 @@
     p = subprocess.Popen([
             "make",
             "install",
-        ], cwd=builddir)
+        ], cwd=builddir, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=os.environ)
+    data = p.communicate()[0]
 
     xit = p.wait()
     if xit != 0:
+        print(data.decode('utf-8').rstrip())
         lg.debug("Install failed for %r", version)
         raise ShellError(xit)
 
@@ -173,6 +193,7 @@
     lg.debug("Installing distribute")
 
     distribute_dir = os.path.join(gBaseDir, "distribute-0.6.12-patched")
+    distribute_dir = os.path.join(gBaseDir, "distribute-0.6.14")
     builddir = os.path.join(distribute_dir, "build")
     if os.path.exists(builddir):
         lg.debug("Remove existing 'build' subdir")
@@ -186,12 +207,19 @@
         python += '3'
 
 
+    if os.path.exists(os.path.join(distribute_dir, 'build')):
+        shutil.rmtree(os.path.join(distribute_dir, 'build'))
+
     lg.debug("Run setup script with '%s'", python)
     p = subprocess.Popen([
         python, "setup.py", "install"],
-        cwd=distribute_dir)
+        cwd=distribute_dir, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=os.environ)
+    
+    data = p.communicate()[0]
+
     xit = p.wait()
     if xit != 0:
+        print(data.decode('utf-8').rstrip())
         lg.warning("Installing 'distribute' failed")
         raise ShellError(xit)
 
@@ -217,11 +245,17 @@
     else:
         srcdir = os.path.join(gBaseDir, 'virtualenv3-src')
 
+    if os.path.exists(os.path.join(srcdir, 'build')):
+        shutil.rmtree(os.path.join(srcdir, 'build'))
+
     p = subprocess.Popen([ python, "setup.py", "install" ],
-            cwd=srcdir)
+            cwd=srcdir, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=os.environ)
+
+    data = p.communicate()[0]
 
     xit = p.wait()
     if xit != 0:
+        print(data.decode('utf-8').rstrip())
         lg.warning("Installing 'virtualenv' failed")
         raise ShellError(xit)
 
@@ -230,7 +264,7 @@
     logging.basicConfig(level=logging.DEBUG)
 
     try:
-        opts, args = getopt.getopt(sys.argv[1:], 'v:a:h?', ['help', 'versions=', 'archs='])
+        opts, args = getopt.getopt(sys.argv[1:], 'v:a:h?f:', ['help', 'versions=', 'archs=', 'flavours=', 'flavors='])
     except getopt.error as msg:
         print(msg, file=sys.stderr)
         print(gUsage, file=sys.stderr)
@@ -238,6 +272,7 @@
 
     versions = sorted(gURLMap.keys())
     archs = gArchs
+    flavours = gFlavours
 
     if args:
         print("Additional arguments", file=sys.stderr)
@@ -269,6 +304,14 @@
                             file=sys.stderr)
                     sys.exit(1)
 
+        elif k in ('-f', '--flavours', '--flavors'):
+            flavours = [v.strip() for v in v.split(',')]
+            for v in flavours:
+                if v not in gFlavours:
+                    print("Unsupported python flavour: {0}".format(v), 
+                            file=sys.stderr)
+                    sys.exit(1)
+
         else:
             print("ERROR: unhandled script option: {0}".format(k), 
                     file=sys.stderr)
@@ -281,8 +324,12 @@
         for version in sorted(versions):
             create_checkout(version)
 
-            for flavour in gFlavours:
+            for flavour in flavours:
                 for arch in sorted(archs):
+                    if arch not in gArchMap[version]:
+                        lg.info('Skip %s framework for python %s (%s)', flavour["name"], version, arch)
+                        continue
+
                     try:
                         lg.info('Building %s framework for python %s (%s)', flavour["name"], version, arch)
                         build_framework(flavour, version, arch)

Modified: trunk/pyobjc/build-support/run_tests.py
==============================================================================
--- trunk/pyobjc/build-support/run_tests.py	(original)
+++ trunk/pyobjc/build-support/run_tests.py	Mon Apr 25 05:07:59 2011
@@ -40,9 +40,9 @@
 
 
 gUsage = """\
-run_tests.py [-a archs] [--archs=archs] [-v versions] [--versions=versions] [-s|--setup-only]
+run_tests.py [-a archs] [--archs=archs] [-v versions] [--versions=versions] [-s|--setup-only] [-i index.html|--index=index.html] [--skip-quartz]
 
-archs:    32-bit,3-way (values separated by commas)
+archs:    32-bit,3-way,intel (values separated by commas)
 versions: 2.6,2.7,3.1,3.2    (values seperated by commas)
 """
 
@@ -52,8 +52,6 @@
 
 gFrameworkNameTemplate="DbgPython-{archs}"
 
-gVersions=["3.2", "2.7", "3.1", "2.6"]
-gArchs=["32-bit", "3-way"]
 
 gArchMap={
     '3-way': ['ppc', 'i386', 'x86_64'],
@@ -61,6 +59,14 @@
     'intel': ['i386', 'x86_64'],
 }
 
+gVersionArchs = {
+    '2.6': {'32-bit'},
+    '2.7': {'32-bit', 'intel', '3-way'},
+    '3.1': {'32-bit'},
+    '3.2': {'32-bit', 'intel', '3-way'},
+}
+gVersions=list(sorted(gVersionArchs))
+gArchs=list(sorted(gArchMap))
 
 def supports_arch_command(version):
 
@@ -84,7 +90,7 @@
     logging.basicConfig(level=logging.DEBUG)
 
     try:
-        opts, args = getopt.getopt(sys.argv[1:], 'a:v:h?s', ["help", "archs=", "versions=", "setup-only"])
+        opts, args = getopt.getopt(sys.argv[1:], 'a:v:h?si', ["help", "archs=", "versions=", "setup-only", "index=", "skip-quartz"])
     except getopt.error as msg:
         print(msg, file=sys.stderr)
         print(gUsage, file=sys.stderr)
@@ -95,9 +101,11 @@
         print(gUsage, file=sys.stderr)
         sys.exit(1)
 
-    versions=gVersions
-    archs=gArchs
-    setup_only=False
+    versions = gVersions
+    archs = gArchs
+    setup_only = False
+    index_html = 'index.html'
+    skip_quartz = False
 
     for k, v in opts:
         if k in ('-?', '-h', '--help'):
@@ -124,19 +132,30 @@
         elif k in ['-s', '--setup-only']:
             setup_only = True
 
+        elif k in ['-i', '--index']:
+            index_html = v
+
+        elif k in ['--skip-quartz']:
+            skip_quartz = True
+
         else:
             print("ERROR: Unhandled script option: {0}".format(k),
                     file=sys.stderr)
             sys.exit(2)
 
+    if 'MACOSX_DEPLOYMENT_TARGET' in os.environ:
+        del os.environ['MACOSX_DEPLOYMENT_TARGET']
+
     for ver in versions:
         for arch in archs:
-            run_tests(ver, arch, setup_only)
+            if arch not in gVersionArchs[ver]:
+                continue
+            run_tests(ver, arch, setup_only, skip_quartz)
 
     if setup_only:
         return
 
-    gen_summary(versions, archs)
+    gen_summary(index_html, versions, archs)
 
 def detect_frameworks():
     """
@@ -177,12 +196,16 @@
 
 
 
-def run_tests(version, archs, setup_only):
+def run_tests(version, archs, setup_only, skip_quartz):
 
     lg = logging.getLogger("run_tests")
 
+    lg.info("Running tests python %s with archs %s setup_only=%s skip_quartz=%s",
+            version, archs, setup_only, skip_quartz)
+
     p = subprocess.Popen(["xcode-select", "-print-path" ],
-        stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+        stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
+        env=os.environ)
 
     stdout, _ = p.communicate()
     path = stdout.strip()
@@ -231,12 +254,12 @@
         p = subprocess.Popen([
             base_python,
             "-mvirtualenv",
-            subdir])
+            subdir], env=os.environ)
     else:
         p = subprocess.Popen([
             base_python,
             "-mvirtualenv3",
-            subdir])
+            subdir], env=os.environ)
 
     xit = p.wait()
     if xit != 0:
@@ -268,7 +291,8 @@
         lg.info("Install %s into %s", pkg, os.path.basename(subdir))
         p = subprocess.Popen([
             python, "setup.py", "install"],
-            cwd=pkgroot, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+            cwd=pkgroot, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
+            env=os.environ)
 
         stdout, _ = p.communicate()
 
@@ -306,7 +330,8 @@
         lg.debug("Build %s for %s", pkg, os.path.basename(subdir))
         p = subprocess.Popen([
             python, "setup.py", "install"],
-            cwd=pkgroot, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+            cwd=pkgroot, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, 
+            env=os.environ)
 
         stdout, _ = p.communicate()
         with open(os.path.join(resultdir, pkg, "build-stdout.txt"), "wb") as fd:
@@ -319,6 +344,20 @@
             #raise RuntimeError(pkg)
             continue
 
+        lg.debug("Install %s into %s", pkg, os.path.basename(subdir))
+        p = subprocess.Popen([
+            python, "setup.py", "install"],
+            cwd=pkgroot, env=os.environ)
+
+        xit = p.wait()
+        if xit != 0:
+            lg.warning("Install %s failed", pkg)
+            raise RuntimeError(pkg)
+
+        if pkg == 'pyobjc-framework-Quartz':
+            if skip_quartz:
+                continue
+
         # TODO: 
         # - For python2.7/3.2: use `arch` to run tests with all architectures
         # - For python2.6/3.1: run tests using 'python-32' and 'python-64' 
@@ -372,15 +411,6 @@
                 #raise RuntimeError(pkg)
 
         
-        lg.debug("Install %s into %s", pkg, os.path.basename(subdir))
-        p = subprocess.Popen([
-            python, "setup.py", "install"],
-            cwd=pkgroot)
-
-        xit = p.wait()
-        if xit != 0:
-            lg.warning("Install %s failed", pkg)
-            raise RuntimeError(pkg)
 
        
 
@@ -522,7 +552,7 @@
 
     return "{ProductName} {ProductVersion} ({BuildVersion})".format(**r)
 
-def gen_summary(report_versions, report_archs):
+def gen_summary(index_html, report_versions, report_archs):
     with open(gIndexTemplate) as fp:
         tmpl = Template(fp.read())
 
@@ -536,12 +566,15 @@
     versions = {}
 
     for subdir in os.listdir(gTestResults):
-        if subdir == 'index.html': continue
+        if '--' not in subdir: continue
         version, style = subdir.split('--')
 
         if version not in report_versions: continue
         if style not in report_archs: continue
 
+        if style not in gVersionArchs[version]:
+            continue
+
         versions[(version, style)] = modules = []
 
         for mod in os.listdir(os.path.join(gTestResults, subdir)):
@@ -587,7 +620,7 @@
             if info['class'] is None:
                 info['class'] = 'ok'
 
-    with open(os.path.join(gTestResults, 'index.html'), 'w') as fp:
+    with open(os.path.join(gTestResults, index_html), 'w') as fp:
         fp.write(tmpl.render(
             svn=svn,
             osx=osx,

Modified: trunk/pyobjc/pyobjc-core/Lib/PyObjCTools/KeyValueCoding.py
==============================================================================
--- trunk/pyobjc/pyobjc-core/Lib/PyObjCTools/KeyValueCoding.py	(original)
+++ trunk/pyobjc/pyobjc-core/Lib/PyObjCTools/KeyValueCoding.py	Mon Apr 25 05:07:59 2011
@@ -25,16 +25,21 @@
 information on Key-Value coding. The protocol is basicly used to enable
 weaker coupling between the view and model layers.
 """
+from __future__ import unicode_literals
+import sys
 
 __all__ = ("getKey", "setKey", "getKeyPath", "setKeyPath")
+if sys.version_info[0] == 2:
+    __all__ = tuple(str(x) for x in __all__)
+
 
 import objc
 import types
-from itertools import imap
-try:
-    set
-except NameError:
-    from sets import Set as set
+
+if sys.version_info[0] == 2:
+    from itertools import imap as map
+else:
+    basestr = str
 
 if objc.lookUpClass('NSObject').alloc().init().respondsToSelector_('setValue:forKey:'):
     SETVALUEFORKEY = 'setValue_forKey_'
@@ -43,6 +48,10 @@
     SETVALUEFORKEY = 'takeValue_forKey_'
     SETVALUEFORKEYPATH = 'takeValue_forKeyPath_'
 
+if sys.version_info[0] == 2:
+    SETVALUEFORKEY = str(SETVALUEFORKEY)
+    SETVALUEFORKEYPATH = str(SETVALUEFORKEYPATH)
+
 def keyCaps(s):
     return s[:1].capitalize() + s[1:]
 
@@ -70,18 +79,18 @@
 
 class ArrayOperators(object):
     def avg(self, obj, segments):
-        path = u'.'.join(segments)
+        path = '.'.join(segments)
         lst = getKeyPath(obj, path)
         count = len(lst)
         if count == 0:
             return 0.0
-        return msum(imap(float, lst)) / count
+        return msum(map(float, lst)) / count
     
     def count(self, obj, segments):
         return len(obj)
     
     def distinctUnionOfArrays(self, obj, segments):
-        path = u'.'.join(segments)
+        path = '.'.join(segments)
         rval = []
         s = set()
         lists = getKeyPath(obj, path)
@@ -94,7 +103,7 @@
         return rval
 
     def distinctUnionOfObjects(self, obj, segments):
-        path = u'.'.join(segments)
+        path = '.'.join(segments)
         rval = []
         s = set()
         lst = getKeyPath(obj, path)
@@ -106,20 +115,20 @@
         return rval
         
     def max(self, obj, segments):
-        path = u'.'.join(segments)
+        path = '.'.join(segments)
         return max(getKeyPath(obj, path))
     
     def min(self, obj, segments):
-        path = u'.'.join(segments)
+        path = '.'.join(segments)
         return min(getKeyPath(obj, path))
     
     def sum(self, obj, segments):
-        path = u'.'.join(segments)
+        path = '.'.join(segments)
         lst = getKeyPath(obj, path)
-        return msum(imap(float, lst))
+        return msum(map(float, lst))
 
     def unionOfArrays(self, obj, segments):
-        path = u'.'.join(segments)
+        path = '.'.join(segments)
         rval = []
         lists = getKeyPath(obj, path)
         for lst in lists:
@@ -127,7 +136,7 @@
         return rval
 
     def unionOfObjects(self, obj, segments):
-        path = u'.'.join(segments)
+        path = '.'.join(segments)
         return getKeyPath(obj, path)
 
 arrayOperators = ArrayOperators()
@@ -152,10 +161,10 @@
     if isinstance(obj, (objc.objc_object, objc.objc_class)):
         try:
             return obj.valueForKey_(key)
-        except ValueError, msg:
+        except ValueError as msg:
             # This is not entirely correct, should check if this
             # is the right kind of ValueError before translating
-            raise KeyError, str(msg)
+            raise KeyError(str(msg))
     
     # check for dict-like objects
     getitem = getattr(obj, '__getitem__', None)
@@ -194,7 +203,7 @@
         except AttributeError:
             continue
 
-        if isinstance(m, types.MethodType) and m.im_self is obj:
+        if isinstance(m, types.MethodType) and m.__self__ is obj:
             return m()
 
         elif isinstance(m, types.BuiltinMethodType):
@@ -210,7 +219,7 @@
     try:
         return getattr(obj, "_" + key)
     except AttributeError:
-        raise KeyError, "Key %s does not exist" % (key,)
+        raise KeyError("Key %s does not exist" % (key,))
 
 
 def setKey(obj, key, value):
@@ -233,8 +242,8 @@
         try:
             getattr(obj, SETVALUEFORKEY)(value, key)
             return
-        except ValueError, msg:
-            raise KeyError, str(msg)
+        except ValueError as msg:
+            raise KeyError(str(msg))
 
     aBase = 'set' + keyCaps(key)
     for accessor in (aBase + '_', aBase, 'set_' + key):
@@ -258,7 +267,7 @@
     try:
         setattr(obj, key, value)
     except AttributeError:
-        raise KeyError, "Key %s does not exist" % (key,)
+        raise KeyError("Key %s does not exist" % (key,))
 
 def getKeyPath(obj, keypath):
     """
@@ -275,11 +284,11 @@
     cur = obj
     elemiter = iter(elements)
     for e in elemiter:
-        if e[:1] == u'@':
+        if e[:1] == '@':
             try:
                 oper = getattr(arrayOperators, e[1:])
             except AttributeError:
-                raise KeyError, "Array operator %s not implemented" % (e,)
+                raise KeyError("Array operator %s not implemented" % (e,))
             return oper(cur, elemiter)
         cur = getKey(cur, e)
     return cur
@@ -320,10 +329,10 @@
 
     def __getitem__(self, item):
         if not isinstance(item, basestring):
-            raise TypeError, 'Keys must be strings'
+            raise TypeError('Keys must be strings')
         return getKeyPath(self.__pyobjc_object__, item)
 
     def __setitem__(self, item, value):
         if not isinstance(item, basestring):
-            raise TypeError, 'Keys must be strings'
+            raise TypeError('Keys must be strings')
         setKeyPath(self.__pyobjc_object__, item, value)

Modified: trunk/pyobjc/pyobjc-core/Lib/PyObjCTools/Signals.py
==============================================================================
--- trunk/pyobjc/pyobjc-core/Lib/PyObjCTools/Signals.py	(original)
+++ trunk/pyobjc/pyobjc-core/Lib/PyObjCTools/Signals.py	Mon Apr 25 05:07:59 2011
@@ -19,7 +19,7 @@
 
           DO NOT USE THIS MODULE IN PRODUCTION CODE
 """
-
+from __future__ import print_function
 import signal
 import traceback
 import os
@@ -34,9 +34,9 @@
     then re-raise the signal
     """
     resetFatalSignals()
-    print "*** Handling fatal signal '%d'." % signum
+    print("*** Handling fatal signal '%d'." % signum)
     traceback.print_stack(frame)
-    print "*** Restored handlers and resignaling."
+    print("*** Restored handlers and resignaling.")
     os.kill(os.getpid(), signum)
 
 def installHandler(sig):

Modified: trunk/pyobjc/pyobjc-core/Lib/PyObjCTools/TestSupport.py
==============================================================================
--- trunk/pyobjc/pyobjc-core/Lib/PyObjCTools/TestSupport.py	(original)
+++ trunk/pyobjc/pyobjc-core/Lib/PyObjCTools/TestSupport.py	Mon Apr 25 05:07:59 2011
@@ -4,6 +4,7 @@
 This module is unsupported and is primairily used in the PyObjC
 testsuite.
 """
+from __future__ import print_function
 import plistlib as _pl
 import unittest as _unittest
 import objc
@@ -654,12 +655,12 @@
             if _useleaks:
                 leaksAfter = _leaks()
                 if len(leaksBefore) != len(leaksAfter):
-                    print "\ntest %s is leaking [%d lines]"%(self, len(leaksAfter) - len(leaksBefore))
+                    print("\ntest %s is leaking [%d lines]"%(self, len(leaksAfter) - len(leaksBefore)))
                     if _leaksVerbose:
                         # XXX: add a smartish filter the surpresses the leaks
                         # in leaksBefore.
                         for ln in leaksAfter:
-                            print ln
+                            print(ln)
 
     def _deprecate(original_func):
         def deprecated_func(*args, **kwds):

Modified: trunk/pyobjc/pyobjc-core/PyObjCTest/fnd.py
==============================================================================
--- trunk/pyobjc/pyobjc-core/PyObjCTest/fnd.py	(original)
+++ trunk/pyobjc/pyobjc-core/PyObjCTest/fnd.py	Mon Apr 25 05:07:59 2011
@@ -6,7 +6,7 @@
 __bundle__ = _objc.loadBundle(
         'Foundation',
         globals(),
-        bundle_identifier=u'com.apple.Foundation',
+        bundle_identifier='com.apple.Foundation',
 )
 
 _objc.loadBundleVariables(__bundle__, globals(), [

Modified: trunk/pyobjc/pyobjc-core/PyObjCTest/keyvaluehelper.py
==============================================================================
--- trunk/pyobjc/pyobjc-core/PyObjCTest/keyvaluehelper.py	(original)
+++ trunk/pyobjc/pyobjc-core/PyObjCTest/keyvaluehelper.py	Mon Apr 25 05:07:59 2011
@@ -1,13 +1,14 @@
 """
 Helper module for KeyValue tests
 """
+from __future__ import unicode_literals, absolute_import
 from PyObjCTest.testbndl import PyObjCTest_KVBaseClass, PyObjCTest_KVPathClass
 import objc
 
 NSObject = objc.lookUpClass('NSObject')
 
-DirectString = u'Direct String'
-IndirectString = u'Indirect String'
+DirectString = 'Direct String'
+IndirectString = 'Indirect String'
 DirectNumber = 42
 IndirectNumber = 84
 

Modified: trunk/pyobjc/pyobjc-core/PyObjCTest/loader.py
==============================================================================
--- trunk/pyobjc/pyobjc-core/PyObjCTest/loader.py	(original)
+++ trunk/pyobjc/pyobjc-core/PyObjCTest/loader.py	Mon Apr 25 05:07:59 2011
@@ -1,8 +1,10 @@
+from __future__ import absolute_import, print_function
 import sys, os, string, glob
 from os.path import basename, dirname, splitext, join, expanduser
 from fnmatch import fnmatch
 import unittest
-import dejagnu
+
+from . import dejagnu
 
 from distutils.command.install_lib import install_lib
 from distutils.errors import DistutilsOptionError
@@ -28,7 +30,7 @@
     """
 
     testFiles = recursiveGlob(root, pathPattern)
-    testModules = map(lambda x:x[len(root)+1:-3].replace('/', '.'), testFiles)
+    testModules = [ x[len(root)+1:-3].replace('/', '.') for x in  testFiles ]
     if package is not None:
         testModules = [(package + '.' + m) for m in testModules]
 
@@ -37,8 +39,8 @@
     for modName in testModules:
         try:
             module = __import__(modName)
-        except ImportError, msg:
-            print "SKIP %s: %s"%(modName, msg)
+        except ImportError as msg:
+            print("SKIP %s: %s"%(modName, msg))
             continue
 
         if '.' in modName:

Modified: trunk/pyobjc/pyobjc-core/PyObjCTest/test2_dict_interface.py
==============================================================================
--- trunk/pyobjc/pyobjc-core/PyObjCTest/test2_dict_interface.py	(original)
+++ trunk/pyobjc/pyobjc-core/PyObjCTest/test2_dict_interface.py	Mon Apr 25 05:07:59 2011
@@ -154,7 +154,7 @@
         d.clear()
         class FailingUserDict:
             def keys(self):
-                raise Exc
+                raise Exc()
         self.assertRaises(Exc, d.update, FailingUserDict())
 
         class FailingUserDict:
@@ -168,7 +168,7 @@
                         if self.i:
                             self.i = 0
                             return 'a'
-                        raise Exc
+                        raise Exc()
                 return BogonIter()
             def __getitem__(self, key):
                 return key
@@ -186,10 +186,10 @@
                             rtn = chr(self.i)
                             self.i += 1
                             return rtn
-                        raise StopIteration
+                        raise StopIteration()
                 return BogonIter()
             def __getitem__(self, key):
-                raise Exc
+                raise Exc()
         self.assertRaises(Exc, d.update, FailingUserDict())
 
         class badseq(object):

Modified: trunk/pyobjc/pyobjc-core/PyObjCTest/test3_dict_interface.py
==============================================================================
--- trunk/pyobjc/pyobjc-core/PyObjCTest/test3_dict_interface.py	(original)
+++ trunk/pyobjc/pyobjc-core/PyObjCTest/test3_dict_interface.py	Mon Apr 25 05:07:59 2011
@@ -211,7 +211,7 @@
     def testErrorsInViewContainmentCheck(self):
         class C:
             def __eq__(self, other):
-                raise RuntimeError
+                raise RuntimeError()
 
         d1 = self.dictClass().dictionaryWithDictionary_({1: C()})
         d2 = self.dictClass().dictionaryWithDictionary_({1: C()})

Modified: trunk/pyobjc/pyobjc-core/PyObjCTest/test_allocatebuffer.py
==============================================================================
--- trunk/pyobjc/pyobjc-core/PyObjCTest/test_allocatebuffer.py	(original)
+++ trunk/pyobjc/pyobjc-core/PyObjCTest/test_allocatebuffer.py	Mon Apr 25 05:07:59 2011
@@ -20,7 +20,7 @@
             b[5:10] = 'abcde'
             try:
                 b[5:10] = 'abcdefghijk'
-            except TypeError, r:
+            except TypeError as r:
                 if str(r).find("right operand length must match slice length") is not 0:
                     raise
 

Modified: trunk/pyobjc/pyobjc-core/PyObjCTest/test_archive_python.py
==============================================================================
--- trunk/pyobjc/pyobjc-core/PyObjCTest/test_archive_python.py	(original)
+++ trunk/pyobjc/pyobjc-core/PyObjCTest/test_archive_python.py	Mon Apr 25 05:07:59 2011
@@ -5,7 +5,13 @@
 """
 import os
 
-import sys, copy_reg
+import sys
+
+if sys.version_info[0] == 3:
+    import copyreg
+
+else:
+    import copy_reg as copyreg
 
 from PyObjCTools.TestSupport import *
 
@@ -20,6 +26,14 @@
 # object-graphs.
 #
 
+if sys.version_info[0] == 3:
+    # Dummy conversion functions, to make it easier to have
+    # the same test code in python 2 and 3.
+    def unicode(v):
+        return v
+    def long(v):
+        return v
+
 import test.pickletester
 
 MyList = test.pickletester.MyList
@@ -84,10 +98,11 @@
             self.assertIsInstance(v, a_classic_class)
             self.assertEqual(o.x, 42)
 
-            buf = self.archiverClass.archivedDataWithRootObject_(u"hello")
-            self.assertIsInstance(buf, NSData)
-            v = self.unarchiverClass.unarchiveObjectWithData_(buf)
-            self.assertIsInstance(v, unicode)
+            if sys.version_info[0] == 2:
+                buf = self.archiverClass.archivedDataWithRootObject_(unicode("hello"))
+                self.assertIsInstance(buf, NSData)
+                v = self.unarchiverClass.unarchiveObjectWithData_(buf)
+                self.assertIsInstance(v, unicode)
 
             buf = self.archiverClass.archivedDataWithRootObject_("hello")
             self.assertIsInstance(buf, NSData)
@@ -95,17 +110,17 @@
             self.assertIsInstance(v, str)
             self.assertEqual(v, "hello")
 
-            buf = self.archiverClass.archivedDataWithRootObject_(sys.maxint * 4)
+            buf = self.archiverClass.archivedDataWithRootObject_(sys.maxsize * 4)
             self.assertIsInstance(buf, NSData)
             v = self.unarchiverClass.unarchiveObjectWithData_(buf)
             self.assertIsInstance(v, long)
-            self.assertEqual(v, sys.maxint * 4)
+            self.assertEqual(v, sys.maxsize * 4)
 
-            buf = self.archiverClass.archivedDataWithRootObject_(sys.maxint ** 4)
+            buf = self.archiverClass.archivedDataWithRootObject_(sys.maxsize ** 4)
             self.assertIsInstance(buf, NSData)
             v = self.unarchiverClass.unarchiveObjectWithData_(buf)
             self.assertIsInstance(v, long)
-            self.assertEqual(v, sys.maxint ** 4)
+            self.assertEqual(v, sys.maxsize ** 4)
 
         def testSimpleLists(self):
             o = []
@@ -115,7 +130,7 @@
             self.assertIsInstance(v, list)
             self.assertEqual(v, o)
 
-            o = [u"hello", 42]
+            o = [unicode("hello"), 42]
             buf = self.archiverClass.archivedDataWithRootObject_(o)
             self.assertIsInstance(buf, NSData)
             v = self.unarchiverClass.unarchiveObjectWithData_(buf)
@@ -130,7 +145,7 @@
             self.assertIsInstance(v, tuple)
             self.assertEqual(v, o)
 
-            o = (u"hello", 42)
+            o = (unicode("hello"), 42)
             buf = self.archiverClass.archivedDataWithRootObject_(o)
             self.assertIsInstance(buf, NSData)
             v = self.unarchiverClass.unarchiveObjectWithData_(buf)
@@ -145,7 +160,7 @@
             self.assertIsInstance(v, dict)
             self.assertEqual(v, o)
 
-            o = {u"hello": u"bar", 42: 1.5 }
+            o = {unicode("hello"): unicode("bar"), 42: 1.5 }
             buf = self.archiverClass.archivedDataWithRootObject_(o)
             self.assertIsInstance(buf, NSData)
             v = self.unarchiverClass.unarchiveObjectWithData_(buf)
@@ -154,8 +169,8 @@
 
         def testNestedDicts(self):
             o = {
-                    u"hello": { 1:2 },
-                    u"world": u"foobar"
+                    unicode("hello"): { 1:2 },
+                    unicode("world"): unicode("foobar")
                 }
             buf = self.archiverClass.archivedDataWithRootObject_(o)
             self.assertIsInstance(buf, NSData)
@@ -164,15 +179,15 @@
             self.assertEqual(v, o)
 
             o = {}
-            o[u'self'] = o
+            o[unicode('self')] = o
             buf = self.archiverClass.archivedDataWithRootObject_(o)
             self.assertIsInstance(buf, NSData)
             v = self.unarchiverClass.unarchiveObjectWithData_(buf)
             self.assertIsInstance(v, dict)
-            self.assertIs(v[u'self'], v)
+            self.assertIs(v[unicode('self')], v)
 
         def testNestedSequences(self):
-            o = [ 1, 2, 3, (5, (u'a', u'b'), 6), {1:2} ]
+            o = [ 1, 2, 3, (5, (unicode('a'), unicode('b')), 6), {1:2} ]
             o[-1] = o
 
             buf = self.archiverClass.archivedDataWithRootObject_(o)
@@ -204,16 +219,12 @@
             import pickle
             b = pickle.dumps(o)
             o2 = pickle.loads(b)
-            print "+++", o2.value is o2
 
             buf = self.archiverClass.archivedDataWithRootObject_(o)
             self.assertIsInstance(buf, NSData)
             v = self.unarchiverClass.unarchiveObjectWithData_(buf)
 
             self.assertIsInstance(v, a_reducing_class)
-            print type(v.value)
-            print v.value
-            print v
             self.assertIs(v.value, v)
 
         def testRecusiveNesting(self):
@@ -291,7 +302,7 @@
         def test_load_from_canned_string(self): pass
 
         @onlyIf(0, "python unittest not relevant for archiving")
-        def test_maxint64(self): pass
+        def test_maxsize64(self): pass
 
         @onlyIf(0, "python unittest not relevant for archiving")
         def test_dict_chunking(self): pass
@@ -350,7 +361,7 @@
 
         def test_long(self):
             # The real test_long method takes way to much time, test a subset
-            x = 12345678910111213141516178920L << (256*8)
+            x = 12345678910111213141516178920 << (256*8)
             buf = self.dumps(x)
             v = self.loads(buf)
             self.assertEqual(v, x)
@@ -362,7 +373,7 @@
 
             self.assertEqual(v, x)
 
-            for val in (0L, 1L, long(sys.maxint), long(sys.maxint * 128)):
+            for val in (long(0), long(1), long(sys.maxsize), long(sys.maxsize * 128)):
                 for x in val, -val:
                     buf = self.dumps(x)
                     v = self.loads(buf)
@@ -377,7 +388,7 @@
         def produce_global_ext(self, extcode, opcode):
             e = test.pickletester.ExtensionSaver(extcode)
             try:
-                copy_reg.add_extension(__name__, "MyList", extcode)
+                copyreg.add_extension(__name__, "MyList", extcode)
                 x = MyList([1, 2, 3])
                 x.foo = 42
                 x.bar = "hello"

Modified: trunk/pyobjc/pyobjc-core/PyObjCTest/test_bundleFunctions.py
==============================================================================
--- trunk/pyobjc/pyobjc-core/PyObjCTest/test_bundleFunctions.py	(original)
+++ trunk/pyobjc/pyobjc-core/PyObjCTest/test_bundleFunctions.py	Mon Apr 25 05:07:59 2011
@@ -1,5 +1,6 @@
+from __future__ import absolute_import, unicode_literals
 import objc
-import PyObjCTest.fnd as Foundation
+from . import fnd as Foundation
 from PyObjCTools.TestSupport import *
 import os
 
@@ -9,10 +10,10 @@
     return b''.join(args)
 
 FUNCTIONS=[
-    ( u'NSHomeDirectory', S(objc._C_ID)),
-    ( u'NSIsFreedObject', S(objc._C_NSBOOL, objc._C_ID) ),
-    ( u'NSCountFrames', S(objc._C_UINT) ),
-    ( u'NSClassFromString', S(objc._C_CLASS, objc._C_ID) ),
+    ( 'NSHomeDirectory', S(objc._C_ID)),
+    ( 'NSIsFreedObject', S(objc._C_NSBOOL, objc._C_ID) ),
+    ( 'NSCountFrames', S(objc._C_UINT) ),
+    ( 'NSClassFromString', S(objc._C_CLASS, objc._C_ID) ),
 ]
 
 class TestBundleFunctions (TestCase):
@@ -33,12 +34,12 @@
         #value = fn(obj)
         #self.assertTrue(not value)
 
-        fn = d[u'NSHomeDirectory']
+        fn = d['NSHomeDirectory']
         value = fn()
         self.assertEqual(value, os.path.expanduser('~'))
 
-        fn = d[u'NSClassFromString']
-        value = fn(u'NSObject')
+        fn = d['NSClassFromString']
+        value = fn('NSObject')
         self.assertIs(value, NSObject)
 
         # Need to look for a different example, NSCountFrames crashes

Modified: trunk/pyobjc/pyobjc-core/PyObjCTest/test_bundleVariables.py
==============================================================================
--- trunk/pyobjc/pyobjc-core/PyObjCTest/test_bundleVariables.py	(original)
+++ trunk/pyobjc/pyobjc-core/PyObjCTest/test_bundleVariables.py	Mon Apr 25 05:07:59 2011
@@ -1,5 +1,6 @@
+from __future__ import absolute_import, unicode_literals
 import objc
-import PyObjCTest.fnd as Foundation
+from . import fnd as Foundation
 from PyObjCTools.TestSupport import *
 
 class TestBundleVariables (TestCase):
@@ -13,11 +14,11 @@
                 ('NSBundleDidLoadNotification', b'@'),
             ])
 
-        self.assertIn(u'NSBundleDidLoadNotification', d)
-        self.assertIn(u'NSAppleScriptErrorMessage', d)
+        self.assertIn('NSBundleDidLoadNotification', d)
+        self.assertIn('NSAppleScriptErrorMessage', d)
 
-        self.assertIsInstance(d[u'NSAppleScriptErrorMessage'], objc.pyobjc_unicode)
-        self.assertIsInstance(d[u'NSBundleDidLoadNotification'], objc.pyobjc_unicode)
+        self.assertIsInstance(d['NSAppleScriptErrorMessage'], objc.pyobjc_unicode)
+        self.assertIsInstance(d['NSBundleDidLoadNotification'], objc.pyobjc_unicode)
 
     def testSimple(self):
         d = {}

Modified: trunk/pyobjc/pyobjc-core/PyObjCTest/test_conversion.py
==============================================================================
--- trunk/pyobjc/pyobjc-core/PyObjCTest/test_conversion.py	(original)
+++ trunk/pyobjc/pyobjc-core/PyObjCTest/test_conversion.py	Mon Apr 25 05:07:59 2011
@@ -3,21 +3,24 @@
 
 TODO: This only tests C values at the moment.
 """
+from __future__ import absolute_import
 from PyObjCTools.TestSupport import *
-from PyObjCTest.testbndl import pyObjCPy, carrayMaker
-from PyObjCTest.testbndl import UCHAR_MAX
-from PyObjCTest.testbndl import CHAR_MAX, CHAR_MIN
-from PyObjCTest.testbndl import SCHAR_MAX, SCHAR_MIN
-from PyObjCTest.testbndl import USHRT_MAX, SHRT_MAX, SHRT_MIN
-from PyObjCTest.testbndl import UINT_MAX, INT_MAX, INT_MIN
-from PyObjCTest.testbndl import ULONG_MAX, LONG_MAX, LONG_MIN
-from PyObjCTest.testbndl import ULLONG_MAX, LLONG_MAX, LLONG_MIN
-from PyObjCTest.testbndl import DBL_MAX, DBL_MIN, DBL_EPSILON
-from PyObjCTest.testbndl import FLT_MAX, FLT_MIN, FLT_EPSILON
+
+from .testbndl import pyObjCPy, carrayMaker
+from .testbndl import UCHAR_MAX
+from .testbndl import CHAR_MAX, CHAR_MIN
+from .testbndl import SCHAR_MAX, SCHAR_MIN
+from .testbndl import USHRT_MAX, SHRT_MAX, SHRT_MIN
+from .testbndl import UINT_MAX, INT_MAX, INT_MIN
+from .testbndl import ULONG_MAX, LONG_MAX, LONG_MIN
+from .testbndl import ULLONG_MAX, LLONG_MAX, LLONG_MIN
+from .testbndl import DBL_MAX, DBL_MIN, DBL_EPSILON
+from .testbndl import FLT_MAX, FLT_MIN, FLT_EPSILON
 import objc
 import array, sys
 
 
+
 class TestNumbers (TestCase):
     """
     Test of conversion of numbers, especially boundary cases
@@ -26,7 +29,9 @@
     def test_unsigned_char(self):
         self.assertEqual(0, pyObjCPy(objc._C_UCHR, 0))
         self.assertEqual(0, pyObjCPy(objc._C_UCHR, b'\0'))
-        self.assertEqual(0, pyObjCPy(objc._C_UCHR, long(0)))
+
+        if sys.version_info[0] == 2:
+            self.assertEqual(0, pyObjCPy(objc._C_UCHR, long(0)))
         self.assertEqual(0, pyObjCPy(objc._C_UCHR, float(0)))
 
         self.assertEqual(UCHAR_MAX, pyObjCPy(objc._C_UCHR, UCHAR_MAX))
@@ -35,7 +40,9 @@
         else:
             self.assertEqual(UCHAR_MAX, pyObjCPy(objc._C_UCHR, bytes([UCHAR_MAX])))
             self.assertEqual(UCHAR_MAX, pyObjCPy(objc._C_UCHR, bytearray([UCHAR_MAX])))
-        self.assertEqual(UCHAR_MAX, pyObjCPy(objc._C_UCHR, long(UCHAR_MAX)))
+
+        if sys.version_info[0] == 2:
+            self.assertEqual(UCHAR_MAX, pyObjCPy(objc._C_UCHR, long(UCHAR_MAX)))
         self.assertEqual(UCHAR_MAX, pyObjCPy(objc._C_UCHR, float(UCHAR_MAX)))
 
         self.assertRaises((IndexError, ValueError), pyObjCPy, objc._C_UCHR, SCHAR_MIN)
@@ -44,7 +51,8 @@
     def test_char(self):
         self.assertEqual(0, pyObjCPy(objc._C_CHR, 0))
         self.assertEqual(0, pyObjCPy(objc._C_CHR, b'\x00'))
-        self.assertEqual(0, pyObjCPy(objc._C_CHR, long(0)))
+        if sys.version_info[0] == 2:
+            self.assertEqual(0, pyObjCPy(objc._C_CHR, long(0)))
 
         self.assertEqual(CHAR_MAX, pyObjCPy(objc._C_CHR, CHAR_MAX))
         if sys.version_info[0] == 2:
@@ -53,8 +61,9 @@
             self.assertEqual(CHAR_MAX, pyObjCPy(objc._C_CHR, bytes([CHAR_MAX])))
             self.assertEqual(CHAR_MAX, pyObjCPy(objc._C_CHR, bytearray([CHAR_MAX])))
         self.assertEqual(CHAR_MIN, pyObjCPy(objc._C_CHR, CHAR_MIN))
-        self.assertEqual(CHAR_MAX, pyObjCPy(objc._C_CHR, long(CHAR_MAX)))
-        self.assertEqual(CHAR_MIN, pyObjCPy(objc._C_CHR, long(CHAR_MIN)))
+        if sys.version_info[0] == 2:
+            self.assertEqual(CHAR_MAX, pyObjCPy(objc._C_CHR, long(CHAR_MAX)))
+            self.assertEqual(CHAR_MIN, pyObjCPy(objc._C_CHR, long(CHAR_MIN)))
         self.assertEqual(CHAR_MAX, pyObjCPy(objc._C_CHR, float(CHAR_MAX)))
         self.assertEqual(CHAR_MIN, pyObjCPy(objc._C_CHR, float(CHAR_MIN)))
 
@@ -68,8 +77,9 @@
     def test_unsigned_short(self):
         self.assertEqual(0, pyObjCPy(objc._C_USHT, 0))
         self.assertEqual(USHRT_MAX, pyObjCPy(objc._C_USHT, USHRT_MAX))
-        self.assertEqual(0, pyObjCPy(objc._C_USHT, long(0)))
-        self.assertEqual(USHRT_MAX, pyObjCPy(objc._C_USHT, long(USHRT_MAX)))
+        if sys.version_info[0] == 2:
+            self.assertEqual(0, pyObjCPy(objc._C_USHT, long(0)))
+            self.assertEqual(USHRT_MAX, pyObjCPy(objc._C_USHT, long(USHRT_MAX)))
         self.assertEqual(0, pyObjCPy(objc._C_USHT, float(0)))
         self.assertEqual(USHRT_MAX, pyObjCPy(objc._C_USHT, float(USHRT_MAX)))
 
@@ -83,9 +93,10 @@
         self.assertEqual(0, pyObjCPy(objc._C_SHT, 0))
         self.assertEqual(SHRT_MAX, pyObjCPy(objc._C_SHT, SHRT_MAX))
         self.assertEqual(SHRT_MIN, pyObjCPy(objc._C_SHT, SHRT_MIN))
-        self.assertEqual(0, pyObjCPy(objc._C_SHT, long(0)))
-        self.assertEqual(SHRT_MAX, pyObjCPy(objc._C_SHT, long(SHRT_MAX)))
-        self.assertEqual(SHRT_MIN, pyObjCPy(objc._C_SHT, long(SHRT_MIN)))
+        if sys.version_info[0] == 2:
+            self.assertEqual(0, pyObjCPy(objc._C_SHT, long(0)))
+            self.assertEqual(SHRT_MAX, pyObjCPy(objc._C_SHT, long(SHRT_MAX)))
+            self.assertEqual(SHRT_MIN, pyObjCPy(objc._C_SHT, long(SHRT_MIN)))
         self.assertEqual(0, pyObjCPy(objc._C_SHT, float(0)))
         self.assertEqual(SHRT_MAX, pyObjCPy(objc._C_SHT, float(SHRT_MAX)))
         self.assertEqual(SHRT_MIN, pyObjCPy(objc._C_SHT, float(SHRT_MIN)))
@@ -99,8 +110,9 @@
     def test_unsigned_int(self):
         self.assertEqual(0, pyObjCPy(objc._C_UINT, 0))
         self.assertEqual(UINT_MAX, pyObjCPy(objc._C_UINT, UINT_MAX))
-        self.assertEqual(0, pyObjCPy(objc._C_UINT, long(0)))
-        self.assertEqual(UINT_MAX, pyObjCPy(objc._C_UINT, long(UINT_MAX)))
+        if sys.version_info[0] == 2:
+            self.assertEqual(0, pyObjCPy(objc._C_UINT, long(0)))
+            self.assertEqual(UINT_MAX, pyObjCPy(objc._C_UINT, long(UINT_MAX)))
         self.assertEqual(0, pyObjCPy(objc._C_UINT, float(0)))
         self.assertEqual(UINT_MAX, pyObjCPy(objc._C_UINT, float(UINT_MAX)))
 
@@ -114,9 +126,10 @@
         self.assertEqual(0, pyObjCPy(objc._C_INT, 0))
         self.assertEqual(INT_MAX, pyObjCPy(objc._C_INT, INT_MAX))
         self.assertEqual(INT_MIN, pyObjCPy(objc._C_INT, INT_MIN))
-        self.assertEqual(0, pyObjCPy(objc._C_INT, long(0)))
-        self.assertEqual(INT_MAX, pyObjCPy(objc._C_INT, long(INT_MAX)))
-        self.assertEqual(INT_MIN, pyObjCPy(objc._C_INT, long(INT_MIN)))
+        if sys.version_info[0] == 2:
+            self.assertEqual(0, pyObjCPy(objc._C_INT, long(0)))
+            self.assertEqual(INT_MAX, pyObjCPy(objc._C_INT, long(INT_MAX)))
+            self.assertEqual(INT_MIN, pyObjCPy(objc._C_INT, long(INT_MIN)))
         self.assertEqual(0, pyObjCPy(objc._C_INT, float(0)))
         self.assertEqual(INT_MAX, pyObjCPy(objc._C_INT, float(INT_MAX)))
         self.assertEqual(INT_MIN, pyObjCPy(objc._C_INT, float(INT_MIN)))
@@ -131,11 +144,12 @@
     def test_unsigned_long(self):
         self.assertEqual(0, pyObjCPy(objc._C_ULNG, 0))
         self.assertEqual(ULONG_MAX, pyObjCPy(objc._C_ULNG, ULONG_MAX))
-        self.assertEqual(0, pyObjCPy(objc._C_ULNG, long(0)))
-        self.assertEqual(ULONG_MAX, pyObjCPy(objc._C_ULNG, long(ULONG_MAX)))
+        if sys.version_info[0] == 2:
+            self.assertEqual(0, pyObjCPy(objc._C_ULNG, long(0)))
+            self.assertEqual(ULONG_MAX, pyObjCPy(objc._C_ULNG, long(ULONG_MAX)))
         self.assertEqual(0, pyObjCPy(objc._C_ULNG, float(0)))
 
-        if sys.maxint < 2 ** 32:
+        if sys.maxsize < 2 ** 32:
             self.assertEqual(ULONG_MAX, pyObjCPy(objc._C_ULNG, float(ULONG_MAX)))
             self.assertRaises(ValueError, pyObjCPy, objc._C_ULNG, LONG_MIN)
             self.assertRaises(ValueError, pyObjCPy, objc._C_ULNG, LONG_MIN - 1)
@@ -147,11 +161,12 @@
         self.assertEqual(0, pyObjCPy(objc._C_LNG, 0))
         self.assertEqual(LONG_MAX, pyObjCPy(objc._C_LNG, LONG_MAX))
         self.assertEqual(LONG_MIN, pyObjCPy(objc._C_LNG, LONG_MIN))
-        self.assertEqual(0, pyObjCPy(objc._C_LNG, long(0)))
-        self.assertEqual(LONG_MAX, pyObjCPy(objc._C_LNG, long(LONG_MAX)))
-        self.assertEqual(LONG_MIN, pyObjCPy(objc._C_LNG, long(LONG_MIN)))
+        if sys.version_info[0] == 2:
+            self.assertEqual(0, pyObjCPy(objc._C_LNG, long(0)))
+            self.assertEqual(LONG_MAX, pyObjCPy(objc._C_LNG, long(LONG_MAX)))
+            self.assertEqual(LONG_MIN, pyObjCPy(objc._C_LNG, long(LONG_MIN)))
         self.assertEqual(0, pyObjCPy(objc._C_LNG, float(0)))
-        if sys.maxint < 2 ** 32:
+        if sys.maxsize < 2 ** 32:
             self.assertEqual(LONG_MAX, pyObjCPy(objc._C_LNG, float(LONG_MAX)))
             self.assertEqual(LONG_MIN, pyObjCPy(objc._C_LNG, float(LONG_MIN)))
 
@@ -164,8 +179,9 @@
     def test_unsigned_long_long(self):
         self.assertEqual(0, pyObjCPy(objc._C_ULNG_LNG, 0))
         self.assertEqual(ULLONG_MAX, pyObjCPy(objc._C_ULNG_LNG, ULLONG_MAX))
-        self.assertEqual(0, pyObjCPy(objc._C_ULNG_LNG, long(0)))
-        self.assertEqual(ULLONG_MAX, pyObjCPy(objc._C_ULNG_LNG, long(ULLONG_MAX)))
+        if sys.version_info[0] == 2:
+            self.assertEqual(0, pyObjCPy(objc._C_ULNG_LNG, long(0)))
+            self.assertEqual(ULLONG_MAX, pyObjCPy(objc._C_ULNG_LNG, long(ULLONG_MAX)))
         self.assertEqual(0, pyObjCPy(objc._C_ULNG_LNG, float(0)))
 
         with filterWarnings('error', DeprecationWarning):
@@ -183,7 +199,7 @@
     def test_long_long(self):
         self.assertEqual(0, pyObjCPy(objc._C_LNG_LNG, 0))
 
-        if sys.maxint < 2 ** 32:
+        if sys.maxsize < 2 ** 32:
             self.assertEqual(LONG_MAX, pyObjCPy(objc._C_LNG_LNG, float(LONG_MAX)))
         self.assertEqual(LLONG_MAX, pyObjCPy(objc._C_LNG_LNG, LLONG_MAX))
         self.assertEqual(LLONG_MIN, pyObjCPy(objc._C_LNG_LNG, LLONG_MIN))
@@ -204,7 +220,7 @@
         self.assertEqual(DBL_EPSILON, pyObjCPy(objc._C_DBL, DBL_EPSILON))
         self.assertEqual(-DBL_EPSILON, pyObjCPy(objc._C_DBL, -DBL_EPSILON))
 
-        self.assertRaises((OverflowError, ValueError), pyObjCPy, objc._C_DBL, 1L << 10000)
+        self.assertRaises((OverflowError, ValueError), pyObjCPy, objc._C_DBL, 1 << 10000)
 
         self.assertRaises(ValueError, pyObjCPy, objc._C_DBL, "1")
         self.assertRaises(ValueError, pyObjCPy, objc._C_DBL, b"1")
@@ -223,7 +239,7 @@
         # of float
         self.assertNotEqual(DBL_MAX, pyObjCPy(objc._C_FLT, DBL_MAX))
 
-        self.assertRaises((ValueError, OverflowError), pyObjCPy, objc._C_FLT, 1L << 10000)
+        self.assertRaises((ValueError, OverflowError), pyObjCPy, objc._C_FLT, 1 << 10000)
 
         self.assertRaises(ValueError, pyObjCPy, objc._C_FLT, "1")
         self.assertRaises(ValueError, pyObjCPy, objc._C_FLT, b"1")

Modified: trunk/pyobjc/pyobjc-core/PyObjCTest/test_copying.py
==============================================================================
--- trunk/pyobjc/pyobjc-core/PyObjCTest/test_copying.py	(original)
+++ trunk/pyobjc/pyobjc-core/PyObjCTest/test_copying.py	Mon Apr 25 05:07:59 2011
@@ -7,7 +7,7 @@
 
 def funcattr(**kwds):
     def annotate(func):
-        for k, v in kwds.iteritems():
+        for k, v in kwds.items():
             setattr(func, k, v)
         return func
     return annotate

Modified: trunk/pyobjc/pyobjc-core/PyObjCTest/test_corefoundation.py
==============================================================================
--- trunk/pyobjc/pyobjc-core/PyObjCTest/test_corefoundation.py	(original)
+++ trunk/pyobjc/pyobjc-core/PyObjCTest/test_corefoundation.py	Mon Apr 25 05:07:59 2011
@@ -22,6 +22,9 @@
         "NSDate",
     )
 
+if sys.version_info[0] == 3:
+    unicode = str
+
 class TestCoreFoundation (TestCase):
     def testTollFree(self):
         obj = OC_TestCoreFoundation.today()

Modified: trunk/pyobjc/pyobjc-core/PyObjCTest/test_ctests.py
==============================================================================
--- trunk/pyobjc/pyobjc-core/PyObjCTest/test_ctests.py	(original)
+++ trunk/pyobjc/pyobjc-core/PyObjCTest/test_ctests.py	Mon Apr 25 05:07:59 2011
@@ -32,7 +32,7 @@
             except AssertionError:
                 return
 
-            raise AssertionError, "NSInvocation works!"
+            self.fail("NSInvocation works!")
 
         return test_CheckNSInvoke
 

Modified: trunk/pyobjc/pyobjc-core/PyObjCTest/test_exceptions.py
==============================================================================
--- trunk/pyobjc/pyobjc-core/PyObjCTest/test_exceptions.py	(original)
+++ trunk/pyobjc/pyobjc-core/PyObjCTest/test_exceptions.py	Mon Apr 25 05:07:59 2011
@@ -15,7 +15,7 @@
         try:
             o.raiseSimple()
 
-        except objc.error, e:
+        except objc.error as e:
             self.assertEqual(str(e), 'SimpleException - hello world')
             self.assertEqual(e._pyobjc_info_['name'], u'SimpleException')
             self.assertEqual(e._pyobjc_info_['reason'], u'hello world')
@@ -27,7 +27,7 @@
         try:
             o.raiseSimpleWithInfo()
 
-        except objc.error, e:
+        except objc.error as e:
             self.assertEqual(str(e), 'InfoException - Reason string')
             self.assertEqual(e._pyobjc_info_['name'], u'InfoException')
             self.assertEqual(e._pyobjc_info_['reason'], u'Reason string')
@@ -42,7 +42,7 @@
         try:
             o.raiseUnicodeName()
 
-        except objc.error, e:
+        except objc.error as e:
             if sys.version_info[0] == 2:
                 self.assertEqual(str(e), u'SimpleException\u1234\u2049 - hello world'.encode('utf-8'))
             else:
@@ -57,7 +57,7 @@
         try:
             o.raiseUnicodeReason()
 
-        except objc.error, e:
+        except objc.error as e:
             if sys.version_info[0] == 2:
                 self.assertEqual(str(e), u'SimpleException - hello world\u1234\u2049'.encode('utf-8'))
             else:
@@ -72,7 +72,7 @@
         try:
             o.raiseUnicodeWithInfo()
 
-        except objc.error, e:
+        except objc.error as e:
             if sys.version_info[0] == 2:
                 self.assertEqual(str(e), u'InfoException\u1234\u2049 - Reason string\u1234\u2049'.encode('utf-8'))
             else:
@@ -91,7 +91,7 @@
         try:
             o.raiseAString()
 
-        except objc.error, e:
+        except objc.error as e:
             self.assertEqual(e._pyobjc_exc_, u"thrown string")
 
 if __name__ == "__main__":

Modified: trunk/pyobjc/pyobjc-core/PyObjCTest/test_methodedits.py
==============================================================================
--- trunk/pyobjc/pyobjc-core/PyObjCTest/test_methodedits.py	(original)
+++ trunk/pyobjc/pyobjc-core/PyObjCTest/test_methodedits.py	Mon Apr 25 05:07:59 2011
@@ -277,7 +277,7 @@
             class NSObject ( objc.Category(NSObject), object ):
                 pass
 
-            raise AssertionError, u"Can use objc.Category with MI"
+            self.fail("Can use objc.Category with MI")
         except TypeError:
             pass
 
@@ -286,7 +286,7 @@
             class NSFoo (objc.Category(NSObject)):
                     pass
 
-            raise AssertionError, u"Category name != class name"
+            self.fail("Category name != class name")
 
         except TypeError:
             pass
@@ -298,7 +298,7 @@
             class list (objc.Category(list)):
                 pass
 
-            raise AssertionError, u"Category on list???"
+            self.fail("Category on list???")
 
         except TypeError:
             pass

Modified: trunk/pyobjc/pyobjc-framework-PreferencePanes/Examples/EnvironmentPrefs/ShellEnv.py
==============================================================================
--- trunk/pyobjc/pyobjc-framework-PreferencePanes/Examples/EnvironmentPrefs/ShellEnv.py	(original)
+++ trunk/pyobjc/pyobjc-framework-PreferencePanes/Examples/EnvironmentPrefs/ShellEnv.py	Mon Apr 25 05:07:59 2011
@@ -122,7 +122,7 @@
         if not os.path.isdir(dname):
             try:
                 os.mkdir(dname)
-            except os.error, msg:
+            except os.error:
                 return False
 
         if not self.environ.writeToFile_atomically_(fname, True):

Modified: trunk/pyobjc/pyobjc-framework-PreferencePanes/Examples/EnvironmentPrefs/setup.py
==============================================================================
--- trunk/pyobjc/pyobjc-framework-PreferencePanes/Examples/EnvironmentPrefs/setup.py	(original)
+++ trunk/pyobjc/pyobjc-framework-PreferencePanes/Examples/EnvironmentPrefs/setup.py	Mon Apr 25 05:07:59 2011
@@ -4,8 +4,8 @@
 Usage:
     python setup.py py2app
 """
-from distutils.core import setup
-import py2app
+from setuptools import setup
+import sys
 
 infoPlist = dict(
     CFBundleName='Shell Environment',
@@ -19,6 +19,10 @@
     NSMainNibFile='EnvironmentPane',
 )
 
+setup_args = {}
+if sys.version_info[0] == 3:
+    setup_args['use_2to3'] = 1
+
 setup(
     name="Shell Environment",
     plugin=['ShellEnv.py'],
@@ -27,4 +31,5 @@
         extension=".prefPane",
         plist=infoPlist,
     )),
+    **setup_args
 )

Modified: trunk/pyobjc/pyobjc-metadata/Doc/xmlformat.txt
==============================================================================
--- trunk/pyobjc/pyobjc-metadata/Doc/xmlformat.txt	(original)
+++ trunk/pyobjc/pyobjc-metadata/Doc/xmlformat.txt	Mon Apr 25 05:07:59 2011
@@ -26,7 +26,7 @@
   - 'z': a small integer of type ``char``
   - 'Z': a value of type 'bool'
 
-* PyObjC adds the attribute "block_pointer" to the "arg" and "retval" elements.
+* PyObjC adds the attribute "block" to the "arg" and "retval" elements.
 
 * PyObjC adds the attribute "c_array_delimited_by_null" to the "function" and
   "method" elements.
@@ -422,7 +422,7 @@
    can contain the encoded signature for the selector. This can be used by
    bridges for additional type-checking.
 
- * ``block_pointer`` (BOOLEAN): if true the argument is a block. 
+ * ``block`` (BOOLEAN): if true the argument is a block. 
 
    The signature of the block is described by subelements of this element and
    does not include the implement first argument.

Modified: trunk/pyobjc/pyobjc-metadata/Lib/PyObjCMetaData/genwrapper.py
==============================================================================
--- trunk/pyobjc/pyobjc-metadata/Lib/PyObjCMetaData/genwrapper.py	(original)
+++ trunk/pyobjc/pyobjc-metadata/Lib/PyObjCMetaData/genwrapper.py	Mon Apr 25 05:07:59 2011
@@ -114,6 +114,23 @@
         globals=globals())
 """)
 
+INIT_TMPL_NOID=textwrap.dedent("""\
+    '''
+    Python mapping for the %(framework)s framework.
+
+    This module does not contain docstrings for the wrapped code, check Apple's
+    documentation for details on how to use these functions and classes. 
+    '''
+
+    import objc as _objc
+    %(frameworkDepends)s
+
+    __bundle__ = _objc.initFrameworkWrapper("%(framework)s",
+        frameworkPath=_objc.pathForFramework(
+            "%(frameworkPath)s"),
+        globals=globals())
+""")
+
 
 # Note: the test template doesn't define tests, but only contains a template
 # for some tests. This is because it would be rather pointless to check if 
@@ -217,7 +234,8 @@
             raise RuntimeError, "plutil failed"
         pl = plistlib.readPlist('Info.plist')
         os.unlink('Info.plist')
-    return pl['CFBundleIdentifier']
+
+    return pl.get('CFBundleIdentifier', None)
 
 def getFrameworkPath(framework):
 
@@ -336,7 +354,11 @@
         
     fp = open(
         os.path.join(basedir, "Lib", framework, '__init__.py'), 'w')
-    fp.write(INIT_TMPL % locals())
+
+    if bundleIdentifier is None:
+        fp.write(INIT_TMPL_NOID % locals())
+    else:
+        fp.write(INIT_TMPL % locals())
     fp.close()
 
     fp = open(

Modified: trunk/pyobjc/pyobjc-metadata/Lib/PyObjCMetaData/lint.py
==============================================================================
--- trunk/pyobjc/pyobjc-metadata/Lib/PyObjCMetaData/lint.py	(original)
+++ trunk/pyobjc/pyobjc-metadata/Lib/PyObjCMetaData/lint.py	Mon Apr 25 05:07:59 2011
@@ -18,12 +18,18 @@
     'r^{__CFData}',
 ]
 
+gOpaqueTypes = [
+        '^{_NSZone=}',
+]
+
 default_name_attribute='name'
 name_attribute={
     'method': 'selector',
+    'depends_on': 'path',
 }
 
 mandatory_attributes={
+    'depends_on': ('path,'),
     'struct': ('name',),
     'cftype': ('name',),
     'opaque': ('name',),
@@ -39,6 +45,7 @@
 }
 
 valid_attributes={
+    'depends_on': ('path,'),
     'struct': ('name', 'type', 'type64', 'opaque'),
     'cftype': ('name', 'type', 'type64', 'tollfree', 'gettypeid_func'),
     'opaque': ('name', 'type', 'type64'),
@@ -50,9 +57,9 @@
     'class': ('name',),
     'informal_protocol': ('name',),
     ('informal_protocol', 'method'): ('selector', 'type', 'type64', 'class_method'),
-    ('class', 'method'): ('selector', 'class_method', 'variadic', 'ignore', 'suggestion', ),
-    'arg': ('c_array_length_in_arg', 'c_array_of_fixed_length', 'c_array_delimited_by_null', 'c_array_of_variable_length', 'function_pointer', 'sel_of_type', 'sel_of_type64', 'c_array_length_in_retval', 'type_modifier', 'null_accepted', 'printf_format', 'already_retained', 'type', 'type64', 'index'),
-    'retval': ('c_array_length_in_arg', 'c_array_of_fixed_length', 'c_array_delimited_by_null', 'c_array_of_variable_length', 'function_pointer', 'sel_of_type', 'sel_of_type64', 'already_retained', 'type', 'type64'),
+    ('class', 'method'): ('selector', 'class_method', 'variadic', 'ignore', 'suggestion', 'c_array_delimited_by_null', ),
+    'arg': ('c_array_length_in_arg', 'c_array_of_fixed_length', 'c_array_delimited_by_null', 'c_array_of_variable_length', 'function_pointer', 'sel_of_type', 'sel_of_type64', 'c_array_length_in_retval', 'type_modifier', 'null_accepted', 'printf_format', 'already_retained', 'already_cfretained', 'type', 'type64', 'index', 'function_pointer_retained', 'c_array_length_in_result'),
+    'retval': ('c_array_length_in_arg', 'c_array_of_fixed_length', 'c_array_delimited_by_null', 'c_array_of_variable_length', 'function_pointer', 'sel_of_type', 'sel_of_type64', 'already_retained', 'already_cfretained', 'type', 'type64'),
 }
 
 boolean_attributes={
@@ -63,8 +70,8 @@
     'function': ('variadic', 'inline'),
     ('informal_protocol', 'method'): ('class_method',),
     ('class', 'method'): ('class_method', 'variadic', 'ignore', ),
-    'arg': ('c_array_delimitd_by_null', 'c_array_of_variable_length', 'function_pointer', 'c_array_length_in_retval', 'null_accepted', 'printf_format', 'already_retained', ),
-    'retval': ('c_array_delimitd_by_null', 'c_array_of_variable_length', 'function_pointer', 'already_retained'),
+    'arg': ('c_array_delimitd_by_null', 'c_array_of_variable_length', 'function_pointer', 'c_array_length_in_retval', 'null_accepted', 'printf_format', 'already_cfretained', 'already_retained', 'function_pointer_retained', 'c_array_length_in_result',),
+    'retval': ('c_array_delimitd_by_null', 'c_array_of_variable_length', 'function_pointer', 'already_cfretained', 'already_retained'),
 }
 
 encoding_attributes={
@@ -72,7 +79,7 @@
     'cftype': ('type', 'type64',),
     'opaque': ('type', 'type64',),
     'constant': ('type', 'type64',),
-    ('informal_protocol', 'method'): ('type', 'type64'),
+    #('informal_protocol', 'method'): ('type', 'type64'),
     'arg': ('type', 'type64',),
     'retval': ('type', 'type64',),
 }
@@ -136,7 +143,8 @@
             objc._C_CLASS, objc._C_DBL, objc._C_FLT, objc._C_ID, objc._C_INT, 
             objc._C_LNG, objc._C_LNG_LNG, objc._C_NSBOOL, objc._C_SEL, objc._C_SHT, 
             objc._C_UCHR, objc._C_UINT, objc._C_ULNG, objc._C_ULNG_LNG, objc._C_UNDEF, 
-            objc._C_USHT):
+            objc._C_USHT, objc._C_VOID, objc._C_CHAR_AS_INT, objc._C_CHAR_AS_TEXT,
+            objc._C_UNICHAR):
 
         return len(typestr) == 1
 
@@ -211,6 +219,12 @@
             typestr = typestr[1:]
         return typestr == ''
 
+    elif typestr[0] in (objc._C_PTR, objc._C_IN, objc._C_OUT, objc._C_INOUT, objc._C_CONST):
+        return validate_encoding(typestr[1:])
+
+    else:
+        return False
+
     return True
 
 def validate_encoding_string(typestr):
@@ -365,9 +379,12 @@
                 print "WARNING: %s: non-selector (%s) and sel_of_type annotation"%(
                         tag, element.get('type'))
 
+        if tp == '*':
+            print "WARNING: %s: has type=='*'"%(tag,)
+
         if tp.startswith('^') or tp.startswith('r^'):
             if element.tag == 'arg' and element.get('type_modifier') is None:
-                if tp not in gCoreFoundationTypes and tp != '^?':
+                if tp not in gCoreFoundationTypes and tp not in gOpaqueTypes and tp != '^?' and tp != '^v':
                     print "WARNING: %s: pointer-type (%s) without 'type_modifier'"%(
                         tag, tp)
 
@@ -376,6 +393,16 @@
                 print "WARNING: %s: type '^?', but not a function_pointer"%(
                         tag,)
 
+        if element.get('function_pointer'):
+            if tp != '^?':
+                print "WARNING: %s: function_pointer, but type is %r"%(
+                        tag, tp)
+
+
+        if element.get('function_pointer_retained'):
+            if not element.get('function_pointer'):
+                print "WARNING: %s: function_pointer_retained, but not a function_pointer"%(tag,)
+
 
 
 
@@ -641,9 +668,9 @@
                     print "ERROR: %s %r: method without 'selector'"%(
                             element.tag, name(element))
 
-                basicValidation('%s %r: %s %r'%(
-                    element.tag, name(element), method.tag, name(method)),
-                    method, element)
+                mmsg = '%s %r: %s %r'%(
+                        element.tag, name(element), method.tag, name(method))
+                basicValidation(mmsg, method, element)
 
                 arglist = list(method.getchildren())
                 if len(arglist) != 0:
@@ -701,6 +728,11 @@
                         validateArgRetval('%s %r: %s %r (arg %s)'%(
                             element.tag, name(element), method.tag, name(method), a.get('index')), a, None)
 
+        elif element.tag == 'opaque':
+            tp = element.get('type')
+            if tp is not None:
+                gOpaqueTypes.append(tp)
+
         else:
             if element.tag not in valid_attributes:
                 print "ERROR: illegal tag: %r"%(element.tag,)
@@ -708,6 +740,7 @@
                 print "ERROR: %s %r:Subelements present"%(
                         element.tag, name(element))
 
+
     
 if __name__ == "__main__":
     main()

Modified: trunk/pyobjc/pyobjc-metadata/Lib/PyObjCMetaData/scanframework.py
==============================================================================
--- trunk/pyobjc/pyobjc-metadata/Lib/PyObjCMetaData/scanframework.py	(original)
+++ trunk/pyobjc/pyobjc-metadata/Lib/PyObjCMetaData/scanframework.py	Mon Apr 25 05:07:59 2011
@@ -82,6 +82,7 @@
 
 gBooleanAttributesDefaultingFalse=[
     'nsstring',
+    'free_result',
     'already_retained',
     'already_cfretained',
     'class_method',
@@ -114,7 +115,6 @@
             'type', 'type64', 
             'already_retained',
             'already_cfretained',
-            'numeric',
             'c_array_length_in_arg',
             'c_array_of_fixed_length',
             'c_array_delimited_by_null',
@@ -122,6 +122,7 @@
             'sel_of_type',
             'function_pointer',
             'function_pointer_retained',
+            'free_result',
         ],
     arg = [ 
             'type', 'type64', 
@@ -129,7 +130,6 @@
             'null_accepted', 
             'already_retained',
             'already_cfretained',
-            'numeric',
             'c_array_length_in_arg',
             'c_array_of_fixed_length',
             'c_array_delimited_by_null',
@@ -331,6 +331,7 @@
         if level and (not elem.tail or not elem.tail.strip()):
             elem.tail = i
 
+
 class cleanfile(file):
     def write(self, s):
         file.write(self, cleanup_text(s))
@@ -408,7 +409,7 @@
 
 def link_flag_for_framework(name):
     try:
-        framework_find(name)
+        framework_find(name + '.framework')
         return name
 
     except ValueError:
@@ -624,11 +625,13 @@
         self.special_type_encodings.add(objc._C_PTR+objc._C_BOOL)
 
         if hasattr(objc, '_C_UNICHAR'):
+            #print "WITH _C_UNICHAR"
             self.special_type_encodings.add(objc._C_UNICHAR)
             self.special_type_encodings.add(objc._C_PTR+objc._C_UNICHAR)
             self.special_type_encodings.add(objc._C_PTR+objc._C_PTR+objc._C_UNICHAR)
             self.special_type_encodings.add(objc._C_CONST+objc._C_PTR+objc._C_UNICHAR)
         else:
+            #print "WITHOUT _C_UNICHAR"
             objc._C_UNICHAR = self.encodedType('unichar')[0]
 
         if hasattr(objc, '_C_CHAR_AS_TEXT'):
@@ -766,11 +769,11 @@
         # Make up a struct tag if a struct definition doesn't have one
         if data and data.startswith('{?'):
             if ' ' not in ctype:
-                data = data[0] + ctype + data[2:]
+                data = data[0] + "_" + ctype + data[2:]
 
         if data2 and data2.startswith('{?'):
             if ' ' not in ctype:
-                data2 = data2[0] + ctype + data2[2:]
+                data2 = data2[0] + "_" + ctype + data2[2:]
 
 
         if data:
@@ -863,6 +866,9 @@
                 objc._C_IN, objc._C_OUT, objc._C_INOUT, objc._C_CONST):
             encoded = encoded[1:]
 
+        if encoded == objc._C_ID:
+            return False
+
         for nm, tp, tp64 in self.cftypes:
             if tp == encoded:
                 return True
@@ -911,7 +917,7 @@
         if self.isCFType(encoded) or self.isOpaquePointerType(encoded):
             return False
 
-        return True
+        return False
     
     def emitDependecyList(self, fp):
         for k in sorted(self.dependencies):
@@ -1073,6 +1079,7 @@
 
             func.set('name', nm)
             self.copyExceptionData(func, exc)
+            self.pruneComment(func)
 
             retexc = self.find_exception('function', nm, 'retval')
 
@@ -1095,8 +1102,6 @@
                 if arg['encoded64'] and arg['encoded64'] != arg['encoded']:
                     e.set('type64', arg['encoded'])
 
-                if 'numeric' in arg:
-                    e.set('numeric', arg['numeric'])
 
                 self.copyExceptionData(e, exc, copyChildren=True)
                 self.pruneComment(e)
@@ -1177,6 +1182,10 @@
                         'method', method['selector'],
                         exceptions=clsexc, nameattr='selector')
 
+                if methodExc is not None and methodExc.get('ignore') == 'true':
+                    print 'ignore', classname, method['selector']
+                    continue
+
                 # The 'ignore' atribute on methods is slight different than
                 # on other elements: copy to the metadata file.
                 #if methodExc and methodExc.get('ignore') == 'true':
@@ -1191,6 +1200,12 @@
                 if method.get('comment'):
                     meth.set('comment', method['comment'])
 
+                if methodExc is not None and methodExc.get('suggestion'):
+                    # If the method has a suggestion, skip all other metadata
+                    # we might have calculated.
+                    meth.set('suggestion', methodExc.get('suggestion'))
+                    #continue
+
                 self.copyExceptionData(meth, methodExc)
                 self.pruneComment(meth)
 
@@ -1273,6 +1288,7 @@
                 if nm == name:
                     break
             else:
+                print "No exception data for %s yet", nm, node
                 e = ET.SubElement(root, node.tag, name=nm)
                 self.copyExceptionData(e, node)
                 if node is not None:
@@ -1299,10 +1315,11 @@
             if name.startswith('_') and exc is None:
                 continue
 
-            e = ET.SubElement(root, 'struct', name=name)
+            e = ET.SubElement(root, 'struct', name=name, type=encoded, type64=encoded64)
             if exc is not None and exc.get('ignore') == 'true':
                 e.set('ignore', 'true')
 
+
             self.copyExceptionData(e, exc)
 
         self.copyUnhandledNodes(root, 'struct', self.structs)
@@ -1368,6 +1385,8 @@
                 e = ET.SubElement(root, 'string_constant', name=name)
 
                 if exc.get('ignore') == 'true':
+                    if exc.get('comment'):
+                        e.set('comment', exc.get('comment'))
                     e.set('ignore', 'true')
 
                 self.copyExceptionData(e, exc)
@@ -1388,6 +1407,8 @@
             exc = self.find_exception('function', nm)
             if exc is not None and exc.get('ignore') == 'true':
                 e = ET.SubElement(root, 'function', name=nm, ignore='true')
+                if exc.get('comment'):
+                    e.set('comment', exc.get('comment'))
                 continue
 
             func = None
@@ -1506,16 +1527,13 @@
             for idx, arg in enumerate(arginfo):
                 exc = self.find_exception('function', nm, 'arg', idx)
 
-                if exc is not None or self.isPointerType(arg['encoded']) or 'numeric' in arg:
+                if exc is not None or self.isPointerType(arg['encoded']):
                     func = makeFunction()
                     e = ET.SubElement(func, 'arg', index=str(idx))
                     e.set('type', arg['encoded'])
                     if arg.get('encoded64'):
                         e.set('type64', arg['encoded64'])
 
-                    if 'numeric' in arg:
-                        e.set('numeric', arg['numeric'])
-
                     self.copyExceptionData(e, exc, copyChildren=True)
                     self.pruneTypeInfo(e, 'type', arg['encoded'], arg.get('encoded64'))
 
@@ -1597,8 +1615,10 @@
                 exc = self.find_exception(
                         'retval', None, exceptions = methodExc)
 
+                #print "DEBUGCHECK: method ret", ret
                 if self.isPointerType(ret) or (ret64 and self.isPointerType(ret64)) or ret == objc._C_SEL: 
                     # Ignore special_encodings for the exceptions file:
+                    #print "DEBUGCHECK: copy into exceptions", self.isPointerType(ret), self.isPointerType(ret64), ret == objc._C_SEL
                     # or ret in self.special_type_encodings:
                     if meth is None:
                         cls, meth = getMethod()
@@ -1634,7 +1654,7 @@
                     if arg in self.special_type_encodings:
                         # Don't add these to the exceptions file unless there
                         # is other metadata.
-                        if exc is not None:
+                        if exc is not None or self.isPointerType(arg):
                             cls, meth = getMethod()
                             e = ET.SubElement(meth, 
                                     'arg', index=str(argidx))
@@ -1676,7 +1696,7 @@
                         self.classes[classname],
                         nameAttr='selector', getName=lambda x:x['selector'])
 
-        self.copyUnhandledNodes(root, 'class', self.classes)
+        self.copyUnhandledNodes(root, 'class', self.classes.values())
 
         print >>fp, HEADER
         indentET(root)
@@ -1700,7 +1720,8 @@
             if node.get('type'):
                 # Ensure that this type gets used throughout: add the type
                 # to the encodings dict and to special_type_encodings
-                self.special_type_encodings.add(node.get('type'))
+                if node.get('type') != objc._C_ID:
+                    self.special_type_encodings.add(node.get('type'))
 
                 nm = node.get('name')
                 tp = self.stripStructFieldNames(node.get('type'))
@@ -2412,7 +2433,7 @@
                 logging.debug("Cannot get encoded struct %s", nm) 
                 continue
 
-            if realTp != tp:
+            if realTp != tp and tp != objc._C_ID:
                 self.special_type_encodings.add(tp)
                 self.types[nm] = tp
                 self.types[nm + '*'] = objc._C_PTR + tp
@@ -2463,14 +2484,78 @@
         # Skip structs containing function pointers, those cannot be
         # wrapped automaticly (yet?)
         if isinstance(token, Struct):
+            if contains_instances_of(token.matches(), FunctionStructMember): return
             externalname = name
+            fields = token.matches()
 
         elif isinstance(token, NamedStruct):
             if contains_instances_of(token.matches(), FunctionStructMember): return
 
             externalname = token.matches()[-1]['name']
+            fields = token.matches()[:-1]
         else:
             externalname = token['name']
+            fields = token.matches()
+
+
+
+
+
+# And attempt to avoid compiling, won't work when a struct has different
+# definitions for 64-bit vs. 32-bit (such as NSPoint).
+#
+#        data   = [ objc._C_STRUCT_B]
+#        data64 = [ objc._C_STRUCT_B]
+#
+#        if token['structname']:
+#            data.append(token['structname'])
+#            data64.append(token['structname'])
+#        else:
+#            data.append('_' + externalname)
+#            data64.append('_' + externalname)
+#        data.append('=')
+#        data64.append('=')
+#        for field in fields:
+#            name = field['name']
+#            array = ''
+#            if name.endswith('['):
+#                name, array = name.split('[', 1)
+#                array = '[' + array
+#
+#            print "XXX: Struct field", externalname, field
+#
+#            data.append('"%s"'%(name))
+#            data64.append('"%s"'%(name))
+#            tp, tp64 = self.encodedType(field['type'] + array)
+#            #if tp == objc._C_LNG:
+#                #tp = objc._C_INT
+#            #elif tp == objc._C_ULNG:
+#                #tp = objc._C_UINT
+#            if tp64 == objc._C_LNG:
+#                tp64 = objc._C_LNG_LNG
+#            elif tp64 == objc._C_ULNG:
+#                tp64 = objc._C_ULNG_LNG
+#            data.append(tp)
+#            data64.append(tp64)
+#        data.append(objc._C_STRUCT_E)
+#        data64.append(objc._C_STRUCT_E)
+#        try:
+#            data = ''.join(data)
+#        except TypeError:
+#            data = ''
+#            return
+#
+#        try:
+#            data64 = ''.join(data64)
+#        except TypeError:
+#            data64 = ''
+#
+#        if not data and not data64:
+#            # A field-type could not be encoded in 32-bit or 64-bit mode,
+#            # ignore the struct
+#            print "Ignore struct %s: cannot encode some fields"%(externalname,)
+#            return
+            
 
         ivarType = externalname
         data, data64 = self._compileAndRun(
@@ -2480,12 +2565,34 @@
         # Found a struct without a struct tag. That's rather useless because
         # two different types may have the same structure (excluding field *names*)
         # Therefore make up a struct tag.
+
+        print type(token).__name__, externalname, data, self.stripStructFieldNames(data)
+        if externalname in self.types:
+            print "-->", self.types[externalname]
+
         if data and data[1] == '?':
             data = data[0] + '_' + externalname + data[2:]
-
-        if data64 and data64[1] == '?':
+        if data and data64[1] == '?':
             data64 = data64[0] + '_' + externalname + data64[2:]
 
+        exc = self.find_exception('struct', externalname)
+        if exc is not None and exc.get('type') is not None:
+            data = exc.get('type')
+        if exc is not None and exc.get('type64') is not None:
+            data64 = exc.get('type64')
+
+        self.types[externalname] = self.stripStructFieldNames(data)
+        self.types64[externalname] = self.stripStructFieldNames(data64)
+        self.types[externalname+'*'] = objc._C_PTR+self.stripStructFieldNames(data)
+        self.types64[externalname+'*'] = objc._C_PTR+self.stripStructFieldNames(data64)
+        print externalname, self.types[externalname]
+
+        #if data64 and data64[1] == '?':
+        #    data64 = data64[0] + '_' + externalname + data64[2:]
+        self.types64[externalname] = self.stripStructFieldNames(data64)
+        self.types64[externalname+'*'] = objc._C_PTR+self.stripStructFieldNames(data64)
+
+
         self.structs.append((externalname, data, data64))
         logging.debug("Struct definition for %s", externalname)
 
@@ -2497,7 +2604,8 @@
         indirect = normalize_type(token['indirection'])
 
         if not indirect and tag in self.plain_structs:
-            self._processNamedStruct(token)
+            print "--->", token
+            #self._processNamedStruct(token)
             return
 
         logging.debug("Process opaque struct: %(name)s"% token)
@@ -2598,6 +2706,8 @@
 
                 returnType, returnType64 = self.encodedType(t['returntype'] or 'id')
                 if self.isPointerType(returnType) or returnType in self.special_type_encodings:
+                    if not t['name']:
+                        print t
                     methods.append(
                         dict(
                             selector=t['name'],
@@ -2654,6 +2764,8 @@
 
 
                 selector = ''.join(segs)
+                if not selector:
+                    print t
 
 
                 for i in range(len(segs)+1):
@@ -2752,8 +2864,6 @@
 
                     # First try to tell about the propertygetter
                     returnsMeta = {}
-                    if self.isStringyType(tp, curtype):
-                        returnsMeta['numeric'] = 'false'
                     
                     if self.isPointerType(tp) or tp in self.special_type_encodings or returnsMeta:
                         methods.append(
@@ -2800,9 +2910,6 @@
 
                 returnType, returnType64 = self.encodedType(t['returntype'] or 'id')
                 returnsMeta = {}
-                if self.isStringyType(returnType, t['returntype'] or 'id'):
-                    returnsMeta['numeric'] = 'false'
-
                 if self.isPointerType(returnType) or returnType in self.special_type_encodings or returnsMeta:
                     methods.append(
                         dict(
@@ -2824,8 +2931,6 @@
                
                 returnType, returnType64 = self.encodedType(t['returntype'] or 'id')
                 returnsMeta = {}
-                if self.isStringyType(returnType, t['returntype'] or 'id'):
-                    returnsMeta['numeric'] = 'false'
 
                 haveSpecial = self.isPointerType(returnType) or returnType in self.special_type_encodings
                 arguments = {}
@@ -2857,8 +2962,7 @@
 
                         elif self.isStringyType(argType, s['type']):
                             haveSpecial = True
-                            arguments[idx] = (argType, argType64, {
-                                'numeric': 'false'})
+                            arguments[idx] = (argType, argType64, None)
 
 
                 selector = ''.join(segs)
@@ -2915,7 +3019,7 @@
                 )
 
                 if returnType64 and returnType64 != returnType:
-                    methods[-1]['type64'] = returnType64 + '@:',
+                    methods[-1]['type64'] = returnType64 + '@:'
 
             elif isinstance(t, SegmentedMethodDef):
                 if t['kind'] == '-':
@@ -2996,8 +3100,6 @@
                         name, returns)
                 return
             returnMeta = {}
-            if self.isStringyType(returnType, returns):
-                returnMeta['numeric'] = 'false'
 
             self.functions.append((name, (returnType,returnType64, returnMeta), [], False))
             return
@@ -3012,8 +3114,6 @@
             return
 
         returnMeta = {}
-        if self.isStringyType(returnType, returns):
-            returnMeta['numeric'] = 'false'
 
         arginfo = []
         for idx, arg in enumerate([ x for x in token.matches()[:-1] if not isinstance(x, BlockComment)]):
@@ -3061,8 +3161,6 @@
                     name, tp, idx)
                 return
 
-            if self.isStringyType(arg['encoded'], tp):
-                arg['numeric'] = 'false'
 
         if isinstance(token, StaticInlineFunction):
             self.inline_functions.append((name, (returnType, returnType64), arginfo, variadic))
@@ -3347,7 +3445,10 @@
 
         outfp.close()
         if options.outfile:
-            os.rename(options.outfile + '~', options.outfile)
+            try:
+                os.rename(options.outfile + '~', options.outfile)
+            except os.error, msg:
+                print options.outfile, msg
 
         if options.format == 'both':
 
@@ -3360,7 +3461,10 @@
             meta.emitExceptionsXML(outfp)
 
             if options.outmeta:
-                os.rename(options.outmeta + '~', options.outmeta)
+                try:
+                    os.rename(options.outmeta + '~', options.outmeta)
+                except os.error, msg:
+                    print options.outmeta, msg
 
     except:
         if options.outfile is not None:

Modified: trunk/pyobjc/pyobjc-metadata/Lib/PyObjCMetaData/tokenize_header.py
==============================================================================
--- trunk/pyobjc/pyobjc-metadata/Lib/PyObjCMetaData/tokenize_header.py	(original)
+++ trunk/pyobjc/pyobjc-metadata/Lib/PyObjCMetaData/tokenize_header.py	Mon Apr 25 05:07:59 2011
@@ -551,7 +551,7 @@
 class StructMember(Token):
     pattern = pattern(r'''
     (const\s+)?
-    (?P<type>%(IDENTIFIER)s%(INDIRECTION)s*)
+    (?P<type>(?:%(IDENTIFIER)s\s*)+%(INDIRECTION)s*)
     \s*(const\s+)?
     (?P<name>
         %(IDENTIFIER)s

------------------------------------------------------------------------------
Fulfilling the Lean Software Promise
Lean software platforms are now widely adopted and the benefits have been 
demonstrated beyond question. Learn why your peers are replacing JEE 
containers with lightweight application servers - and what you can gain 
from the move. http://p.sf.net/sfu/vmware-sfemails