[PyObjC-svn] r2269 - in trunk/pyobjc/pyobjc-core: . Doc Lib/PyObjCTools Lib/objc Modules/objc Modules/objc/test PyObjCTest
[email protected] Tue, 01 Sep 2009 04:24:48 -0500
| Newsgroups | gmane.comp.python.pyobjc.cvs |
|---|---|
| Message-ID | <[email protected]> |
Author: ronaldoussoren
Date: Tue Sep 1 04:24:47 2009
New Revision: 2269
Log:
* Port to SnowLeopard
* Fix issue where KVO notification weren't generated
Added:
trunk/pyobjc/pyobjc-core/PyObjCTest/test_usekvo.py (contents, props changed)
Modified:
trunk/pyobjc/pyobjc-core/Doc/24blocks.txt
trunk/pyobjc/pyobjc-core/Lib/PyObjCTools/TestSupport.py
trunk/pyobjc/pyobjc-core/Lib/objc/_convenience.py
trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonArray.h
trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonArray.m
trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonData.h
trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonData.m
trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonDate.h
trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonDate.m
trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonDictionary.h
trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonDictionary.m
trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonEnumerator.h
trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonEnumerator.m
trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonNumber.h
trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonNumber.m
trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonObject.h
trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonObject.m
trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonSet.h
trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonSet.m
trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonString.h
trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonString.m
trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonUnicode.h
trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonUnicode.m
trunk/pyobjc/pyobjc-core/Modules/objc/block_support.m
trunk/pyobjc/pyobjc-core/Modules/objc/corefoundation.h
trunk/pyobjc/pyobjc-core/Modules/objc/corefoundation.m
trunk/pyobjc/pyobjc-core/Modules/objc/fsref.h
trunk/pyobjc/pyobjc-core/Modules/objc/fsspec.h
trunk/pyobjc/pyobjc-core/Modules/objc/libffi_support.m
trunk/pyobjc/pyobjc-core/Modules/objc/method-signature.h
trunk/pyobjc/pyobjc-core/Modules/objc/method-signature.m
trunk/pyobjc/pyobjc-core/Modules/objc/module.m
trunk/pyobjc/pyobjc-core/Modules/objc/objc-class.m
trunk/pyobjc/pyobjc-core/Modules/objc/objc_support.m
trunk/pyobjc/pyobjc-core/Modules/objc/objc_util.m
trunk/pyobjc/pyobjc-core/Modules/objc/parsexml.m
trunk/pyobjc/pyobjc-core/Modules/objc/pyobjc.h
trunk/pyobjc/pyobjc-core/Modules/objc/registry.m
trunk/pyobjc/pyobjc-core/Modules/objc/selector.m
trunk/pyobjc/pyobjc-core/Modules/objc/super-call.m
trunk/pyobjc/pyobjc-core/Modules/objc/test/corefoundation.m
trunk/pyobjc/pyobjc-core/Modules/objc/test/exceptions.m
trunk/pyobjc/pyobjc-core/Modules/objc/test/sockaddr.m
trunk/pyobjc/pyobjc-core/Modules/objc/test/testbndl2.m
trunk/pyobjc/pyobjc-core/NEWS.txt
trunk/pyobjc/pyobjc-core/PyObjCTest/test_allocatebuffer.py
trunk/pyobjc/pyobjc-core/PyObjCTest/test_corefoundation.py
trunk/pyobjc/pyobjc-core/PyObjCTest/test_ivar.py
trunk/pyobjc/pyobjc-core/PyObjCTest/test_keyvalue.py
trunk/pyobjc/pyobjc-core/PyObjCTest/test_metadata.py
trunk/pyobjc/pyobjc-core/PyObjCTest/test_regr.py
trunk/pyobjc/pyobjc-core/setup.py
Modified: trunk/pyobjc/pyobjc-core/Doc/24blocks.txt
==============================================================================
--- trunk/pyobjc/pyobjc-core/Doc/24blocks.txt (original)
+++ trunk/pyobjc/pyobjc-core/Doc/24blocks.txt Tue Sep 1 04:24:47 2009
@@ -16,8 +16,6 @@
Blocks are only suppored when PyObjC is compiled using an Objective-C compiler
that also supports blocks.
-WARNING: This feature is still in development.
-
Calling blocks from Python
--------------------------
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 Tue Sep 1 04:24:47 2009
@@ -32,13 +32,18 @@
if m is None:
return None
+
path = m.group(1)
+ if path == '/':
+ return tuple(map(int, os_release().split('.')))
+
bn = _os.path.basename(path)
version = bn[6:-4]
if version.endswith('u'):
version = version[:-1]
- return map(int, version.split('.'))
+
+ return tuple(map(int, version.split('.')))
return _cache[0]
@@ -93,6 +98,8 @@
The test runs only on 32-bit systems
"""
if _sys.maxint > 2 ** 32:
+ if _sys.version_info[:2] >= (2, 7):
+ return _unittest.skip("only on 32-bit")(function)
return None
else:
return function
@@ -113,7 +120,31 @@
return function
else:
+ if _sys.version_info[:2] >= (2, 7):
+ return _unittest.skip("min_os_level(%s)"%(release,))
+ else:
+ return None
+
+ return decorator
+
+def max_os_level(release):
+ """
+ Usage::
+
+ class Tests (unittest.TestCase):
+
+ @max_os_level('10.5')
+ def testUntilLeopard(self):
+ pass
+ """
+ if os_release() <= release:
def decorator(function):
+ return function
+
+ else:
+ if _sys.version_info[:2] >= (2, 7):
+ return _unittest.skip("max_os_level(%s)"%(release,))
+ else:
return None
return decorator
@@ -299,6 +330,51 @@
self.fail(message or "arg %d of %s; retained: %r, expected: %r"%(
argno, method, st, retained))
+ def failUnlessArgIsBlock(self, method, argno, sel_type, message=None):
+ if isinstance(method, objc.selector):
+ offset = 2
+ else:
+ offset = 0
+ info = method.__metadata__()
+ type = info['arguments'][argno+offset]['type']
+ if type != '@?':
+ self.fail(message or "arg %d of %s is not of type block: %s"%(
+ argno, method, type))
+
+ st = info['arguments'][argno+offset].get('callable')
+ if st is None:
+ self.fail(message or "arg %d of %s is not of type block: no callable"%(
+ argno, method))
+
+ iface = st['retval']['type']
+ if st['arguments'][0]['type'] != '^v':
+ self.fail(message or "arg %d of %s has an invalid block signature"%(argno, method))
+ for a in st['arguments'][1:]:
+ iface += a['type']
+
+ if iface != sel_type:
+ self.fail(message or "arg %d of %s is not a block with type %r, but %r"%(argno, method, sel_type, iface))
+
+ def failUnlessResultIsBlock(self, method, sel_type, message=None):
+ info = method.__metadata__()
+ type = info['retval']['type']
+ if type != '@?':
+ self.fail(message or "result of %s is not of type block"%(
+ method))
+
+ st = info['retval'].get('callable')
+ if st is None:
+ self.fail(message or "result of %s is not of type block"%(
+ method))
+
+ iface = st['retval']['type']
+ if st['arguments'][0]['type'] != '^v':
+ self.fail(message or "result %s has an invalid block signature"%(method))
+ for a in st['arguments'][1:]:
+ iface += a['type']
+
+ if iface != sel_type:
+ self.fail(message or "result of %s is not a block with type %r, but %r"%(method, sel_type, iface))
def failUnlessArgIsSEL(self, method, argno, sel_type, message=None):
if isinstance(method, objc.selector):
@@ -331,8 +407,8 @@
info = method.__metadata__()
type = info['arguments'][argno+offset]['type']
if type != objc._C_NSBOOL:
- self.fail(message or "arg %d of %s is not of type BOOL"%(
- argno, method))
+ self.fail(message or "arg %d of %s is not of type BOOL, but %r"%(
+ argno, method, type))
def failUnlessArgIsFixedSize(self, method, argno, count, message=None):
if isinstance(method, objc.selector):
@@ -420,6 +496,22 @@
assertIsInstance = failUnlessIsInstance
+ def failUnlessIsIn(self, value, seq, message=None):
+ if value not in seq:
+ self.fail(message or "%r is not in %r"%(value, seq))
+
+ def failIfIsNotIn(self, value, seq, message=None):
+ if value not in seq:
+ self.fail(message or "%r is not in %r"%(value, seq))
+
+ def failUnlessIsNotIn(self, value, seq, message=None):
+ if value in seq:
+ self.fail(message or "%r is in %r"%(value, seq))
+
+ def failIfIsIn(self, value, seq, message=None):
+ if value in seq:
+ self.fail(message or "%r is in %r"%(value, seq))
+
if not hasattr(_unittest.TestCase, "assertAlmostEquals"):
def assertAlmostEquals(self, val1, val2, message=None):
self.failUnless(abs (val1 - val2) < 0.00001, message)
Modified: trunk/pyobjc/pyobjc-core/Lib/objc/_convenience.py
==============================================================================
--- trunk/pyobjc/pyobjc-core/Lib/objc/_convenience.py (original)
+++ trunk/pyobjc/pyobjc-core/Lib/objc/_convenience.py Tue Sep 1 04:24:47 2009
@@ -42,9 +42,6 @@
NSObject = lookUpClass('NSObject')
-def isNative(sel):
- return not hasattr(sel, 'callable')
-
def add_convenience_methods(super_class, name, type_dict):
try:
return _add_convenience_methods(super_class, name, type_dict)
@@ -72,11 +69,6 @@
def bundleForClass(cls):
return cb
type_dict['bundleForClass'] = selector(bundleForClass, isClassMethod=True)
- if ('__useKVO__' not in type_dict and
- isNative(type_dict.get('willChangeValueForKey_')) and
- isNative(type_dict.get('didChangeValueForKey_'))):
- useKVO = issubclass(super_class, NSObject)
- type_dict['__useKVO__'] = useKVO
if '__bundle_hack__' in type_dict:
import warnings
warnings.warn(
Modified: trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonArray.h
==============================================================================
--- trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonArray.h (original)
+++ trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonArray.h Tue Sep 1 04:24:47 2009
@@ -35,14 +35,14 @@
/*!
- * @method newWithPythonObject:
+ * @method arrayWithPythonObject:
* @abstract Create a new OC_PythonArray for a specific Python sequence
* @param value A python sequence
* @result Returns an autoreleased instance representing value
*
* Caller must own the GIL.
*/
-+ newWithPythonObject:(PyObject*)value;
++ arrayWithPythonObject:(PyObject*)value;
/*!
* @method initWithPythonObject:
Modified: trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonArray.m
==============================================================================
--- trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonArray.m (original)
+++ trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonArray.m Tue Sep 1 04:24:47 2009
@@ -23,7 +23,7 @@
if (!r) continue;
/* Instance of this type should be pythonifyed as a sequence */
- return [OC_PythonArray newWithPythonObject:object];
+ return [[[OC_PythonArray alloc] initWithPythonObject:object] autorelease];
}
return NULL;
@@ -51,7 +51,7 @@
return result;
}
-+ newWithPythonObject:(PyObject*)v;
++ arrayWithPythonObject:(PyObject*)v;
{
OC_PythonArray* res;
@@ -139,9 +139,8 @@
err = depythonify_c_value(@encode(id), v, &result);
if (unlikely(err == -1)) {
PyObjC_GIL_FORWARD_EXC();
- } else {
- Py_DECREF(v);
- }
+ }
+ Py_CLEAR(v);
PyObjC_END_WITH_GIL
@@ -305,10 +304,21 @@
* for other sequences use the generic pickle support code.
*/
if (PyTuple_CheckExact(value)) {
+ /* Encode tuples as type 4 with an explicit length, this allows
+ * us to create the tuple during decoding instead of having to
+ * create a temporary list. This is needed to get full support
+ * for encoding all datastructures, and is needed to pass the
+ * unittests for pickle in python2.7.
+ *
+ * NOTE: older versions used type 1 and no length.
+ */
if ([coder allowsKeyedCoding]) {
- [coder encodeInt32:1 forKey:@"pytype"];
+ [coder encodeInt32:4 forKey:@"pytype"];
+ [coder encodeInt32:PyTuple_Size(value) forKey:@"pylength"];
} else {
- int v = 1;
+ int v = 4;
+ [coder encodeValueOfObjCType:@encode(int) at:&v];
+ v = (int)PyTuple_Size(value);
[coder encodeValueOfObjCType:@encode(int) at:&v];
}
[super encodeWithCoder:coder];
@@ -345,16 +355,31 @@
{
NSUInteger i;
PyObjC_BEGIN_WITH_GIL
- for (i = 0; i < count; i++) {
- PyObject* v = PyObjC_IdToPython(objects[i]);
- if (v == NULL) {
- PyObjC_GIL_FORWARD_EXC();
+ if (PyTuple_CheckExact(value) && (NSUInteger)PyTuple_Size(value) == count) {
+ for (i = 0; i < count; i++) {
+ PyObject* v = PyObjC_IdToPython(objects[i]);
+ if (v == NULL) {
+ PyObjC_GIL_FORWARD_EXC();
+ }
+ if (PyTuple_GET_ITEM(value, i) != NULL) {
+ abort();
+ }
+ PyTuple_SET_ITEM(value, i, v);
+ /* Don't DECREF v; SetItem stole a reference */
}
- int r = PyList_Append(value, v);
- if (r == -1) {
- PyObjC_GIL_FORWARD_EXC();
+ } else {
+
+ for (i = 0; i < count; i++) {
+ PyObject* v = PyObjC_IdToPython(objects[i]);
+ if (v == NULL) {
+ PyObjC_GIL_FORWARD_EXC();
+ }
+ int r = PyList_Append(value, v);
+ if (r == -1) {
+ PyObjC_GIL_FORWARD_EXC();
+ }
+ Py_DECREF(v);
}
- Py_DECREF(v);
}
PyObjC_END_WITH_GIL
@@ -376,21 +401,43 @@
{
PyObject* t;
int code;
+ int size;
if ([coder allowsKeyedCoding]) {
code = [coder decodeInt32ForKey:@"pytype"];
} else {
[coder decodeValueOfObjCType:@encode(int) at:&code];
}
- PyObjC_BEGIN_WITH_GIL
- value = PyList_New(0);
- if (value == NULL) {
- PyObjC_GIL_FORWARD_EXC();
- }
- PyObjC_END_WITH_GIL
switch (code) {
+ case 4:
+ if ([coder allowsKeyedCoding]) {
+ size = [coder decodeInt32ForKey:@"pylength"];
+ } else {
+ [coder decodeValueOfObjCType:@encode(int) at:&size];
+ }
+
+ PyObjC_BEGIN_WITH_GIL
+ value = PyTuple_New(size);
+ if (value == NULL){
+ PyObjC_GIL_FORWARD_EXC();
+ }
+ PyObjC_END_WITH_GIL
+ [super initWithCoder:coder];
+ return self;
+
+
case 1:
+ /* This code was created by some previous versions of PyObjC
+ * (before 2.2) and is kept around for backward compatibilty.
+ */
+ PyObjC_BEGIN_WITH_GIL
+ value = PyList_New(0);
+ if (value == NULL){
+ PyObjC_GIL_FORWARD_EXC();
+ }
+ PyObjC_END_WITH_GIL
+
[super initWithCoder:coder];
PyObjC_BEGIN_WITH_GIL
t = value;
@@ -403,10 +450,22 @@
return self;
case 2:
+ PyObjC_BEGIN_WITH_GIL
+ value = PyList_New(0);
+ if (value == NULL) {
+ PyObjC_GIL_FORWARD_EXC();
+ }
+ PyObjC_END_WITH_GIL
[super initWithCoder:coder];
return self;
case 3:
+ PyObjC_BEGIN_WITH_GIL
+ value = PyList_New(0);
+ if (value == NULL) {
+ PyObjC_GIL_FORWARD_EXC();
+ }
+ PyObjC_END_WITH_GIL
if (PyObjC_Decoder != NULL) {
PyObjC_BEGIN_WITH_GIL
Modified: trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonData.h
==============================================================================
--- trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonData.h (original)
+++ trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonData.h Tue Sep 1 04:24:47 2009
@@ -37,7 +37,7 @@
*
* Caller must own the GIL.
*/
-+ newWithPythonObject:(PyObject*)value;
++ dataWithPythonObject:(PyObject*)value;
/*!
* @method initWithPythonObject:
Modified: trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonData.m
==============================================================================
--- trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonData.m (original)
+++ trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonData.m Tue Sep 1 04:24:47 2009
@@ -3,7 +3,7 @@
@implementation OC_PythonData
-+ newWithPythonObject:(PyObject*)v;
++ dataWithPythonObject:(PyObject*)v;
{
OC_PythonData* res;
Modified: trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonDate.h
==============================================================================
--- trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonDate.h (original)
+++ trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonDate.h Tue Sep 1 04:24:47 2009
@@ -8,7 +8,7 @@
}
+ depythonifyObject:(PyObject*)object;
-+ newWithPythonObject:(PyObject*)value;
++ dateWithPythonObject:(PyObject*)value;
- initWithPythonObject:(PyObject*)value;
-(void)dealloc;
-(PyObject*)__pyobjc_PythonObject__;
Modified: trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonDate.m
==============================================================================
--- trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonDate.m (original)
+++ trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonDate.m Tue Sep 1 04:24:47 2009
@@ -48,7 +48,7 @@
return nil;
}
-+ newWithPythonObject:(PyObject*)v;
++ dateWithPythonObject:(PyObject*)v;
{
OC_PythonArray* res;
Modified: trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonDictionary.h
==============================================================================
--- trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonDictionary.h (original)
+++ trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonDictionary.h Tue Sep 1 04:24:47 2009
@@ -46,7 +46,7 @@
*
* The caller must own the GIL.
*/
-+ newWithPythonObject:(PyObject*)value;
++ dictionaryWithPythonObject:(PyObject*)value;
/*!
* @method initWithPythonObject:
Modified: trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonDictionary.m
==============================================================================
--- trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonDictionary.m (original)
+++ trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonDictionary.m Tue Sep 1 04:24:47 2009
@@ -19,7 +19,7 @@
BOOL valid;
Py_ssize_t pos;
}
-+ newWithWrappedDictionary:(OC_PythonDictionary*)value;
++ enumeratorWithWrappedDictionary:(OC_PythonDictionary*)value;
- initWithWrappedDictionary:(OC_PythonDictionary*)value;
-(void)dealloc;
@@ -31,7 +31,7 @@
@implementation OC_PythonDictionaryEnumerator
-+newWithWrappedDictionary:(OC_PythonDictionary*)v;
++enumeratorWithWrappedDictionary:(OC_PythonDictionary*)v;
{
return [[[self alloc] initWithWrappedDictionary:v] autorelease];
}
@@ -86,7 +86,7 @@
if (!r) continue;
/* Instance of this type should be pythonifyed as a sequence */
- return [OC_PythonArray newWithPythonObject:object];
+ return [OC_PythonArray arrayWithPythonObject:object];
}
return NULL;
@@ -114,7 +114,7 @@
return result;
}
-+newWithPythonObject:(PyObject*)v;
++dictionaryWithPythonObject:(PyObject*)v;
{
OC_PythonDictionary* res =
[[OC_PythonDictionary alloc] initWithPythonObject:v];
@@ -350,7 +350,7 @@
-(NSEnumerator *)keyEnumerator
{
if (PyDict_CheckExact(value)) {
- return [OC_PythonDictionaryEnumerator newWithWrappedDictionary:self];
+ return [OC_PythonDictionaryEnumerator enumeratorWithWrappedDictionary:self];
} else {
PyObjC_BEGIN_WITH_GIL
PyObject* keys = PyObject_CallMethod(value, "keys", NULL);
@@ -364,7 +364,7 @@
PyObjC_GIL_FORWARD_EXC();
}
- NSEnumerator* result = [OC_PythonEnumerator newWithPythonObject:iter];
+ NSEnumerator* result = [OC_PythonEnumerator enumeratorWithPythonObject:iter];
PyObjC_GIL_RETURN(result);
PyObjC_END_WITH_GIL
Modified: trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonEnumerator.h
==============================================================================
--- trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonEnumerator.h (original)
+++ trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonEnumerator.h Tue Sep 1 04:24:47 2009
@@ -5,7 +5,7 @@
BOOL valid;
}
-+newWithPythonObject:(PyObject*)object;
++enumeratorWithPythonObject:(PyObject*)object;
-initWithPythonObject:(PyObject*)object;
@end
Modified: trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonEnumerator.m
==============================================================================
--- trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonEnumerator.m (original)
+++ trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonEnumerator.m Tue Sep 1 04:24:47 2009
@@ -2,7 +2,7 @@
@implementation OC_PythonEnumerator
-+newWithPythonObject:(PyObject*)object
++enumeratorWithPythonObject:(PyObject*)object
{
return [[self alloc] initWithPythonObject:object];
}
Modified: trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonNumber.h
==============================================================================
--- trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonNumber.h (original)
+++ trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonNumber.h Tue Sep 1 04:24:47 2009
@@ -5,7 +5,7 @@
PyObject* value;
}
-+ newWithPythonObject:(PyObject*)value;
++ numberWithPythonObject:(PyObject*)value;
- initWithPythonObject:(PyObject*)value;
-(void)dealloc;
-(PyObject*)__pyobjc_PythonObject__;
Modified: trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonNumber.m
==============================================================================
--- trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonNumber.m (original)
+++ trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonNumber.m Tue Sep 1 04:24:47 2009
@@ -2,7 +2,7 @@
@implementation OC_PythonNumber
-+ newWithPythonObject:(PyObject*)v;
++ numberWithPythonObject:(PyObject*)v;
{
OC_PythonNumber* res;
Modified: trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonObject.h
==============================================================================
--- trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonObject.h (original)
+++ trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonObject.h Tue Sep 1 04:24:47 2009
@@ -43,11 +43,11 @@
}
+ (int)wrapPyObject:(PyObject *)argument toId:(id *)datum;
-+ newWithObject:(PyObject *) obj;
++ objectWithPythonObject:(PyObject *) obj;
+ depythonifyTable;
+ pythonifyStructTable;
+ (PyObject *)__pythonifyStruct:(PyObject *) obj withType:(const char *) type length:(Py_ssize_t) length;
-+ newWithCoercedObject:(PyObject *) obj;
++ objectWithCoercedObject:(PyObject *) obj;
- initWithObject:(PyObject *) obj;
/*!
Modified: trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonObject.m
==============================================================================
--- trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonObject.m (original)
+++ trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonObject.m Tue Sep 1 04:24:47 2009
@@ -103,7 +103,7 @@
if (PyUnicode_Check(argument)) {
rval = [OC_PythonUnicode
- newWithPythonObject:argument];
+ unicodeWithPythonObject:argument];
if (rval) {
PyObjC_RegisterObjCProxy(argument, rval);
r = 0;
@@ -124,28 +124,28 @@
r = 0;
} else if (PyInt_Check (argument)) {
- rval = [OC_PythonNumber newWithPythonObject:argument];
+ rval = [OC_PythonNumber numberWithPythonObject:argument];
PyObjC_RegisterObjCProxy(argument, rval);
r = 0;
} else if (PyFloat_Check (argument)) {
- rval = [OC_PythonNumber newWithPythonObject:argument];
+ rval = [OC_PythonNumber numberWithPythonObject:argument];
PyObjC_RegisterObjCProxy(argument, rval);
r = 0;
} else if (PyLong_Check(argument)) {
- rval = [OC_PythonNumber newWithPythonObject:argument];
+ rval = [OC_PythonNumber numberWithPythonObject:argument];
PyObjC_RegisterObjCProxy(argument, rval);
r = 0;
} else if (PyList_Check(argument) || PyTuple_Check(argument)) {
rval = [OC_PythonArray
- newWithPythonObject:argument];
+ arrayWithPythonObject:argument];
PyObjC_RegisterObjCProxy(argument, rval);
r = 0;
} else if (PyDict_Check(argument)) {
rval = [OC_PythonDictionary
- newWithPythonObject:argument];
+ dictionaryWithPythonObject:argument];
PyObjC_RegisterObjCProxy(argument, rval);
r = 0;
} else if (PyString_Check(argument)) {
@@ -158,7 +158,7 @@
}
if (r == 0) {
rval = [OC_PythonString
- newWithPythonObject:argument];
+ stringWithPythonObject:argument];
if (rval) {
PyObjC_RegisterObjCProxy(argument, rval);
r = 0;
@@ -168,7 +168,7 @@
}
} else if (PyObject_CheckReadBuffer(argument)) {
rval = [OC_PythonData
- newWithPythonObject:argument];
+ dataWithPythonObject:argument];
if (rval) {
PyObjC_RegisterObjCProxy(argument, rval);
r = 0;
@@ -177,7 +177,7 @@
}
} else if (PyAnySet_Check(argument)) {
- rval = [OC_PythonSet newWithPythonObject:argument];
+ rval = [OC_PythonSet setWithPythonObject:argument];
if (rval) {
PyObjC_RegisterObjCProxy(argument, rval);
r = 0;
@@ -191,7 +191,7 @@
} else {
PyObjC_DURING
rval = [OC_PythonObject
- newWithCoercedObject:argument];
+ objectWithCoercedObject:argument];
r = 0;
@@ -208,7 +208,7 @@
return r;
}
-+ newWithObject:(PyObject *) obj
++ objectWithPythonObject:(PyObject *) obj
{
id instance;
if (likely(PyObjCObject_Check(obj))) {
@@ -220,7 +220,7 @@
return instance;
}
-+ newWithCoercedObject:(PyObject *)obj
++ objectWithCoercedObject:(PyObject *)obj
{
id instance;
PyObjC_BEGIN_WITH_GIL
Modified: trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonSet.h
==============================================================================
--- trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonSet.h (original)
+++ trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonSet.h Tue Sep 1 04:24:47 2009
@@ -6,7 +6,7 @@
}
+ depythonifyObject:(PyObject*)object;
-+ newWithPythonObject:(PyObject*)value;
++ setWithPythonObject:(PyObject*)value;
- initWithPythonObject:(PyObject*)value;
-(void)dealloc;
-(PyObject*)__pyobjc_PythonObject__;
Modified: trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonSet.m
==============================================================================
--- trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonSet.m (original)
+++ trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonSet.m Tue Sep 1 04:24:47 2009
@@ -24,7 +24,7 @@
if (!r) continue;
/* Instance of this type should be pythonifyed as a sequence */
- return [OC_PythonSet newWithPythonObject:object];
+ return [OC_PythonSet setWithPythonObject:object];
}
return NULL;
@@ -52,7 +52,7 @@
return result;
}
-+ newWithPythonObject:(PyObject*)v;
++ setWithPythonObject:(PyObject*)v;
{
OC_PythonSet* res;
@@ -322,7 +322,7 @@
PyObjC_GIL_FORWARD_EXC();
}
- NSEnumerator* result = [OC_PythonEnumerator newWithPythonObject:tmp];
+ NSEnumerator* result = [OC_PythonEnumerator enumeratorWithPythonObject:tmp];
Py_DECREF(tmp);
PyObjC_GIL_RETURN(result);
Modified: trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonString.h
==============================================================================
--- trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonString.h (original)
+++ trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonString.h Tue Sep 1 04:24:47 2009
@@ -28,7 +28,7 @@
*
* Caller must own the GIL.
*/
-+ newWithPythonObject:(PyObject*)value;
++ stringWithPythonObject:(PyObject*)value;
/*!
* @method initWithPythonObject:
Modified: trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonString.m
==============================================================================
--- trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonString.m (original)
+++ trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonString.m Tue Sep 1 04:24:47 2009
@@ -3,7 +3,7 @@
@implementation OC_PythonString
-+ newWithPythonObject:(PyObject*)v;
++ stringWithPythonObject:(PyObject*)v;
{
OC_PythonString* res;
@@ -146,6 +146,8 @@
PyObjC_GIL_FORWARD_EXC();
}
+ PyString_InternInPlace(&value);
+
PyObjC_END_WITH_GIL;
if (flag) {
free(characters);
Modified: trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonUnicode.h
==============================================================================
--- trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonUnicode.h (original)
+++ trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonUnicode.h Tue Sep 1 04:24:47 2009
@@ -30,7 +30,7 @@
*
* Caller must own the GIL.
*/
-+ newWithPythonObject:(PyObject*)value;
++ unicodeWithPythonObject:(PyObject*)value;
/*!
* @method initWithPythonObject:
Modified: trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonUnicode.m
==============================================================================
--- trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonUnicode.m (original)
+++ trunk/pyobjc/pyobjc-core/Modules/objc/OC_PythonUnicode.m Tue Sep 1 04:24:47 2009
@@ -3,7 +3,7 @@
@implementation OC_PythonUnicode
-+ newWithPythonObject:(PyObject*)v;
++ unicodeWithPythonObject:(PyObject*)v;
{
OC_PythonUnicode* res;
Modified: trunk/pyobjc/pyobjc-core/Modules/objc/block_support.m
==============================================================================
--- trunk/pyobjc/pyobjc-core/Modules/objc/block_support.m (original)
+++ trunk/pyobjc/pyobjc-core/Modules/objc/block_support.m Tue Sep 1 04:24:47 2009
@@ -76,10 +76,6 @@
PyObject* invoke_cleanup;
};
-/*
- * FIXME: keep track of the refcount on the invoke function
- * as well, deconstruct it when it is no longer needed.
- */
static void
oc_copy_helper(void* _dst, void* _src)
{
@@ -132,6 +128,16 @@
0
};
+
+/*
+ * PyObjCBlock_Call is exposed to python code as objc._block_call(block, signature, args, kwds),
+ * and is called from the __call__ method on blocks.
+ *
+ * The tp_call of blocks isn't set directly because that's annoyingly hard to arrange for
+ * in objc-class.m, just setting the tp_call slot isn't good enough: you somehow have to update
+ * the class dictionary as well (including those of subclasses). There is no public API for
+ * that.
+ */
static inline Py_ssize_t align(Py_ssize_t offset, Py_ssize_t alignment)
{
Py_ssize_t rest = offset % alignment;
Modified: trunk/pyobjc/pyobjc-core/Modules/objc/corefoundation.h
==============================================================================
--- trunk/pyobjc/pyobjc-core/Modules/objc/corefoundation.h (original)
+++ trunk/pyobjc/pyobjc-core/Modules/objc/corefoundation.h Tue Sep 1 04:24:47 2009
@@ -9,4 +9,4 @@
extern PyObject* PyObjCCF_NewSpecial2(CFTypeID typeid, void* datum);
-#endif PyObjC_COREFOUNDATION_H
+#endif /* PyObjC_COREFOUNDATION_H */
Modified: trunk/pyobjc/pyobjc-core/Modules/objc/corefoundation.m
==============================================================================
--- trunk/pyobjc/pyobjc-core/Modules/objc/corefoundation.m (original)
+++ trunk/pyobjc/pyobjc-core/Modules/objc/corefoundation.m Tue Sep 1 04:24:47 2009
@@ -215,7 +215,10 @@
return -1;
}
- cls = objc_lookUpClass("NSCFType");
+ cls = objc_lookUpClass("__NSCFType");
+ if (cls == nil) {
+ cls = objc_lookUpClass("NSCFType");
+ }
if (cls == nil) {
PyErr_SetString(PyExc_RuntimeError,
"Cannot locate NSCFType");
@@ -250,7 +253,7 @@
PyObject* rval = NULL;
PyObject* v = PyDict_GetItemString(PyObjC_TypeStr2CFTypeID, typestr);
if (v == NULL) {
- PyErr_SetString(PyExc_ValueError, "Unknown typestr");
+ PyErr_Format(PyExc_ValueError, "Don't know CF type for typestr '%s', cannot create special wrapper", typestr);
return NULL;
}
CFTypeID typeid;
Modified: trunk/pyobjc/pyobjc-core/Modules/objc/fsref.h
==============================================================================
--- trunk/pyobjc/pyobjc-core/Modules/objc/fsref.h (original)
+++ trunk/pyobjc/pyobjc-core/Modules/objc/fsref.h Tue Sep 1 04:24:47 2009
@@ -14,4 +14,4 @@
#define PyObjC_FSRefCheck(value) \
PyObject_TypeCheck(value, &PyObjC_FSRefType)
-#endif PyObjC_FSREF_H
+#endif /* PyObjC_FSREF_H */
Modified: trunk/pyobjc/pyobjc-core/Modules/objc/fsspec.h
==============================================================================
--- trunk/pyobjc/pyobjc-core/Modules/objc/fsspec.h (original)
+++ trunk/pyobjc/pyobjc-core/Modules/objc/fsspec.h Tue Sep 1 04:24:47 2009
@@ -14,4 +14,4 @@
#define PyObjC_FSSpecCheck(value) \
PyObject_TypeCheck(value, &PyObjC_FSSpecType)
-#endif PyObjC_FSSPEC_H
+#endif /* PyObjC_FSSPEC_H */
Modified: trunk/pyobjc/pyobjc-core/Modules/objc/libffi_support.m
==============================================================================
--- trunk/pyobjc/pyobjc-core/Modules/objc/libffi_support.m (original)
+++ trunk/pyobjc/pyobjc-core/Modules/objc/libffi_support.m Tue Sep 1 04:24:47 2009
@@ -2025,7 +2025,7 @@
PyObjCPythonSelector *pythonSelector = (PyObjCPythonSelector *) aSelector;
PyObjCMethodSignature* methinfo = PyObjCMethodSignature_ForSelector(
pythonSelector->sel_class,
-// (pythonSelector->sel_flags & PyObjCSelector_kCLASS_METHOD) != 0,
+ (pythonSelector->sel_flags & PyObjCSelector_kCLASS_METHOD) != 0,
pythonSelector->sel_selector,
pythonSelector->sel_python_signature);
Modified: trunk/pyobjc/pyobjc-core/Modules/objc/method-signature.h
==============================================================================
--- trunk/pyobjc/pyobjc-core/Modules/objc/method-signature.h (original)
+++ trunk/pyobjc/pyobjc-core/Modules/objc/method-signature.h Tue Sep 1 04:24:47 2009
@@ -66,7 +66,7 @@
extern PyObjCMethodSignature* PyObjCMethodSignature_WithMetaData(const char* signature, PyObject* metadata);
extern PyObjCMethodSignature* PyObjCMethodSignature_ForSelector(
- Class cls, SEL sel, const char* signature);
+ Class cls, BOOL isClassMethod, SEL sel, const char* signature);
Modified: trunk/pyobjc/pyobjc-core/Modules/objc/method-signature.m
==============================================================================
--- trunk/pyobjc/pyobjc-core/Modules/objc/method-signature.m (original)
+++ trunk/pyobjc/pyobjc-core/Modules/objc/method-signature.m Tue Sep 1 04:24:47 2009
@@ -614,13 +614,19 @@
PyObjCMethodSignature* PyObjCMethodSignature_ForSelector(
- Class cls, SEL sel, const char* signature)
+ Class cls, BOOL isClassMethod, SEL sel, const char* signature)
{
PyObjCMethodSignature* methinfo;
PyObject* metadata;
metadata = PyObjC_FindInRegistry(registry, cls, sel);
methinfo = PyObjCMethodSignature_WithMetaData(signature, metadata);
+ if (isClassMethod) {
+ const char* nm = sel_getName(sel);
+ if (strncmp(nm, "new", 3) == 0 && ((nm[3] == 0) || isupper(nm[3]))) {
+ methinfo->rettype.alreadyRetained = YES;
+ }
+ }
Py_XDECREF(metadata);
return methinfo;
}
@@ -721,6 +727,8 @@
case PyObjC_kVariableLengthArray:
r = PyDict_SetItemString(result, "c_array_of_variable_length",
Py_True);
+ if (r == -1) goto error;
+
}
if (descr->ptrType != PyObjC_kPointerPlain) {
Modified: trunk/pyobjc/pyobjc-core/Modules/objc/module.m
==============================================================================
--- trunk/pyobjc/pyobjc-core/Modules/objc/module.m (original)
+++ trunk/pyobjc/pyobjc-core/Modules/objc/module.m Tue Sep 1 04:24:47 2009
@@ -24,6 +24,7 @@
int PyObjC_VerboseLevel = 0;
int PyObjC_HideProtected = 1;
+BOOL PyObjC_useKVO = YES;
PyObject* PyObjCClass_DefaultModule = NULL;
PyObject* PyObjC_NSNumberWrapper = NULL;
@@ -36,6 +37,12 @@
static NSAutoreleasePool* global_release_pool = nil;
@interface OC_NSAutoreleasePoolCollector: NSObject
+ /*
+ * This class is used to automaticly reset the
+ * global pool when an outer autorelease pool is
+ * recycled. This avoids problems when a python
+ * plugin is loaded in an Objective-C program.
+ */
{}
+(void)newAutoreleasePool;
+(void)targetForBecomingMultiThreaded:(id)sender;
@@ -406,14 +413,17 @@
return NULL;
}
- PyObjC_DURING
- [global_release_pool release];
- [OC_NSAutoreleasePoolCollector newAutoreleasePool];
- PyObjC_HANDLER
- PyObjCErr_FromObjC(localException);
- PyObjC_ENDHANDLER
+ if (global_release_pool != NULL) {
- if (PyErr_Occurred()) return NULL;
+ PyObjC_DURING
+ [global_release_pool release];
+ [OC_NSAutoreleasePoolCollector newAutoreleasePool];
+ PyObjC_HANDLER
+ PyObjCErr_FromObjC(localException);
+ PyObjC_ENDHANDLER
+
+ if (PyErr_Occurred()) return NULL;
+ }
Py_INCREF(Py_None);
return Py_None;
@@ -568,7 +578,7 @@
static char* keywords[] = { "flag", NULL };
PyObject* o;
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:setVerbose",
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O",
keywords, &o)) {
return NULL;
}
@@ -602,6 +612,28 @@
return Py_None;
}
+PyDoc_STRVAR(setUseKVOForSetattr_doc,
+ "setUseKVOForSetattr(bool) -> bool\n"
+ "\n"
+ "Specify the default value for __useKVO__ on classes defined "
+ "after this call. Returns the previous value."
+);
+static PyObject*
+setUseKVOForSetattr(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;
+ }
+
+ PyObject* result = PyBool_FromLong(PyObjC_useKVO);
+ PyObjC_useKVO = PyObject_IsTrue(o);
+
+ return result;
+}
+
PyDoc_STRVAR(getVerbose_doc,
"getVerbose() -> bool\n"
"\n"
@@ -1392,84 +1424,6 @@
return NULL;
}
-static PyObject*
-PyObjC_objc_sync_notify(PyObject* self __attribute__((__unused__)), PyObject* args)
-{
- NSObject* object;
- int rv;
-
- if (!PyArg_ParseTuple(args, "O&",
- PyObjCObject_Convert, &object)) {
- return NULL;
- }
-
- Py_BEGIN_ALLOW_THREADS
- rv = objc_sync_notify(object);
-
- Py_END_ALLOW_THREADS
-
- if (rv == OBJC_SYNC_SUCCESS) {
- Py_INCREF(Py_None);
- return Py_None;
- }
-
- PyErr_Format(PyObjCExc_LockError, "objc_sync_notify failed: %d", rv);
- return NULL;
-}
-
-static PyObject*
-PyObjC_objc_sync_notifyAll(PyObject* self __attribute__((__unused__)), PyObject* args)
-{
- NSObject* object;
- int rv;
-
- if (!PyArg_ParseTuple(args, "O&",
- PyObjCObject_Convert, &object)) {
- return NULL;
- }
-
- Py_BEGIN_ALLOW_THREADS
- rv = objc_sync_notifyAll(object);
-
- Py_END_ALLOW_THREADS
-
- if (rv == OBJC_SYNC_SUCCESS) {
- Py_INCREF(Py_None);
- return Py_None;
- }
-
- PyErr_Format(PyObjCExc_LockError, "objc_sync_notifyAll failed: %d", rv);
- return NULL;
-}
-
-
-static PyObject*
-PyObjC_objc_sync_wait(PyObject* self __attribute__((__unused__)), PyObject* args)
-{
- NSObject* object;
- long long timeout;
- int rv;
-
- if (!PyArg_ParseTuple(args, "O&L",
- PyObjCObject_Convert, &object, &timeout)) {
- return NULL;
- }
-
- Py_BEGIN_ALLOW_THREADS
- rv = objc_sync_wait(object, timeout);
-
- Py_END_ALLOW_THREADS
-
- if (rv == OBJC_SYNC_SUCCESS) {
- Py_INCREF(Py_None);
- return Py_None;
- }
-
- PyErr_Format(PyObjCExc_LockError, "objc_sync_wait failed: %d", rv);
- return NULL;
-}
-
-
PyDoc_STRVAR(parseBridgeSupport_doc,
"parseBridgeSupport(xmldata, globals, framework [, dylib_path] [, inlineTab]) -> None\n"
"\n"
@@ -1656,6 +1610,7 @@
{ "_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 },
+ { "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 },
{ "pyobjc_id", (PyCFunction)pyobjc_id, METH_VARARGS|METH_KEYWORDS, pyobjc_id_doc },
@@ -1710,14 +1665,6 @@
METH_VARARGS, "acquire mutex for an object" },
{ "_objc_sync_exit", (PyCFunction)PyObjC_objc_sync_exit,
METH_VARARGS, "release mutex for an object" },
- { "_objc_sync_wait", (PyCFunction)PyObjC_objc_sync_wait,
- METH_VARARGS, "wait for mutex for an object" },
- { "_objc_sync_notify", (PyCFunction)PyObjC_objc_sync_notify,
- METH_VARARGS,
- "notify a thread waiting for mutex for an object" },
- { "_objc_sync_notifyAll", (PyCFunction)PyObjC_objc_sync_notifyAll,
- METH_VARARGS,
- "notify a all threads waiting for mutex for an object" },
{ "_block_call", (PyCFunction)PyObjCBlock_Call,
METH_VARARGS,
"_block_call(block, signature, args, kwds) -> retval" },
@@ -1946,5 +1893,6 @@
/* Allocate an auto-release pool for our own use, this avoids numerous
* warnings during startup of a python script.
*/
+ global_release_pool = [[NSAutoreleasePool alloc] init];
[OC_NSAutoreleasePoolCollector newAutoreleasePool];
}
Modified: trunk/pyobjc/pyobjc-core/Modules/objc/objc-class.m
==============================================================================
--- trunk/pyobjc/pyobjc-core/Modules/objc/objc-class.m (original)
+++ trunk/pyobjc/pyobjc-core/Modules/objc/objc-class.m Tue Sep 1 04:24:47 2009
@@ -332,6 +332,8 @@
* -> a new proxy type for CoreFoundation classes
*/
isCFProxyClass = YES;
+
+
}
if (!PyObjCClass_Check(py_super_class)) {
@@ -666,9 +668,14 @@
useKVOObj = PyDict_GetItemString(dict, "__useKVO__");
if (useKVOObj != NULL) {
info->useKVO = PyObject_IsTrue(useKVOObj);
+ } else {
+ info->useKVO = PyObjC_useKVO;
}
-
+ if (isCFProxyClass) {
+ /* Disable automatic KVO on pure CoreFoundation types */
+ info->useKVO = 0;
+ }
keys = PyDict_Keys(dict);
if (keys == NULL) {
Py_DECREF(old_dict);
@@ -1390,7 +1397,7 @@
info->sel_to_py = NULL;
info->method_magic = 0;
info->dictoffset = 0;
- info->useKVO = 0;
+ info->useKVO = 1;
info->delmethod = NULL;
info->hasPythonImpl = 0;
info->isCFWrapper = 0;
@@ -1404,10 +1411,8 @@
((PyTypeObject *)result)->tp_as_buffer = &nsdata_as_buffer;
} else if (strcmp(className, "NSMutableData") == 0) {
((PyTypeObject *)result)->tp_as_buffer = &nsmutabledata_as_buffer;
- }
- if (strcmp(className, "NSBlock") == 0) {
+ } else if (strcmp(className, "NSBlock") == 0) {
((PyTypeObject *)result)->tp_basicsize = sizeof(PyObjCBlockObject);
- ((PyTypeObject *)result)->tp_call = PyObjCBlock_Call;
PyType_Modified((PyTypeObject*)result);
PyType_Ready((PyTypeObject *)result);
}
Modified: trunk/pyobjc/pyobjc-core/Modules/objc/objc_support.m
==============================================================================
--- trunk/pyobjc/pyobjc-core/Modules/objc/objc_support.m (original)
+++ trunk/pyobjc/pyobjc-core/Modules/objc/objc_support.m Tue Sep 1 04:24:47 2009
@@ -1351,7 +1351,7 @@
/* We're depythonifying a list of strings, make sure the originals stay
* around long enough.
*/
- [OC_PythonObject newWithObject:seq];
+ [[[OC_PythonObject alloc] initWithObject:seq] autorelease];
}
Py_DECREF(seq);
return 0;
@@ -2574,7 +2574,7 @@
}
buf += strlen(buf);
- type += end - type;
+ /*type += end - type;*/
buf[0] = _C_ARY_E;
buf[1] = '\0';
return end + 1;
Modified: trunk/pyobjc/pyobjc-core/Modules/objc/objc_util.m
==============================================================================
--- trunk/pyobjc/pyobjc-core/Modules/objc/objc_util.m (original)
+++ trunk/pyobjc/pyobjc-core/Modules/objc/objc_util.m Tue Sep 1 04:24:47 2009
@@ -91,7 +91,7 @@
} else {
PyObject_SetAttrString(exc_value, "_pyobjc_exc_", exc);
}
- Py_DECREF(exc); exc = NULL;
+ Py_CLEAR(exc);
PyErr_Restore(exc_type, exc_value, exc_traceback);
PyGILState_Release(state);
return;
@@ -280,15 +280,15 @@
typerepr = PyObject_Str(exc_type);
userInfo = [NSMutableDictionary dictionaryWithCapacity: 3];
[userInfo setObject:
- [OC_PythonObject newWithObject:exc_type]
+ [[[OC_PythonObject alloc] initWithObject:exc_type] autorelease]
forKey:@"__pyobjc_exc_type__"];
if (exc_value != NULL)
[userInfo setObject:
- [OC_PythonObject newWithObject:exc_value]
+ [[[OC_PythonObject alloc] initWithObject:exc_value] autorelease]
forKey:@"__pyobjc_exc_value__"];
if (exc_traceback != NULL)
[userInfo setObject:
- [OC_PythonObject newWithObject:exc_traceback]
+ [[[OC_PythonObject alloc] initWithObject:exc_traceback] autorelease]
forKey:@"__pyobjc_exc_traceback__"];
val = [NSException
@@ -829,6 +829,8 @@
if (buffer_get(writable, pythonList, (void**)&buf, &bufsize) == -1) {
return -1;
}
+
+ assert(eltsize != 0);
if ((bufsize % eltsize) != 0) {
PyErr_SetString(PyExc_ValueError,
"Badly shaped array.array");
Modified: trunk/pyobjc/pyobjc-core/Modules/objc/parsexml.m
==============================================================================
--- trunk/pyobjc/pyobjc-core/Modules/objc/parsexml.m (original)
+++ trunk/pyobjc/pyobjc-core/Modules/objc/parsexml.m Tue Sep 1 04:24:47 2009
@@ -37,7 +37,6 @@
"already_cfretained",
"c_array_length_in_result",
"c_array_delimited_by_null",
- "null_accepted', ",
"c_array_of_variable_length",
"printf_format",
"free_result",
@@ -342,6 +341,17 @@
}
}
+ if (attribute_bool(node, "null_accepted", NULL, YES)) {
+ r = PyDict_SetItemString(result, "null_accepted", Py_True);
+ } else {
+ r = PyDict_SetItemString(result, "null_accepted", Py_False);
+ }
+ if (r == -1) {
+ Py_DECREF(result);
+ return NULL;
+ }
+
+
s = attribute_string(node, "c_array_length_in_arg", NULL);
if (s && *s) {
char* end = strchr(s, ',');
Modified: trunk/pyobjc/pyobjc-core/Modules/objc/pyobjc.h
==============================================================================
--- trunk/pyobjc/pyobjc-core/Modules/objc/pyobjc.h (original)
+++ trunk/pyobjc/pyobjc-core/Modules/objc/pyobjc.h Tue Sep 1 04:24:47 2009
@@ -83,6 +83,7 @@
@end /* interface NSMethodSignature */
+extern BOOL PyObjC_useKVO;
extern int PyObjC_VerboseLevel;
extern int PyObjC_HideProtected;
extern int PyObjC_StrBridgeEnabled;
Modified: trunk/pyobjc/pyobjc-core/Modules/objc/registry.m
==============================================================================
--- trunk/pyobjc/pyobjc-core/Modules/objc/registry.m (original)
+++ trunk/pyobjc/pyobjc-core/Modules/objc/registry.m Tue Sep 1 04:24:47 2009
@@ -58,6 +58,7 @@
sublist = PyDict_GetItemString(registry, (char*)sel_getName(selector));
if (sublist == NULL) return NULL;
+
len = PyList_Size(sublist);
for (i = 0; i < len; i++) {
Class cur_class;
Modified: trunk/pyobjc/pyobjc-core/Modules/objc/selector.m
==============================================================================
--- trunk/pyobjc/pyobjc-core/Modules/objc/selector.m (original)
+++ trunk/pyobjc/pyobjc-core/Modules/objc/selector.m Tue Sep 1 04:24:47 2009
@@ -112,6 +112,7 @@
if (self->sel_methinfo == NULL) {
self->sel_methinfo = PyObjCMethodSignature_ForSelector(
self->sel_class,
+ (self->sel_flags & PyObjCSelector_kCLASS_METHOD) != 0,
self->sel_selector,
self->sel_python_signature);
if (self->sel_methinfo == NULL) return NULL;
@@ -534,14 +535,14 @@
pyres = res = execute((PyObject*)self, self->sel_self, args);
if (pyres != NULL
&& PyTuple_Check(pyres)
- && PyTuple_GET_SIZE(pyres) > 1
+ && PyTuple_GET_SIZE(pyres) >= 1
&& PyTuple_GET_ITEM(pyres, 0) == pyself) {
pyres = pyself;
}
- if (PyObjCObject_Check(self) && (((PyObjCObject*)self->sel_self)->flags & PyObjCObject_kUNINITIALIZED)) {
+ if (PyObjCObject_Check(self->sel_self) && (((PyObjCObject*)self->sel_self)->flags & PyObjCObject_kUNINITIALIZED)) {
if (self->sel_self != pyres && !PyErr_Occurred()) {
- PyObjCObject_ClearObject(pyself);
+ PyObjCObject_ClearObject(self->sel_self);
}
}
} else {
@@ -587,6 +588,12 @@
pyres = pyself;
}
+ if (PyObjCObject_Check(pyself) && (((PyObjCObject*)pyself)->flags & PyObjCObject_kUNINITIALIZED)) {
+ if (pyself != pyres && !PyErr_Occurred()) {
+ PyObjCObject_ClearObject(pyself);
+ }
+ }
+
Py_DECREF(arglist);
}
Modified: trunk/pyobjc/pyobjc-core/Modules/objc/super-call.m
==============================================================================
--- trunk/pyobjc/pyobjc-core/Modules/objc/super-call.m (original)
+++ trunk/pyobjc/pyobjc-core/Modules/objc/super-call.m Tue Sep 1 04:24:47 2009
@@ -316,7 +316,8 @@
if (func != NULL) {
methinfo = PyObjCMethodSignature_ForSelector(
- class, PyObjCSelector_GetSelector(sel),
+ class, (PyObjCSelector_GetFlags(sel) & PyObjCSelector_kCLASS_METHOD) != 0,
+ PyObjCSelector_GetSelector(sel),
PyObjCSelector_Signature(sel));
if (methinfo == NULL) {
return NULL;
@@ -330,7 +331,8 @@
} else {
PyErr_Clear();
methinfo = PyObjCMethodSignature_ForSelector(
- class, PyObjCSelector_GetSelector(sel),
+ class, (PyObjCSelector_GetFlags(sel) & PyObjCSelector_kCLASS_METHOD) != 0,
+ PyObjCSelector_GetSelector(sel),
PyObjCSelector_Signature(sel));
if (methinfo == NULL) {
return NULL;
Modified: trunk/pyobjc/pyobjc-core/Modules/objc/test/corefoundation.m
==============================================================================
--- trunk/pyobjc/pyobjc-core/Modules/objc/test/corefoundation.m (original)
+++ trunk/pyobjc/pyobjc-core/Modules/objc/test/corefoundation.m Tue Sep 1 04:24:47 2009
@@ -17,7 +17,7 @@
// not toll-free bridged.
+(char*)signatureForCFUUIDRef;
+(CFTypeID)typeidForCFUUIDRef;
-+(CFUUIDRef)newUUID;
++(CFUUIDRef)createUUID;
+(NSString*)formatUUID:(CFUUIDRef)uuid;
+(NSObject*)anotherUUID;
@@ -42,11 +42,13 @@
return CFUUIDGetTypeID();
}
-+(CFUUIDRef)newUUID
++(CFUUIDRef)createUUID
{
CFUUIDRef result = CFUUIDCreate(NULL);
/* We own a reference, but want to released a borrowed ref. */
+ [(NSObject*)result retain];
+ CFRelease(result);
[(NSObject*)result autorelease];
return result;
Modified: trunk/pyobjc/pyobjc-core/Modules/objc/test/exceptions.m
==============================================================================
--- trunk/pyobjc/pyobjc-core/Modules/objc/test/exceptions.m (original)
+++ trunk/pyobjc/pyobjc-core/Modules/objc/test/exceptions.m Tue Sep 1 04:24:47 2009
@@ -50,7 +50,7 @@
{
[NSException
raise:@"SimpleException"
- format:addSomeUnicode(@"hello world")];
+ format:@"%@", addSomeUnicode(@"hello world")];
}
-(void)raiseUnicodeWithInfo
Modified: trunk/pyobjc/pyobjc-core/Modules/objc/test/sockaddr.m
==============================================================================
--- trunk/pyobjc/pyobjc-core/Modules/objc/test/sockaddr.m (original)
+++ trunk/pyobjc/pyobjc-core/Modules/objc/test/sockaddr.m Tue Sep 1 04:24:47 2009
@@ -26,7 +26,7 @@
if (error) {
return NULL;
}
- return [NSString stringWithCString:buf];
+ return [NSString stringWithUTF8String:buf];
}
Modified: trunk/pyobjc/pyobjc-core/Modules/objc/test/testbndl2.m
==============================================================================
--- trunk/pyobjc/pyobjc-core/Modules/objc/test/testbndl2.m (original)
+++ trunk/pyobjc/pyobjc-core/Modules/objc/test/testbndl2.m Tue Sep 1 04:24:47 2009
@@ -15,9 +15,9 @@
#import <Foundation/Foundation.h>
-#if defined(MACOSX) && ((__GNUC__* 100) + (__GNUC_MINOR__)) >= 303
+#if ((__GNUC__* 100) + (__GNUC_MINOR__)) >= 303
-#define HAVE_BOOL
+#define HAVE_BOOL 1
#endif
Modified: trunk/pyobjc/pyobjc-core/NEWS.txt
==============================================================================
--- trunk/pyobjc/pyobjc-core/NEWS.txt (original)
+++ trunk/pyobjc/pyobjc-core/NEWS.txt Tue Sep 1 04:24:47 2009
@@ -7,6 +7,45 @@
Version 2.2 (...)
-----------------
+- The default value for the ``__useKVO__`` attribute in class definitions
+ can now be controlled by ``objc.setUseKVOForSetattr(b)``. The default
+ is ``True``.
+
+ Note: in previous versions the default was ``False``.
+
+ Note2: the ``__useKVO__`` attribute is an implementation detail and should
+ not be used in normal code.
+
+ This change fixes an issue where KVO failed to detect some changes when
+ those changes were done in Python using attribute access syntax.
+
+- Wrappers for ``objc_sync_wait``, ``objc_sync_notify`` and
+ ``objc_sync_notifyAll`` have been removed. These have never been part of
+ the public API and this should therefore not affect existing code.
+
+- BUGFIX: There was a refcount leak in the code that proxies native code to
+ Python. This causes refcount leaks in user code when a Python class is
+ instantiated from native code, when that class has an initializer written
+ in Python.
+
+ Thanks to Dirk Stoop of Made by Sofa for providing the bugreport that helped
+ fix this issue.
+
+- ``objc.recycleAutoreleasePool`` is now a no-op when a python bundle is loaded
+ in an Objective-C program and the PyObjC's global release pool gets drained
+ by an outer release pool. This should not affect user programs.
+
+- BUGFIX: Storing pure python objects in a ``NSKeyedArchiver`` archive didn't
+ full work for all tuples, especially self-recursive tuples.
+
+ The current support for archiving Python objects passes all pickle unittests
+ in Python 2.7.
+
+- BUGFIX: ``+new`` is supposed to return an already retained object (that is,
+ the caller owns a reference). Until now PyObjC has assumed that the return
+ value of ``+new`` is an autoreleased value. The same is true for all class
+ methods whose name starts with ``new``.
+
- There is initial support for Objective-C blocks, based on the implementation
description in the `clang repository`__. Blocks are represented in Python
as callable objects. This means you can pass an arbitrary callable when
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 Tue Sep 1 04:24:47 2009
@@ -24,4 +24,3 @@
if __name__ == '__main__':
main()
- objc.recycleAutoreleasePool()
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 Tue Sep 1 04:24:47 2009
@@ -44,7 +44,7 @@
def testBridged(self):
- obj = OC_TestCoreFoundation.newUUID()
+ obj = OC_TestCoreFoundation.createUUID()
self.assert_( isinstance(obj, CFUUIDRef) )
Modified: trunk/pyobjc/pyobjc-core/PyObjCTest/test_ivar.py
==============================================================================
--- trunk/pyobjc/pyobjc-core/PyObjCTest/test_ivar.py (original)
+++ trunk/pyobjc/pyobjc-core/PyObjCTest/test_ivar.py Tue Sep 1 04:24:47 2009
@@ -5,6 +5,7 @@
from PyObjCTest.instanceVariables import ClassWithVariables
NSObject = objc.lookUpClass('NSObject')
+NSAutoreleasePool = objc.lookUpClass('NSAutoreleasePool')
class Base (object):
def __init__(self, ondel):
@@ -72,33 +73,40 @@
def testLeak(self):
# Check that plain python objects are correctly released when
# they are no longer the value of an attribute
+ pool = NSAutoreleasePool.alloc().init()
self.deleted = 0
self.object.idVar = Base(lambda : setattr(self, 'deleted', 1))
self.object.idVar = None
- objc.recycleAutoreleasePool()
+ del pool
self.assertEquals(self.deleted, 1)
def testLeak2(self):
+
self.deleted = 0
+
+ pool = NSAutoreleasePool.alloc().init()
+
self.object.idVar = Base(lambda : setattr(self, 'deleted', 1))
del self.object
- objc.recycleAutoreleasePool()
+ del pool
self.assertEquals(self.deleted, 1)
def testOCLeak(self):
# Check that Objective-C objects are correctly released when
# they are no longer the value of an attribute
+ pool = NSAutoreleasePool.alloc().init()
self.deleted = 0
self.object.idVar = OCBase.alloc().init_(lambda : setattr(self, 'deleted', 1))
self.object.idVar = None
- objc.recycleAutoreleasePool()
+ del pool
self.assertEquals(self.deleted, 1)
def testOCLeak2(self):
+ pool = NSAutoreleasePool.alloc().init()
self.deleted = 0
self.object.idVar = OCBase.alloc().init_(lambda : setattr(self, 'deleted', 1))
del self.object
- objc.recycleAutoreleasePool()
+ del pool
self.assertEquals(self.deleted, 1)
def testDelete(self):
Modified: trunk/pyobjc/pyobjc-core/PyObjCTest/test_keyvalue.py
==============================================================================
--- trunk/pyobjc/pyobjc-core/PyObjCTest/test_keyvalue.py (original)
+++ trunk/pyobjc/pyobjc-core/PyObjCTest/test_keyvalue.py Tue Sep 1 04:24:47 2009
@@ -494,6 +494,7 @@
# Check for using KVO in python.
def testAutomaticObserving(self):
+ outer_pool = NSAutoreleasePool.alloc().init()
observer = PyObjCTestObserver.alloc().init()
o = PyObjCTestObserved2.alloc().init()
pool = NSAutoreleasePool.alloc().init()
@@ -535,9 +536,11 @@
before = DEALLOCS
del o
+ del outer_pool
self.assertEquals(DEALLOCS, before+1, u"Leaking an observed object")
def testObserving(self):
+ outer_pool = NSAutoreleasePool.alloc().init()
observer = PyObjCTestObserver.alloc().init()
o = PyObjCTestObserved1.alloc().init()
@@ -598,6 +601,7 @@
before = DEALLOCS
del o
+ del outer_pool
self.assertEquals(DEALLOCS, before+1, u"Leaking an observed object")
def testObserving2(self):
Modified: trunk/pyobjc/pyobjc-core/PyObjCTest/test_metadata.py
==============================================================================
--- trunk/pyobjc/pyobjc-core/PyObjCTest/test_metadata.py (original)
+++ trunk/pyobjc/pyobjc-core/PyObjCTest/test_metadata.py Tue Sep 1 04:24:47 2009
@@ -633,6 +633,7 @@
# - Add null-terminated arrays of various supported types:
# -> integers
# -> CF-types
+
def testFixedSize(self):
o = OC_MetaDataTest.new()
@@ -904,6 +905,9 @@
self.assertRaises(TypeError, o.ignoreMethod)
class TestMetaDataAccess (TestCase):
+ def testNew(self):
+ self.failUnlessResultIsRetained(OC_MetaDataTest.new)
+
def testSuggestions(self):
meta = OC_MetaDataTest.varargsMethodWithObjects_.__metadata__()
self.assert_(isinstance(meta, dict))
Modified: trunk/pyobjc/pyobjc-core/PyObjCTest/test_regr.py
==============================================================================
--- trunk/pyobjc/pyobjc-core/PyObjCTest/test_regr.py (original)
+++ trunk/pyobjc/pyobjc-core/PyObjCTest/test_regr.py Tue Sep 1 04:24:47 2009
@@ -213,6 +213,23 @@
self.failIfEqual(gDeallocCounter, 0)
+ def testInitFailureLeaks(self):
+ NSData = objc.lookUpClass('NSData')
+ import warnings
+ warnings.filterwarnings('error',
+ category=objc.UninitializedDeallocWarning)
+
+ try:
+ try:
+ v = NSData.alloc().initWithContentsOfFile_("/etc/no-such-file.txt")
+ finally:
+ del warnings.filters[0]
+
+ except objc.UninitializedDeallocWarning:
+ self.fail("Unexpected raising of UninitializedDeallocWarning")
+
+ self.failIf(v is not None)
+
if __name__ == '__main__':
main()
Modified: trunk/pyobjc/pyobjc-core/setup.py
==============================================================================
--- trunk/pyobjc/pyobjc-core/setup.py (original)
+++ trunk/pyobjc/pyobjc-core/setup.py Tue Sep 1 04:24:47 2009
@@ -143,6 +143,9 @@
# Enable 'PyObjC_STRICT_DEBUGGING' to enable some costly internal
# assertions.
CFLAGS.extend([
+
+ # Use this to analyze with clang
+ #"--analyze",
# The following flags are an attempt at getting rid of /usr/local
# in the compiler search path.
@@ -150,6 +153,7 @@
"-DMACOSX", # For libffi
"-DPyObjC_BUILD_RELEASE=%02d%02d"%(tuple(map(int, platform.mac_ver()[0].split('.')[:2]))),
"-no-cpp-precomp",
+ "-DMACOSX",
#"-Wno-long-double",
#"-Wselector",
#"-Wstrict-overflow",
@@ -162,7 +166,7 @@
## on i386 systems when a method returns a struct that isn't returned
## in registers.
#"-O0",
- "-O1",
+ #"-O1",
#"-O2",
#"-O3",
#'-arch', 'x86_64', '-arch', 'ppc64',
------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
trial. Simplify your report design, integration and deployment - and focus on
what you do best, core application coding. Discover what's new with
Crystal Reports now. http://p.sf.net/sfu/bobj-july