1. Dwayne Litzenberger
  2. pyobjc

Commits

Ronald Oussoren  committed 5536ef3

Various updates in pyobjc-core)

*) Remove use_2to3 from setup.py, the code is now valid for python 2 and 3 without
translation (for python2.6 and later).

This will make development easier, and removes a very expensive
translation step when installing for python 3.x

*) Initial support for Python 3.3

This is not yet finished, there are still failing testcases due to
the new unicode representation in 3.3.

  • Participants
  • Parent commits 6025e47
  • Branches default

Comments (0)

Files changed (65)

File pyobjc-core/Lib/PyObjCTools/KeyValueCoding.py

View file
  • Ignore whitespace
 
 import objc
 import types
+import sys
 
 if sys.version_info[0] == 2:
     from itertools import imap as map
     pass
 
 else:
-    basestr = str
+    basestring = str
 
 if objc.lookUpClass('NSObject').alloc().init().respondsToSelector_('setValue:forKey:'):
     SETVALUEFORKEY = 'setValue_forKey_'

File pyobjc-core/Lib/PyObjCTools/TestSupport.py

View file
  • Ignore whitespace
     else:
         return value
 
+def cast_longlong(value):
+    """
+    Cast value to 64bit integer
+
+    Usage:
+        cast_longlong(1 << 63) == -1
+    """
+    value = value & 0xffffffffffffffff
+    if value & 0x8000000000000000:
+        value =   ~value + 1 & 0xffffffffffffffff
+        return -value
+    else:
+        return value
+
 def cast_uint(value):
     """
     Cast value to 32bit integer
     value = value & 0xffffffff
     return value
 
+def cast_ulonglong(value):
+    """
+    Cast value to 64bit integer
+    """
+    value = value & 0xffffffffffffffff
+    return value
+
 _os_release = None
 def os_release():
     """
     def assertResultIsNullTerminated(self, method, message = None):
         info = method.__metadata__()
         if not info['retval'].get('c_array_delimited_by_null'):
-            self.fail(message or "argument %d of %r is not a nul-terminated array"%(argno, method))
+            self.fail(message or "result of %r is not a nul-terminated array"%(method,))
 
     def assertIsNullTerminated(self, method, message = None):
         info = method.__metadata__()

File pyobjc-core/Lib/PyObjCTools/_BSCompiler.py

View file
  • Ignore whitespace
                 result.append(', ')
             result.append(repr(a))
 
-        for k, v in self._kwds.iteritems():
+        for k in self._kwds:
+            v = self.kwds[k]
             if result[-1] != '(':
                 result.append(', ')
             result.append(k)

File pyobjc-core/Lib/objc/__init__.py

View file
  • Ignore whitespace
         import copy_reg
 
     import objc._objc as _objc
-    for k,v in _objc.__dict__.iteritems():
-        g.setdefault(k,v)
+    for k in _objc.__dict__:
+        g.setdefault(k, getattr(_objc, k))
 _update()
 del _update
 

File pyobjc-core/Lib/objc/_category.py

View file
  • Ignore whitespace
             raise TypeError("Category name must be same as class name")
 
 
-        m = [ x[1] for x in methods.iteritems() if x[0] not in cls._IGNORENAMES  and isinstance(x[1], (FunctionType, MethodType, selector, classmethod))]
-        vars = [ x for x in methods.iteritems() if x[0] not in cls._IGNORENAMES  and not isinstance(x[1], (FunctionType, MethodType, selector, classmethod))]
+        m = [ x[1] for x in methods.items() if x[0] not in cls._IGNORENAMES  and isinstance(x[1], (FunctionType, MethodType, selector, classmethod))]
+        vars = [ x for x in methods.items() if x[0] not in cls._IGNORENAMES  and not isinstance(x[1], (FunctionType, MethodType, selector, classmethod))]
         for k, v in vars:
             if isinstance(v, ivar):
                 raise TypeError("Cannot add instance variables in a Category")
     in the class definition will be added to the existing class.
     """
     if not isinstance(cls, objc_class):
-        raise TypeError, "Category can only be used on Objective-C classes"
+        raise TypeError("Category can only be used on Objective-C classes")
     retval = _CategoryMeta._newSubclass('Category', (), dict(real_class=cls))
     return retval

File pyobjc-core/Lib/objc/_compat.py

View file
  • Ignore whitespace
         try:
             return objc.lookUpClass(name)
         except objc.nosuchclass_error:
-            raise AttributeError, name
+            raise AttributeError(name)
 
     def __eq__(self, other):
         return self is other

File pyobjc-core/Lib/objc/_convenience.py

View file
  • Ignore whitespace
 """
 from objc._objc import _setClassExtender, selector, lookUpClass, currentBundle, repythonify, splitSignature, _block_call
 from objc._objc import registerMetaDataForSelector
-from itertools import imap
 import sys
 
 __all__ = ( 'addConvenienceForSelector', 'addConvenienceForClass' )
 CONVENIENCE_METHODS = {}
 CLASS_METHODS = {}
 
+if sys.version_info[0] == 3:
+    # XXX: Temporary backward compatibily
+    xrange = range
+
 def addConvenienceForSelector(selector, methods):
     """
     Add the list with methods to every class that has a selector with the
 
     look_at_super = (super_class is not None and super_class.__name__ != 'Object')
 
-    for k, sel in type_dict.items():
+    for k, sel in list(type_dict.items()):
         if not isinstance(sel, selector):
             continue
 
             def __getattr__(self, key):
                 try:
                     return self.__object.valueForKey_(key)
-                except KeyError, msg:
+                except KeyError as msg:
                     if hasattr(msg, '_pyobjc_info_') and msg._pyobjc_info_['name'] == 'NSUnknownKeyException':
                         raise AttributeError(key)
 
                     super(kvc, self).__setattr__(key, value)
 
             def __getitem__(self, key):
-                if not isinstance(key, (str, unicode)):
+                if not isinstance(key, STR_TYPES):
                     raise TypeError("Key must be string")
                 return self.__object.valueForKey_(key)
 
             def __setitem__(self, key, value):
-                if not isinstance(key, (str, unicode)):
+                if not isinstance(key, STR_TYPES):
                     raise TypeError("Key must be string")
                 return self.__object.setValue_forKey_(value, key)
 
             for key, value in other:
                 self[key] = value
 
-    for k, v in kwds.iteritems():
-        self[k] = v
+    for k in kwds:
+        self[k] = kwds[k]
 
 def setdefault_setObject_forKey_(self, key, dflt=None):
     try:
         it = self.keyEnumerator()
         k = container_unwrap(it.nextObject(), StopIteration)
     except (StopIteration, IndexError):
-        raise KeyError, "popitem on an empty %s" % (type(self).__name__,)
+        raise KeyError("popitem on an empty %s" % (type(self).__name__,))
     else:
         result = (k, container_unwrap(self.objectForKey_(k), KeyError))
         self.removeObjectForKey_(k)
 
 
 
-def objc_hash(self, _max=sys.maxint, _const=((sys.maxint + 1L) * 2L)):
+def objc_hash(self, _max=sys.maxsize, _const=((sys.maxsize + 1) * 2)):
     rval = self.hash()
     if rval > _max:
         rval -= _const
             if ln == 0:
                 raise ValueError("%s.index(x): x not in list" % (type(self).__name__,))
             
-            if ln > sys.maxint:
-                ln = sys.maxint
+            if ln > sys.maxsize:
+                ln = sys.maxsize
 
             res = self.indexOfObject_inRange_(item, (start, ln))
             if res == NSNotFound:
     ( 'insert', insert_insertObject_atIndex_),
 )
 
+if sys.version_info[0] == 2:
+    INT_TYPES = (int, long)
+
+else:
+    INT_TYPES = int
+
 def __getitem__objectAtIndex_(self, idx):
     if isinstance(idx, slice):
         start, stop, step = idx.indices(len(self))
         #        return m((start, stop - start))
         return [self[i] for i in xrange(start, stop, step)]
     
-    elif not isinstance(idx, (int, long)):
+    elif not isinstance(idx, INT_TYPES):
         raise TypeError("index must be a number")
     
     if idx < 0:
             if m is not None:
                 m((start, stop - start))
                 return
-        r = range(start, stop, step)
-        r.sort()
-        r.reverse()
+        r = reversed(range(start, stop, step))
         for i in r:
             self.removeObjectAtIndex_(i)
         return
                 toAssign = list(anObject)
             else:
                 toAssign = anObject
-            #for inIdx, outIdx in reversed(enumerate(reversed(range(start, stop, step)))):
             for inIdx, outIdx in enumerate(xrange(start, stop, step)): 
                 self.replaceObjectAtIndex_withObject_(outIdx, toAssign[inIdx])
 
 
-    elif not isinstance(idx, (int, long)):
+    elif not isinstance(idx, INT_TYPES):
         raise TypeError("index is not an integer")
 
     else:
     NSDictionary.items()
     """
     keys = aDict.allKeys()
