1. Ronald Oussoren
  2. pyobjc

Commits

Ronald Oussoren  committed c51e535

Workaround for a problem with OC_PythonNumber

For some reason OC_PythonNumber's with values between 2**63 and 2**64
end up in binary plist files with the wrong value. This checkin contains
a testcase and a crude workaround.

  • Participants
  • Parent commits fd0ceab
  • Branches default

Comments (0)

Files changed (3)

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

View file
 +(instancetype)numberWithPythonObject:(PyObject*)v
 {
     OC_PythonNumber* res;
+    if (PyLong_Check(v)) {
+        unsigned long long lv = PyLong_AsUnsignedLongLong(v);
+        if (PyErr_Occurred()) {
+            PyErr_Clear();
+        } else if (lv >= 1ULL<<63) {
+            return [[NSNumber alloc] initWithUnsignedLongLong:lv];
+        }
+    }
 
     res = [[OC_PythonNumber alloc] initWithPythonObject:v];
     [res autorelease];
 
 #endif
         } else if (PyLong_Check(value)) {
-            PyObjC_GIL_RETURN(@encode(long long));
+            (void)PyLong_AsLongLong(value);
+            if (!PyErr_Occurred()) {
+                PyObjC_GIL_RETURN(@encode(long long));
+            } else {
+                PyErr_Clear();
+                (void)PyLong_AsUnsignedLongLong(value);
+                if (!PyErr_Occurred()) {
+                    PyObjC_GIL_RETURN(@encode(unsigned long long));
+                }
+                PyErr_Clear();
+            }
         }
     PyObjC_END_WITH_GIL
     [NSException raise:NSInvalidArgumentException
     PyObjC_END_WITH_GIL
 }
 
+-(void)getValue:(void*)buffer forType:(const char*)type
+{
+    int r;
+    NSLog(@"getValue %p forType %s", buffer, type);
+    PyObjC_BEGIN_WITH_GIL
+        r = depythonify_c_value(type, value, buffer);
+        if (r == -1) {
+            PyObjC_GIL_FORWARD_EXC();
+        }
+    PyObjC_END_WITH_GIL
+}
 
 
 -(BOOL)boolValue
             (void)PyLong_AsLongLong(value);
             if (PyErr_Occurred()) {
                 PyErr_Clear();
-                use_super = 0;
+                (void)PyLong_AsUnsignedLongLong(value);
+                if (PyErr_Occurred()) {
+                    PyErr_Clear();
+                    use_super = 0;
+                } else {
+                    use_super = 1;
+                }
             } else {
                 use_super = 1;
             }

File pyobjc-core/NEWS.txt

View file
 Version 3.0
 -----------
 
+* Python integer values with values between 2 ** 63 and 2**64 are now proxied
+  as plain NSNumber objects, not as using PyObjC specific subclass of NSNumber,
+  to avoid a problem with writing them to binary plist files.
+
+  This is a workaround and will likely be changed in some future version.
+
 * ``inspect.signature`` works for all functions and methods implemented in C,
   when using Python 3.4 or later.
 

File pyobjc-framework-Cocoa/PyObjCTest/test_regr.py

View file
                 (AppKit.NSOpenGLPFAAccelerated,
                 AppKit.NSOpenGLPFANoRecovery, AppKit.NSOpenGLPFAColorSize, 32))
 
+    def testBinaryPlist(self):
+        pl = {
+            'key': 2 ** 64 - 1,
+        }
+        data, error = Foundation.NSPropertyListSerialization.dataWithPropertyList_format_options_error_(
+            pl, Foundation.NSPropertyListBinaryFormat_v1_0, 0, None)
+        restored, format, error = Foundation.NSPropertyListSerialization.propertyListWithData_options_format_error_(
+                data, 0, None, None)
+        self.assertEqual(pl, restored)
+
 if __name__ == "__main__":
     main()