-    return zip(keys, imap(aDict.__getitem__, keys))
-
-#CONVENIENCE_METHODS[b'allKeys'] = (
-#    ('keys', lambda self: self.allKeys()),
-#    ('items', lambda self: dictItems(self)),
-#)
-
-#CONVENIENCE_METHODS[b'allValues'] = (
-    #('values', lambda self: self.allValues()),
-#)
+    return zip(keys, map(aDict.__getitem__, keys))
 
 def itemsGenerator(aDict):
     for key in aDict:
 
 CONVENIENCE_METHODS[b'keyEnumerator'] = (
     ('__iter__', __iter__objectEnumerator_keyEnumerator),
-    ('iterkeys', lambda self: iter(self.keyEnumerator())),
-    ('iteritems', lambda self: itemsGenerator(self)),
+)
+if sys.version_info[0] == 2:
+    CONVENIENCE_METHODS[b'keyEnumerator'] += (
+        ('iterkeys', lambda self: iter(self.keyEnumerator())),
+        ('iteritems', lambda self: itemsGenerator(self)),
 )
 
 CONVENIENCE_METHODS[b'objectEnumerator'] = (
     ('__iter__', __iter__objectEnumerator_keyEnumerator),
-    ('itervalues', lambda self: iter(self.objectEnumerator())),
 )
 
+if sys.version_info[0] == 2:
+    CONVENIENCE_METHODS[b'objectEnumerator'] += (
+        ('itervalues', lambda self: iter(self.objectEnumerator())),
+    )
+
 CONVENIENCE_METHODS[b'reverseObjectEnumerator'] = (
     ('__reversed__', lambda self: iter(self.reverseObjectEnumerator())),
 )
         values = list(values)
     return cls.dictionaryWithObjects_forKeys_(values, keys)
 
-#CONVENIENCE_METHODS[b'dictionaryWithObjects:forKeys:'] = (
-    #('fromkeys',
-        #classmethod(fromkeys_dictionaryWithObjects_forKeys_)),
-#)
-
 if sys.version_info[0] == 3:
     def cmp(a, b):
         if a == b:
                         'callable': {
                             'reval': 'i',
                             'arguments': {
-                                0: { 'type': '@' },
-                                1: { 'type': '@' },
-                                2: { 'type': '@' },
+                                0: { 'type': b'@' },
+                                1: { 'type': b'@' },
+                                2: { 'type': b'@' },
                             }
                         },
                         'callable_retained': False,
                 },
-                3:  { 'type': '@' },
+                3:  { 'type': b'@' },
             },
         ))
 
         elif len(args) == 1:
             d = dict()
             if isinstance(args[0], collections.Mapping):
-                items = args[0].iteritems()
+                items = args[0].items()
             else:
                 items = args[0]
             for k , v in items:
                 d[container_wrap(k)] = container_wrap(v)
 
-            for k, v in kwds.iteritems():
+            for k, v in kwds.items():
                 d[container_wrap(k)] = container_wrap(v)
 
             return cls.dictionaryWithDictionary_(d)
                         len(args)))
         if kwds:
             d = dict()
-            for k, v in kwds.iteritems():
+            for k, v in kwds.items():
                 d[container_wrap(k)] = container_wrap(v)
 
             return cls.dictionaryWithDictionary_(d)
             n <<= 1
             tmp = tmp.arrayByAddingObjectsFromArray_(tmp)
 
-    #for n in xrange(other):
-        #result.extend(self)
     return result
 
 
     if not sequence:
         return NSArray.array()
 
-    elif isinstance(sequence, (str, unicode)):
+    elif isinstance(sequence, STR_TYPES):
         return NSArray.arrayWithArray_(list(sequence))
 
     else:
 
         return NSArray.arrayWithArray_(sequence)
 
+if sys.version_info[0] == 2:
+    STR_TYPES=(str, unicode)
+else:
+    STR_TYPES=str
+
 def nsmutablearray_new(cls, sequence=None):
     if not sequence:
         return NSMutableArray.array()
 
-    elif isinstance(sequence, (str, unicode)):
+    elif isinstance(sequence, STR_TYPES):
         return NSMutableArray.arrayWithArray_(list(sequence))
 
     else:
     def __iter__(self):
         return self
 
-    def next(self):
+    def __next__(self):
         self._size -= 1
         return container_unwrap(self._enum.nextObject(), StopIteration)
 
+    next = __next__
+
+
+
 
 CLASS_METHODS['NSSet'] = (
     ('__iter__', lambda self: nsset__iter__(self)),

File pyobjc-core/Lib/objc/_descriptors.py

View file
  • Ignore whitespace
 
 from objc._objc import ivar, selector, _makeClosure, selector, _C_SEL, _C_ID
 import sys, textwrap
+import warnings
+from inspect import getargspec
 
 #
 # Interface builder support.
     Return an Objective-C method object that is conformant with key-value coding
     and key-value observing.
     """
-
-    from inspect import getargspec
     args, varargs, varkw, defaults = getargspec(func)
     funcName = func.__name__
     maxArgs = len(args)
         return selector(func, signature=b"v@:" + typeSignature)
 
     elif selArgs == 1:
-        if typeSignature == b'@' and func.func_name.startswith('countOf'):
+        if typeSignature == b'@' and func.__name__.startswith('countOf'):
             typeSignature = 'i'
 
         return selector(func, signature=typeSignature + b"@:")
     return _namedselector
 
 def namedselector(name, signature=None):
-    import warnings
     warnings.warn("use objc.namedSelector instead of objc.namedselector", stacklevel=2)
     return namedSelector(name, signature)
 
     return _typedAccessor
 
 def Accessor(func):
-    import warnings
     warnings.warn(
         "Use objc.accessor instead of objc.Accessor", DeprecationWarning)
     return accessor(func)
             ''' % dict(name=name, ivar=ivarName))
 
     if readwrite:
-        exec setter in classDict
+        exec(setter, globals(), classDict)
 
-    exec getter in classDict
+    exec(getter, globals(), classDict)
 
     classDict[ivarName] = ivar(type=type)

File pyobjc-core/Lib/objc/_dyld.py

View file
  • Ignore whitespace
 
 # These are the defaults as per man dyld(1)
 #
-DEFAULT_FRAMEWORK_FALLBACK = u':'.join([
-    os.path.expanduser(u"~/Library/Frameworks"),
-    u"/Library/Frameworks",
-    u"/Network/Library/Frameworks",
-    u"/System/Library/Frameworks",
+DEFAULT_FRAMEWORK_FALLBACK = ':'.join([
+    os.path.expanduser("~/Library/Frameworks"),
+    "/Library/Frameworks",
+    "/Network/Library/Frameworks",
+    "/System/Library/Frameworks",
 ])
 
-DEFAULT_LIBRARY_FALLBACK = u':'.join([
-    os.path.expanduser(u"~/lib"),
-    u"/usr/local/lib",
-    u"/lib",
-    u"/usr/lib",
+DEFAULT_LIBRARY_FALLBACK = ':'.join([
+    os.path.expanduser("~/lib"),
+    "/usr/local/lib",
+    "/lib",
+    "/usr/lib",
 ])
 
 def ensure_unicode(s):
         return iterator
     def _inject(iterator=iterator,suffix=suffix):
         for path in iterator:
-            if path.endswith(u'.dylib'):
-                yield path[:-6] + suffix + u'.dylib'
+            if path.endswith('.dylib'):
+                yield path[:-6] + suffix + '.dylib'
             else:
                 yield path + suffix
             yield path
     def _search():
         spath = ensure_unicode(os.environ.get('DYLD_FRAMEWORK_PATH', None))
         if spath is not None:
-            for path in spath.split(u':'):
+            for path in spath.split(':'):
                 if version:
                     yield os.path.join(
-                        path, framework_name + u'.framework',
-                        u'Versions', version, framework_name
+                        path, framework_name + '.framework',
+                        'Versions', version, framework_name
                     )
                 else:
                     yield os.path.join(
-                        path, framework_name + u'.framework', framework_name
+                        path, framework_name + '.framework', framework_name
                     )
         yield filename
         spath = ensure_unicode(os.environ.get(
             'DYLD_FALLBACK_FRAMEWORK_PATH', DEFAULT_FRAMEWORK_FALLBACK
         ))
-        for path in spath.split(u':'):
+        for path in spath.split(':'):
             if version:
                 yield os.path.join(
-                    path, framework_name + u'.framework', u'Versions',
+                    path, framework_name + '.framework', 'Versions',
                     version, framework_name
                 )
             else:
                 yield os.path.join(
-                    path, framework_name + u'.framework', framework_name
+                    path, framework_name + '.framework', framework_name
                 )
 
 
     def _search():
         spath = ensure_unicode(os.environ.get('DYLD_LIBRARY_PATH', None))
         if spath is not None:
-            for path in spath.split(u':'):
+            for path in spath.split(':'):
                 yield os.path.join(path, libname)
         yield filename
         spath = ensure_unicode(os.environ.get(
             'DYLD_FALLBACK_LIBRARY_PATH', DEFAULT_LIBRARY_FALLBACK
         ))
-        for path in spath.split(u':'):
+        for path in spath.split(':'):
             yield os.path.join(path, libname)
     for f in injectSuffixes(_search()):
         if os.path.exists(f):
             return f
-    raise ValueError, "dylib %s could not be found" % (filename,)
+    raise ValueError("dylib %s could not be found" %(filename,))
 
 # Python version upto (at least) 2.5 do not propertly convert unicode
 # arguments to os.readlink, the code below works around that.
 
 def pathForFramework(path):
     fpath, name, version = infoForFramework(dyld_find(path))
-    return os.path.join(fpath, name + u'.framework')
+    return os.path.join(fpath, name + '.framework')

File pyobjc-core/Lib/objc/_framework.py

View file
  • Ignore whitespace
 #   \2 - framework name
 #   \3 - framework version (optional)
 #
-FRAMEWORK_RE_STR = ur"""(^.*)(?:^|/)(\w+).framework(?:/(?:Versions/([^/]+)/)?\2)?$"""
+FRAMEWORK_RE_STR = r"""(^.*)(?:^|/)(\w+).framework(?:/(?:Versions/([^/]+)/)?\2)?$"""
 FRAMEWORK_RE = None
 
 def infoForFramework(filename):

File pyobjc-core/Lib/objc/_lazyimport.py

View file
  • Ignore whitespace
                     return d[name]
 
                 if self.__inlinelist is not None:
-                    objc._loadFunctionList(
+                    try:
+                        objc._loadFunctionList(
                             self.__inlinelist, d, func_list, skip_undefined=False)
-                    if name in d:
-                        return d[name]
+                    except objc.error:
+                        pass
+
+                    else:
+                        if name in d:
+                            return d[name]
 
         if self.__expressions:
             if name in self.__expressions:

File pyobjc-core/Lib/objc/_properties.py

View file
  • Ignore whitespace
 NSSet = lookUpClass('NSSet')
 NSObject = lookUpClass('NSObject')
 
+if sys.version_info[0] == 2:
+    range = xrange
+
 
 def attrsetter(prop, name, copy):
     if copy:
         if isinstance(index, slice):
             result = NSMutableIndexSet.alloc().init()
             start, stop, step = index.indices(len(self._wrapped))
-            for i in xrange(start, stop, step):
+            for i in range(start, stop, step):
                 result.addIndex_(i)
 
             return result

File pyobjc-core/Lib/objc/_protocols.py

View file
  • Ignore whitespace
 from objc import _objc
+import sys
 
 __all__ = ['protocolNamed', 'ProtocolError']
 
     equivalent of @protocol(name) in Objective-C.
     Raises objc.ProtocolError when the protocol does not exist.
     """
-    name = unicode(name)
+    if sys.version_info[0] == 2:
+        name = unicode(name)
     try:
         return PROTOCOL_CACHE[name]
     except KeyError:

File pyobjc-core/Lib/objc/_pycoder.py

View file
  • Ignore whitespace
 object itself, which is why we need a 'setValue' callback for the
 load_* functions below.
 """
+from __future__ import unicode_literals
 import sys
 import objc
 from types import *
-import copy_reg
+
+try:
+    import copyreg
+except ImportError:
+    # Python 2.x
+    import copy_reg as copyreg
 import copy
 
 from pickle import PicklingError, UnpicklingError, whichmodule
 if hasattr(sys, 'intern'):
     intern = sys.intern
 
+if sys.version_info[0] == 3:
+    unicode = str
+    long = int
+
 
 # FIXME: This requires manual wrappers from the Foundation bindings
 def setupPythonObject():
     kOP_GLOBAL_EXT=13
     kOP_FLOAT_STR=14
 
-    kKIND = NSString.stringWithString_(u"kind")
-    kFUNC = NSString.stringWithString_(u"func")
-    kARGS = NSString.stringWithString_(u"args")
-    kLIST = NSString.stringWithString_(u"list")
-    kDICT = NSString.stringWithString_(u"dict")
-    kSTATE = NSString.stringWithString_(u"state")
-    kCLASS = NSString.stringWithString_(u"class")
-    kVALUE = NSString.stringWithString_(u"value")
-    kNAME = NSString.stringWithString_(u"name")
-    kMODULE = NSString.stringWithString_(u"module")
-    kCODE = NSString.stringWithString_(u"code")
+    kKIND = NSString.stringWithString_("kind")
+    kFUNC = NSString.stringWithString_("func")
+    kARGS = NSString.stringWithString_("args")
+    kLIST = NSString.stringWithString_("list")
+    kDICT = NSString.stringWithString_("dict")
+    kSTATE = NSString.stringWithString_("state")
+    kCLASS = NSString.stringWithString_("class")
+    kVALUE = NSString.stringWithString_("value")
+    kNAME = NSString.stringWithString_("name")
+    kMODULE = NSString.stringWithString_("module")
+    kCODE = NSString.stringWithString_("code")
 
     class _EmptyClass:
         pass
         encode_dispatch[int] = save_int
 
         def save_long(coder, obj):
+            encoded = unicode(repr(obj))
+            if encoded.endswith('L'):
+                encoded = encoded[:-1]
             if coder.allowsKeyedCoding():
                 coder.encodeInt_forKey_(kOP_LONG, kKIND)
-                coder.encodeObject_forKey_(unicode(repr(obj)), kVALUE)
+                coder.encodeObject_forKey_(encoded, kVALUE)
             else:
                 coder.__pyobjc__encodeInt_(kOP_LONG)
-                coder.encodeObject_(unicode(repr(obj)))
+                coder.encodeObject_(encoded)
 
         encode_dispatch[long] = save_long
 
                     "Can't pickle %r: it's not the same object as %s.%s" %
                     (obj, module, name))
 
-        code = copy_reg._extension_registry.get((module, name))
+        code = copyreg._extension_registry.get((module, name))
 
         if coder.allowsKeyedCoding():
             if code:
         else:
             code = coder.__pyobjc__decodeInt()
         nil = []
-        obj = copy_reg._extension_cache.get(code, nil)
+        obj = copyreg._extension_cache.get(code, nil)
         if obj is not nil:
             return obj
-        key = copy_reg._inverted_registry.get(code)
+        key = copyreg._inverted_registry.get(code)
         if not key:
             raise ValueError("unregistered extension code %d" % code)
 
         if not instantiated:
             try:
                 value = cls(*initargs)
-            except TypeError, err:
-                raise TypeError, "in constructor for %s: %s" % (
-                    cls.__name__, str(err)), sys.exc_info()[2]
+            except TypeError as err:
+                raise TypeError("in constructor for %s: %s" % (
+                    cls.__name__, str(err)), sys.exc_info()[2])
 
             
         # We now have the object, but haven't set the correct
         if state:
             try:
                 inst_dict = value.__dict__
-                for k, v in state.iteritems():
+                for k in state:
+                    v = state[k]
                     if type(k) == str:
                         inst_dict[intern(k)] = v
                     else:
             try:
                 inst_dict = value.__dict__
 
-                for k, v in state.iteritems():
+                for k in state:
+                    v = state[k]
                     if type(k) == str:
                         inst_dict[intern(k)] = v
                     else:
             save_global(coder, self)
             return
 
-        # Check copy_reg.dispatch_table
-        reduce = copy_reg.dispatch_table.get(t)
+        # Check copyreg.dispatch_table
+        reduce = copyreg.dispatch_table.get(t)
         if reduce is not None:
             rv = reduce(self)
 

File pyobjc-core/Lib/objc/_pythonify.py

View file
  • Ignore whitespace
         # one part of the effect of __slots__: don't allow setting of attributes.
         def __setattr__(self, attr, value):
             if attr != '__pyobjc_object__':
-                raise AttributeError, "'%s' object has no attribute '%s')"%(self.__class__.__name__, attr)
+                raise AttributeError("'%s' object has no attribute '%s')"%(self.__class__.__name__, attr))
             self.__dict__['__pyobjc_object__'] = value
 
         def __reduce__(self):
     class OC_PythonLong(int):
 
         def __new__(cls, obj, value):
-            self = long.__new__(cls, value)
+            self = int.__new__(cls, value)
             self.__pyobjc_object__ = obj
             return self
 
         # one part of the effect of __slots__: don't allow setting of attributes.
         def __setattr__(self, attr, value):
             if attr != '__pyobjc_object__':
-                raise AttributeError, "'%s' object has no attribute '%s')"%(self.__class__.__name__, attr)
+                raise AttributeError("'%s' object has no attribute '%s')"%(self.__class__.__name__, attr))
             self.__dict__['__pyobjc_object__'] = value
 
-        def __reduce__(self):
-            return (long, (long(self),))
+        if sys.version_info[0] == 2:
+            def __reduce__(self):
+                return (long, (long(self),))
+        else:
+            def __reduce__(self):
+                return (int, (int(self),))
 
 NSNumber = _objc.lookUpClass('NSNumber')
 NSDecimalNumber = _objc.lookUpClass('NSDecimalNumber')

File pyobjc-core/Modules/objc/OC_PythonUnicode.m

View file
  • Ignore whitespace
 			length:(NSUInteger)length 
 		  freeWhenDone:(BOOL)flag
 {
-#ifndef PyObjC_UNICODE_FAST_PATH
-# error "Wide UNICODE builds are not supported at the moment"
-#endif
+	int byteorder = 0;
 	PyObjC_BEGIN_WITH_GIL
-		value = PyUnicode_FromUnicode((Py_UNICODE*)characters, length);
+		/* Decode as a UTF-16 string in native byteorder */
+		value = PyUnicode_DecodeUTF16(
+				(const char*)characters,
+				length * 2,
+				NULL,
+				&byteorder); 
 		if (value == NULL) {
 			PyObjC_GIL_FORWARD_EXC();
 		}
 
 -initWithBytes:(void*)bytes length:(NSUInteger)length encoding:(NSStringEncoding)encoding
 {
-#ifndef PyObjC_UNICODE_FAST_PATH
-# error "Wide UNICODE builds are not supported at the moment"
-#endif
+	char* py_encoding = NULL;
+	int byteorder = 0;
+
+	/* Detect some often used single-byte encodings that can be created in Python without
+	 * creating an intermediate object.
+	 */
+
+	switch (encoding) {
+	case NSASCIIStringEncoding: py_encoding = "ascii"; break;
+	case NSUTF8StringEncoding: py_encoding = "UTF-8"; break;
+	case NSISOLatin1StringEncoding: py_encoding = "latin1"; break;
+	}
+
+	if (py_encoding != NULL) {
+		PyObjC_BEGIN_WITH_GIL
+			value = PyUnicode_Decode(bytes, length, py_encoding, NULL);
+			if (value == NULL) {
+				PyObjC_GIL_FORWARD_EXC();
+			}
+		PyObjC_END_WITH_GIL
+		return self;
+	}
+
+	/* UTF-16 encodings can also be decoded without an intermediate object */
+	byteorder = 2;
+	switch (encoding) {
+	case NSASCIIStringEncoding: byteorder = 0; break;
+	case NSUTF8StringEncoding:  byteorder = -1; break;
+	case NSISOLatin1StringEncoding:  byteorder = 1; break;
+	}
+	if (byteorder != 2) {
+		PyObjC_BEGIN_WITH_GIL
+			/* Decode as a UTF-16 string in native byteorder */
+			value = PyUnicode_DecodeUTF16(
+					bytes,
+					length,
+					NULL,
+					&byteorder); 
+			if (value == NULL) {
+				PyObjC_GIL_FORWARD_EXC();
+			}
+
+		PyObjC_END_WITH_GIL;
+		return self;
+	}
+
+	/* And finally: first use the Cocoa decoder to create an NSString, copy the unichars into
+	 * a temporary buffer and use that to create a Python unicode string using the UTF16 decoder.
+	 *
+	 * This can be slightly optimized on systems where sizeof(Py_UNICODE) == sizeof(unichar), but
+	 * that's not worth the additional complexity and won't work on Python 3.3 or later anyway.
+	 */
+
 	NSString* tmpval = [[NSString alloc] initWithBytes:bytes length:length encoding:encoding];
 	Py_ssize_t charcount = [tmpval length];
 
+	/* NOTE: the malloc() call can be avoided when sizeof(unichar) == sizeof(Py_UNICODE) and
+	 * we're on python 3.2 or earlier. That's not worth the added complexity.
+	 */
+	unichar* chars = malloc(charcount*2);
+
+	if (chars == NULL) {
+		[self release];
+		return nil;
+	}
+	[tmpval getCharacters:chars];
+	[tmpval release];
 
 	PyObjC_BEGIN_WITH_GIL
-		value = PyUnicode_FromUnicode(NULL, charcount);
+		/* Decode as a UTF-16 string in native byteorder */
+		byteorder = 0;
+		value = PyUnicode_DecodeUTF16(
+				(const char*)chars,
+				length * 2,
+				NULL,
+				&byteorder); 
+		free(chars);
 		if (value == NULL) {
 			PyObjC_GIL_FORWARD_EXC();
 		}
-		[tmpval getCharacters:PyUnicode_AS_UNICODE(value)];
 
 	PyObjC_END_WITH_GIL;
-	[tmpval release];
 	return self;
 }
 

File pyobjc-core/Modules/objc/ObjCPointer.h

View file
  • Ignore whitespace
   char contents[1];
 } PyObjCPointer;
 
+extern int	PyObjCPointer_RaiseException;
+
 extern PyTypeObject PyObjCPointer_Type;
 
 #define PyObjCPointer_Check(o) (Py_TYPE(o) == &PyObjCPointer_Type)

File pyobjc-core/Modules/objc/ObjCPointer.m

View file
  • Ignore whitespace
 
 #include "pyobjc.h"
 
+int PyObjCPointer_RaiseException = 0;
+
 static void
 PyObjCPointer_dealloc (PyObject* _self)
 {
 	const char *typeend = PyObjCRT_SkipTypeSpec (t);
 	PyObjCPointer *self;
 
+	if (PyObjCPointer_RaiseException) {
+		PyErr_Format(PyObjCExc_UnknownPointerError,
+			"pointer of type %s", t);
+		return NULL;
+	}
 	NSLog(@"PyObjCPointer created: at %p of type %s", p, t);
 
 	if (size == -1) {

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

View file
  • Ignore whitespace
 		doc = NULL;
 		if (!PyArg_ParseTuple(item, 
 #if PY_MAJOR_VERSION == 2
-					"O!s|SO:functionInfo tuple", &PyBaseString_Type, 
+					"O!s|O!O:functionInfo tuple", &PyBaseString_Type, 
 
 #else
-					"Uy|UO:functionInfo tuple", 
+					"Uy|O!O:functionInfo tuple", 
 #endif
-				&name, &signature, &doc, &meta)){
+				&name, &signature, 
+#if PY_MAJOR_VERSION == 2
+				&PyBaseString_Type,
+#else
+				&PyUnicode_Type,
+#endif
+
+				&doc, &meta)){
 			Py_DECREF(seq);
 			return NULL;
 		}

File pyobjc-core/Modules/objc/libffi_support.m

View file
  • Ignore whitespace
 	if (rv != FFI_OK) {
 		PyMem_Free(cl_arg_types);
 		PyErr_Format(PyExc_RuntimeError,
-			"Cannot create FFI CIF: err=%d signature=%s", rv, PyObject_REPR(methinfo));
+			"Cannot create FFI CIF: err=%d", rv);
 		return NULL;
 	}
 

File pyobjc-core/Modules/objc/module.m

View file
  • Ignore whitespace
 	char* class_name = NULL;
 	Class objc_class;
 
-	if (!PyArg_ParseTupleAndKeywords(args, kwds, "s:lookUpClass",
+	if (!PyArg_ParseTupleAndKeywords(args, kwds, "s",
 			keywords, &class_name)) {
 		return NULL;
 	}
 }
 
 
+PyDoc_STRVAR(setObjCPointerIsError_doc,
+	"setObjCPointerIsError(bool) -> None\n"
+	"\n"
+	"If the argument is True PyObjC will raise an exception when it tries to wrap a C pointer it doesn't know about."
+);
+static PyObject* 
+setObjCPointerIsError(PyObject* self __attribute__((__unused__)), PyObject* args, PyObject* kwds)
+{
+static 	char* keywords[] = { "value", NULL };
+	PyObject* o;
+
+	if (!PyArg_ParseTupleAndKeywords(args, kwds, "O",
+			keywords, &o)) {
+		return NULL;
+	}
+
+	PyObjCPointer_RaiseException = PyObject_IsTrue(o);
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
 PyDoc_STRVAR(setVerbose_doc,
 	"setVerbose(bool) -> None\n"
 	"\n"
 	return PyBool_FromLong(PyObjC_VerboseLevel);
 }
 
+PyDoc_STRVAR(getObjCPointerIsError_doc,
+	"getObjCPointerIsError() -> bool\n"
+	"\n"
+	"Returns True if PyObjC raises an exception when it tries to wrap a pointer it doesn't know about."
+);
+static PyObject* 
+getObjCPointerIsError(PyObject* self __attribute__((__unused__)), PyObject* args, PyObject* kwds)
+{
+static 	char* keywords[] = { NULL };
+
+	if (!PyArg_ParseTupleAndKeywords(args, kwds, "",
+			keywords)) {
+		return NULL;
+	}
+
+	return PyBool_FromLong(PyObjCPointer_RaiseException);
+}
+
 
 PyDoc_STRVAR(allocateBuffer_doc,
 	     "allocateBuffer(size) -> <r/w buffer>\n"
 	{ "_setNSNumberWrapper", (PyCFunction)setNSNumberWrapper, METH_VARARGS|METH_KEYWORDS, setNSNumberWrapper_doc },
 	{ "_getNSNumberWrapper", (PyCFunction)getNSNumberWrapper, METH_VARARGS|METH_KEYWORDS, getNSNumberWrapper_doc },
 	{ "setVerbose", (PyCFunction)setVerbose, METH_VARARGS|METH_KEYWORDS, setVerbose_doc },
+	{ "setObjCPointerIsError", (PyCFunction)setObjCPointerIsError, METH_VARARGS|METH_KEYWORDS, setObjCPointerIsError_doc },
 	{ "setUseKVOForSetattr", (PyCFunction)setUseKVOForSetattr, METH_VARARGS|METH_KEYWORDS, setUseKVOForSetattr_doc },
 	{ "setHideProtected", (PyCFunction)setHideProtected, METH_VARARGS|METH_KEYWORDS, setHideProtected_doc },
 	{ "getVerbose", (PyCFunction)getVerbose, METH_VARARGS|METH_KEYWORDS, getVerbose_doc },
+	{ "getObjCPointerIsError", (PyCFunction)getObjCPointerIsError, METH_VARARGS|METH_KEYWORDS, getObjCPointerIsError_doc },
 	{ "pyobjc_id", (PyCFunction)pyobjc_id, METH_VARARGS|METH_KEYWORDS, pyobjc_id_doc },
 	{ "repythonify", (PyCFunction)repythonify, METH_VARARGS|METH_KEYWORDS, repythonify_doc },
 #if PY_MAJOR_VERSION == 2

File pyobjc-core/Modules/objc/objc_support.m

View file
  • Ignore whitespace
 		return NULL;
 	}
 	if (*type == _C_UNICHAR) {
-		return PyUnicode_FromUnicode((Py_UNICODE*)datum, count);
+		int byteorder = 0;
+		return PyUnicode_DecodeUTF16(
+			(const char*)datum,
+			count * 2,
+			NULL,
+			&byteorder);
 	}
 
 	return  PyObjC_CArrayToPython2(type, datum, count, alreadyRetained, alreadyCFRetained);
 	switch (*type) {
 	case _C_UNICHAR:
 		{
-			Py_UNICODE	c  = (Py_UNICODE)(*(UniChar*)datum);
-			retobject = PyUnicode_FromUnicode(&c, 1);
+			int byteorder = 0;
+			retobject =  PyUnicode_DecodeUTF16(
+				(const char*)datum,
+				2,
+				NULL,
+				&byteorder);
 		}
 		break;
 
 
 	case _C_UNICHAR:
 		{
-			Py_UNICODE ch = *(int*)datum;
-			return PyUnicode_FromUnicode(&ch, 1);
+			int byteorder = 0;
+			unichar ch = *(int*)datum;
+			return PyUnicode_DecodeUTF16(
+					(const char*)&ch, 2, NULL, ^byteorder);
+																	                                &byteorder);
 		}
 
 	default:

File pyobjc-core/Modules/objc/objc_util.h

View file
  • Ignore whitespace
 extern PyObject* PyObjCExc_ObjCRevivalWarning;
 extern PyObject* PyObjCExc_LockError;
 extern PyObject* PyObjCExc_BadPrototypeError;
+extern PyObject* PyObjCExc_UnknownPointerError;
 
 int PyObjCUtil_Init(PyObject* module);
 

File pyobjc-core/Modules/objc/objc_util.m

View file
  • Ignore whitespace
 PyObject* PyObjCExc_ObjCRevivalWarning;
 PyObject* PyObjCExc_LockError;
 PyObject* PyObjCExc_BadPrototypeError;
+PyObject* PyObjCExc_UnknownPointerError;
 
 
 
 	NEW_EXC(PyObjCExc_ObjCRevivalWarning, "RevivedObjectiveCObjectWarning", PyExc_Warning);
 	NEW_EXC(PyObjCExc_LockError, "LockError", PyObjCExc_Error);
 	NEW_EXC(PyObjCExc_BadPrototypeError, "BadPrototypeError", PyObjCExc_Error);
+	NEW_EXC(PyObjCExc_UnknownPointerError, "UnknownPointerError", PyObjCExc_Error);
 
 	return 0;
 }
 	}
 
 	if (*elementType == _C_UNICHAR) {
-#if defined(PyObjC_UNICODE_FAST_PATH)
-		result = PyUnicode_FromUnicode((Py_UNICODE*)array, size);
-#else
-#		error "Sorry, Wide Unicode builds not supported at the moment"	
-#endif			
+		int byteorder = 0;
+		result = PyUnicode_DecodeUTF16(array, size*2, NULL, &byteorder);
 		return result;
 	}
 
 		}
 	}
 	if (*elementType == _C_UNICHAR) {
-#if defined(PyObjC_UNICODE_FAST_PATH)
-		result = PyUnicode_FromUnicode((Py_UNICODE*)array, size);
-#else
-#		error "Sorry, Wide Unicode builds not supported at the moment"	
-#endif			
+		int byteorder = 0;
+		result = PyUnicode_DecodeUTF16(array, size*2, NULL, &byteorder);
 		return result;
 	}
 

File pyobjc-core/Modules/objc/pyobjc.h

View file
  • Ignore whitespace
 #include <objc/objc-runtime.h>
 #include <objc/objc.h>
 
-// how do we make this dependent on sizeof(unichar)??
-#if Py_UNICODE_SIZE == 2
+/* Define PyObjC_UNICODE_FAST_PATH when
+ * 1) We're before Python 3.3, and
+ * 2) Py_UNICODE has the same size as unichar
+ *
+ * Python 3.3 has an optimized representation that
+ * makes it impossible to use the "fast path"
+ */
+#if PY_VERSION_HEX >= 0x03030000
+#undef PyObjC_UNICODE_FAST_PATH
+#elif Py_UNICODE_SIZE == 2
 #define PyObjC_UNICODE_FAST_PATH
 #else
 #error "Py_UNICODE_SIZE != 2 is not supported"

File pyobjc-core/Modules/objc/struct-wrapper.m

View file
  • Ignore whitespace
 		PyObject* result;
 		PyObject* it;
 
-		if (PySlice_GetIndicesEx((PySliceObject*)item, 
+		if (PySlice_GetIndicesEx(item, 
 				struct_sq_length(self),
 				&start, &stop, &step, &slicelength) < 0) {
 			return NULL;
 	} else if (PySlice_Check(item)) {
 		Py_ssize_t start, stop, step, slicelength;
 
-		if (PySlice_GetIndicesEx((PySliceObject*)item, 
+		if (PySlice_GetIndicesEx(item, 
 				struct_sq_length(self), &start, &stop,
 				&step, &slicelength) < 0) {
 			return -1;

File pyobjc-core/Modules/objc/unicode-object.m

View file
  • Ignore whitespace
 
 };
 
+
+#if PY_VERSION_HEX >= 0x03030000
+   /* 
+    * Python 3.3 introduced a new, more efficient representation
+    * for unicode objects. 
+    *
+    * This function cannot use the most efficient
+    * representation where the character data is stored in the same
+    * memory block as the object header because PyObjCUnicode adds
+    * more data to the object header, which PyUnicode does not
+    * expect.
+    *
+    * This function therefore creates a "legacy string, ready" (see
+    * unicodeobject.h in the python 3.3 source tree for more information)
+    *
+    *
+    * XXX: I'm not very happy about this implementation, it is too verbose
+    *      and seems to be even more fragile than the implementation for
+    *      older python versions.
+    */
+PyObject* 
+PyObjCUnicode_New(NSString* value)
+{
+	PyObjCUnicodeObject* result;
+        PyASCIIObject *ascii;
+        PyCompactUnicodeObject *compact;
+
+	NSInteger i, length;
+	unichar* volatile characters = NULL;
+	NSRange range;
+
+	PyObjC_DURING
+		length = [value length];
+		characters = PyObject_MALLOC(sizeof(unichar) * (length+1));
+		if (characters == NULL) {
+			PyErr_NoMemory();
+			NS_VALUERETURN(NULL, PyObject*);
+		}
+
+		range = NSMakeRange(0, length);
+
+		[value getCharacters: characters range: range];
+		characters[length] = 0;
+
+	PyObjC_HANDLER
+		if (characters) {
+			PyMem_Free(characters);
+			characters = NULL;
+		}
+		PyObjCErr_FromObjC(localException);
+		NS_VALUERETURN(NULL, PyObject*);
+	PyObjC_ENDHANDLER
+
+	result = PyObject_New(PyObjCUnicodeObject, &PyObjCUnicode_Type);
+	ascii = (PyASCIIObject*)result;
+	compact = (PyCompactUnicodeObject*)result;
+
+	ascii->hash = -1;
+	ascii->wstr = NULL;
+	ascii->length = length;
+
+	ascii->state.compact = 0;
+	ascii->state.ready = 1;
+	ascii->state.interned = SSTATE_NOT_INTERNED;
+
+	compact->utf8_length = 0;
+	compact->utf8 = NULL;
+	compact->wstr_length = 0;
+
+	result->base.data.any = NULL;
+
+	Py_UCS4 maxchar = 0;
+	int nr_surrogates = 0;
+	for (i = 0; i < length; i++) {
+		Py_UCS4 cur = (Py_UCS4)characters[i];
+		if (Py_UNICODE_IS_HIGH_SURROGATE(cur) && (
+			i < length - 1) && (
+			Py_UNICODE_IS_LOW_SURROGATE(characters[i+1]))) {
+			Py_UCS4 ch = Py_UNICODE_JOIN_SURROGATES(
+				characters[i],
+				characters[i+1]);
+			i++;
+			nr_surrogates++;
+			if (ch > maxchar) {
+				maxchar = ch;
+			}
+		} else if (cur > maxchar) {
+			maxchar = cur;
+		}
+	}
+	if (maxchar <= 128) {
+		ascii->state.ascii = 1; 
+		ascii->state.kind = PyUnicode_1BYTE_KIND;
+	} else if (maxchar <= 255) {
+		ascii->state.ascii = 0; 
+		ascii->state.kind = PyUnicode_1BYTE_KIND;
+	} else if (maxchar <= 0xFFFF) {
+		ascii->state.ascii = 0; 
+		ascii->state.kind = PyUnicode_2BYTE_KIND;
+	} else {
+		ascii->state.ascii = 0; 
+		ascii->state.kind = PyUnicode_4BYTE_KIND;
+	}
+
+	/* Create storage for the code points and copy the data */
+	result->base.data.any = NULL;
+	if (ascii->state.kind == PyUnicode_1BYTE_KIND) {
+		result->base.data.latin1 = PyObject_MALLOC(sizeof(Py_UCS1) * (length + 1 - nr_surrogates));
+		if (result->base.data.latin1 == NULL) {
+			Py_DECREF((PyObject*)result);
+			PyMem_Free(characters); characters = NULL;
+			PyErr_NoMemory();
+			return NULL;
+		}
+		Py_UCS1* latin1_cur = result->base.data.latin1;
+		for (i = 0; i < length; i++) {
+			if (Py_UNICODE_IS_HIGH_SURROGATE(characters[i]) && (
+				i < length - 1) && (
+				Py_UNICODE_IS_LOW_SURROGATE(characters[i+1]))) {
+				Py_UCS4 ch = Py_UNICODE_JOIN_SURROGATES(
+					characters[i],
+					characters[i+1]);
+				*latin1_cur++ =  (Py_UCS1)ch;
+				i++;
+			} else {
+				*latin1_cur++ =  (Py_UCS1)characters[i];
+			}
+		}
+		*latin1_cur = 0;
+		ascii->length = length - nr_surrogates;
+		if (ascii->state.ascii) {
+			/* With ASCII representation the UTF8 representation is 
+			 * also known without further calculation, and MUST be
+			 * filled according to the spec
+			 */
+			compact->utf8_length = length - nr_surrogates;
+			compact->utf8 = (char*)result->base.data.latin1;
+		}
+
+	} else if (ascii->state.kind == PyUnicode_2BYTE_KIND) {
+		if (nr_surrogates == 0) {
+			/* No surrogates and 2BYTE_KIND, this means the unichar buffer 
+			 * can be reused as storage for the python unicode string
+			 */
+			ascii->length = length;
+			result->base.data.ucs2 = (Py_UCS2*)characters;
+			characters = NULL;
+
+		} else {
+			result->base.data.ucs2 = PyObject_MALLOC(sizeof(Py_UCS2) * (length + 1 - nr_surrogates));
+			if (result->base.data.ucs2 == NULL) {
+				Py_DECREF((PyObject*)result);
+				PyMem_Free(characters); characters = NULL;
+				PyErr_NoMemory();
+				return NULL;
+			}
+			Py_UCS2* ucs2_cur = result->base.data.ucs2;
+			for (i = 0; i < length; i++) {
+				if (Py_UNICODE_IS_HIGH_SURROGATE(characters[i]) && (
+					i < length - 1) && (
+					Py_UNICODE_IS_LOW_SURROGATE(characters[i+1]))) {
+					Py_UCS4 ch = Py_UNICODE_JOIN_SURROGATES(
+						characters[i],
+						characters[i+1]);
+					*ucs2_cur++ =  (Py_UCS2)ch;
+					i++;
+				} else {
+					*ucs2_cur++ =  (Py_UCS2)characters[i];
+				}
+			}
+			ascii->length = length - nr_surrogates;
+			*ucs2_cur = 0;
+		}
+
+	} else { /* 4BYTE_KIND */
+		result->base.data.ucs4 = PyObject_MALLOC(sizeof(Py_UCS4) * (length + 1 - nr_surrogates));
+		if (result->base.data.ucs4 == NULL) {
+			Py_DECREF((PyObject*)result);
+			PyMem_Free(characters); characters = NULL;
+			PyErr_NoMemory();
+			return NULL;
+		}
+
+		Py_UCS4* ucs4_cur = result->base.data.ucs4;
+		for (i = 0; i < length; i++) {
+			if (Py_UNICODE_IS_HIGH_SURROGATE(characters[i]) && (
+				i < length - 1) && (
+				Py_UNICODE_IS_LOW_SURROGATE(characters[i+1]))) {
+				Py_UCS4 ch = Py_UNICODE_JOIN_SURROGATES(
+					characters[i],
+					characters[i+1]);
+
+				if (ch > 0x10ffff) {
+					/* Unicode spec has a maximum code point value and
+					 * Python 3.3 enforces this, keep surrogate pair 
+					 * to avoid an error.
+					 */
+					*ucs4_cur++ =  (Py_UCS4)characters[i];
+				} else {
+					*ucs4_cur++ =  (Py_UCS4)ch;
+					i++;
+				}
+			} else {
+				*ucs4_cur++ =  (Py_UCS4)characters[i];
+			}
+		}
+		*ucs4_cur = 0;
+		ascii->length = length - nr_surrogates;
+	}
+
+
+	if (characters != NULL) {
+		PyObject_DEL(characters); 
+		characters = NULL;
+	}
+
+
+#ifdef Py_DEBUG
+	/* Check that the unicode object is correct */
+	_PyUnicode_CheckConsistency((PyObject*)result, 1);
+#endif
+
+	/* Finally store PyUnicode specific data */
+	result->weakrefs = NULL;
+	result->py_nsstr = NULL;
+	result->nsstr = value;
+	CFRetain(value);
+
+	return (PyObject*)result;
+}
+
+#else /* Python 3.2 and before */
 PyObject* 
 PyObjCUnicode_New(NSString* value)
 {
 
 	return (PyObject*)result;
 }
+#endif /* Python 3.2 and before */
 
 NSString*
 PyObjCUnicode_Extract(PyObject* value)

File pyobjc-core/NEWS.txt

View file
  • Ignore whitespace
 Version 2.4  (or 3.0)
 ---------------------
 
+- Updated Python support. With this release PyObjC supports Python 2.6 and later,
+  including Python 3.3 (which has a completely new representation for unicode strings)
+
+  NOTE: Support for 3.3 is very much work in progress right now, there have
+  been changes for the new unicode representation, but more changes are required.
+  
+
+- Add ``objc.setObjCPointerIsError`` and ``objc.getObjCPointerIsError``.
+  
+  By default PyObjC will create a ``PyObjCPointer`` object when it tries
+  to convert a pointer it doesn't know about to Python. These values are
+  fairly useless and obvious an indication that an API is wrapped improperly.
+
+  With ``objc.setObjCPointerIsError(True)`` you can tell the bridge to
+  raise an exception instead of creating these values.
+
 - -[OC_PythonNumber compare:] calls super when the other value is
   an NSNumber and the Python value can be represented using a basic C 
   type.

File pyobjc-core/PyObjCTest/dejagnu.py

View file
  • Ignore whitespace
 
         commandline='MACOSX_DEPLPOYMENT_TARGET=%s %s %s -g -DMACOSX -Ilibffi-src/include -Ilibffi-src/powerpc -o /tmp/test.bin %s %s %s 2>&1'%(
                 get_config_var('MACOSX_DEPLOYMENT_TARGET'),
-                get_config_var('CC'),
+                #get_config_var('CC'),
+                'clang',
                 CFLAGS, self.filename, ' '.join(libffiobjects),
 		extra_link)
 

File pyobjc-core/PyObjCTest/test_archive_python.py

View file
  • Ignore whitespace
 
             self.assertEqual(len(v), 1)
             self.assertEqual(dir(v[0]), dir(i))
-            self.assertEqual(v[0].attr.keys(), [1])
+            self.assertEqual(list(v[0].attr.keys()), [1])
             self.assertIs(v[0].attr[1], v)
 
             buf = self.archiverClass.archivedDataWithRootObject_(d)
         # Disable a number of methods, these test things we're not interested in.
         # (Most of these look at the generated byte-stream, as we're not writing data in pickle's
         # format such tests are irrelevant to archiving support)
+        @onlyIf(0, "python unittest not relevant for archiving")
+        def test_dynamic_class(self): pass
+
+        @onlyIf(0, "python unittest not relevant for archiving")
+        def test_ellipsis(self): pass
+
+        @onlyIf(0, "python unittest not relevant for archiving")
+        def test_notimplemented(self): pass
 
         @onlyIf(0, "python unittest not relevant for archiving")
         def test_load_classic_instance(self): pass
         def test_load_from_canned_string(self): pass
 
         @onlyIf(0, "python unittest not relevant for archiving")
-        def test_maxsize64(self): pass
+        def test_maxint64(self): pass
 
         @onlyIf(0, "python unittest not relevant for archiving")
         def test_dict_chunking(self): pass
         def test_unicode(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_empty_bytestring(self): pass

File pyobjc-core/PyObjCTest/test_ctests.py

View file
  • Ignore whitespace
 names = [ x for x in dir (ctests) if not x.startswith('_') ]
 methods = {}
 
+def do_exec(value, locals, globals):
+
+    exec(value, locals, globals)
 
 def make_test(name):
     """
 
         return test_CheckNSInvoke
 
-    exec  """\
+    do_exec("""\
 def test_%s(self):
     meth()
-"""%(name,) in result
+"""%(name,), result, result)
 
     return result['test_%s'%(name,)]
 

File pyobjc-core/PyObjCTest/test_exceptions.py

View file
  • Ignore whitespace
 # XXX: we should centralize all exception handling tests into this file, this
 #      is now mostly used to check general unicode support in exceptions.
 #
+from __future__ import unicode_literals
 from PyObjCTest.exceptions import *
 
 from PyObjCTools.TestSupport import *
 
         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')
+            self.assertEqual(e._pyobjc_info_['name'], 'SimpleException')
+            self.assertEqual(e._pyobjc_info_['reason'], 'hello world')
             self.assertEqual(e._pyobjc_info_['userInfo'], None)
 
     def testSimpleWithInfo(self):
 
         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')
+            self.assertEqual(e._pyobjc_info_['name'], 'InfoException')
+            self.assertEqual(e._pyobjc_info_['reason'], 'Reason string')
             self.assertEqual(e._pyobjc_info_['userInfo'], {
                 'key1': 'value1',
                 'key2': 'value2',
 
         except objc.error as e:
             if sys.version_info[0] == 2:
-                self.assertEqual(str(e), u'SimpleException\u1234\u2049 - hello world'.encode('utf-8'))
+                self.assertEqual(str(e), 'SimpleException\u1234\u2049 - hello world'.encode('utf-8'))
             else:
-                self.assertEqual(str(e), u'SimpleException\u1234\u2049 - hello world')
-            self.assertEqual(e._pyobjc_info_['name'], u'SimpleException\u1234\u2049')
-            self.assertEqual(e._pyobjc_info_['reason'], u'hello world')
+                self.assertEqual(str(e), 'SimpleException\u1234\u2049 - hello world')
+            self.assertEqual(e._pyobjc_info_['name'], 'SimpleException\u1234\u2049')
+            self.assertEqual(e._pyobjc_info_['reason'], 'hello world')
             self.assertEqual(e._pyobjc_info_['userInfo'], None)
 
     def testUnicodeReason(self):
 
         except objc.error as e:
             if sys.version_info[0] == 2:
-                self.assertEqual(str(e), u'SimpleException - hello world\u1234\u2049'.encode('utf-8'))
+                self.assertEqual(str(e), 'SimpleException - hello world\u1234\u2049'.encode('utf-8'))
             else:
-                self.assertEqual(str(e), u'SimpleException - hello world\u1234\u2049')
-            self.assertEqual(e._pyobjc_info_['name'], u'SimpleException')
-            self.assertEqual(e._pyobjc_info_['reason'], u'hello world\u1234\u2049')
+                self.assertEqual(str(e), 'SimpleException - hello world\u1234\u2049')
+            self.assertEqual(e._pyobjc_info_['name'], 'SimpleException')
+            self.assertEqual(e._pyobjc_info_['reason'], 'hello world\u1234\u2049')
             self.assertEqual(e._pyobjc_info_['userInfo'], None)
 
     def testUnicodeWithInfo(self):
 
         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'))
+                self.assertEqual(str(e), 'InfoException\u1234\u2049 - Reason string\u1234\u2049'.encode('utf-8'))
             else:
-                self.assertEqual(str(e), u'InfoException\u1234\u2049 - Reason string\u1234\u2049')
-            self.assertEqual(e._pyobjc_info_['name'], u'InfoException\u1234\u2049')
-            self.assertEqual(e._pyobjc_info_['reason'], u'Reason string\u1234\u2049')
+                self.assertEqual(str(e), 'InfoException\u1234\u2049 - Reason string\u1234\u2049')
+            self.assertEqual(e._pyobjc_info_['name'], 'InfoException\u1234\u2049')
+            self.assertEqual(e._pyobjc_info_['reason'], 'Reason string\u1234\u2049')
             self.assertEqual(e._pyobjc_info_['userInfo'], {
-                u'key1\u1234\u2049': u'value1\u1234\u2049',
-                u'key2\u1234\u2049': u'value2\u1234\u2049',
+                'key1\u1234\u2049': 'value1\u1234\u2049',
+                'key2\u1234\u2049': 'value2\u1234\u2049',
             })
 
     def testRaisingStringsInObjectiveC(self):
             o.raiseAString()
 
         except objc.error as e:
-            self.assertEqual(e._pyobjc_exc_, u"thrown string")
+            self.assertEqual(e._pyobjc_exc_, "thrown string")
 
 if __name__ == "__main__":
     main()

File pyobjc-core/PyObjCTest/test_fsref.py

View file
  • Ignore whitespace
+from __future__ import unicode_literals
 from PyObjCTools.TestSupport import *
 import objc
 
 from PyObjCTest.fsref import *
 
-"""
-@interface OC_TestFSRefHelper : NSObject
-{
-        }
-
--(FSRef)fsrefForPath:(NSString*)path;
--(NSString*)pathForFSRef:(in FSRef *)fsref;
--(void)getFSRef:(out FSRef*)fsref forPath:(NSString*)path;
--(NSString*)stringForFSRef:(FSRef)fsref;
-
-
-
-@end
-"""
-
-
+import sys
+if sys.version_info[0] == 3:
+    unicode = str
 
 class TestFSRef (TestCase):
     def testBasicInterface(self):
 
     def testResult(self):
         o = OC_TestFSRefHelper.alloc().init()
-        ref = o.fsrefForPath_(u"/Library")
+        ref = o.fsrefForPath_("/Library")
         self.assertIsInstance(ref, objc.FSRef)
 
         self.assertIsInstance(ref.data, bytes)
 
     def testArg(self):
         o = OC_TestFSRefHelper.alloc().init()
-        ref = o.fsrefForPath_(u"/Library")
+        ref = o.fsrefForPath_("/Library")
         self.assertIsInstance(ref, objc.FSRef)
 
         p = o.stringForFSRef_(ref)
         self.assertIsInstance(p, unicode)
-        self.assertEqual(p, u"/Library")
+        self.assertEqual(p, "/Library")
 
     def testInput(self):
         o = OC_TestFSRefHelper.alloc().init()
-        ref = o.fsrefForPath_(u"/Library")
+        ref = o.fsrefForPath_("/Library")
         self.assertIsInstance(ref, objc.FSRef)
 
         p = o.pathForFSRef_(ref)
         self.assertIsInstance(p, unicode)
-        self.assertEqual(p, u"/Library")
+        self.assertEqual(p, "/Library")
 
     def testOutput(self):
         o = OC_TestFSRefHelper.alloc().init()
-        ref = o.getFSRef_forPath_(None, u"/Library")
+        ref = o.getFSRef_forPath_(None, "/Library")
         self.assertIsInstance(ref, objc.FSRef)
 
         # Verify the fsref contents:
         p = o.stringForFSRef_(ref)
         self.assertIsInstance(p, unicode)
-        self.assertEqual(p, u"/Library")
+        self.assertEqual(p, "/Library")
 
 
 if __name__ == "__main__":

File pyobjc-core/PyObjCTest/test_identity.py

View file
  • Ignore whitespace
 # - Add unittests that test for "real-world" scenarios (writing stuff
 #   to plists, ...)
 # - Implement the required functionality
+from __future__ import unicode_literals
 
 import sys, os
 import objc
 from PyObjCTest.identity import *
 from PyObjCTools.TestSupport import *
 
+if sys.version_info[0] == 3:
+    unicode = str
+
 class TestPythonRoundTrip (TestCase):