1from objc import _objc
2import sys
3
4__all__ = []
5
6
7class OC_PythonFloat(float):
8    __slots__=('__pyobjc_object__',)
9
10
11    def __new__(cls, obj, value):
12        self = float.__new__(cls, value)
13        self.__pyobjc_object__ = obj
14        return self
15
16    __class__ = property(lambda self: self.__pyobjc_object__.__class__)
17
18    def __getattr__(self, attr):
19        return getattr(self.__pyobjc_object__, attr)
20
21    def __reduce__(self):
22        return (float, (float(self),))
23
24if sys.version_info[0] == 2:
25    class OC_PythonLong(long):
26
27        def __new__(cls, obj, value):
28            self = long.__new__(cls, value)
29            self.__pyobjc_object__ = obj
30            return self
31
32        __class__ = property(lambda self: self.__pyobjc_object__.__class__)
33
34        def __getattr__(self, attr):
35            return getattr(self.__pyobjc_object__, attr)
36
37        # The long type doesn't support __slots__ on subclasses, fake
38        # one part of the effect of __slots__: don't allow setting of attributes.
39        def __setattr__(self, attr, value):
40            if attr != '__pyobjc_object__':
41                raise AttributeError, "'%s' object has no attribute '%s')"%(self.__class__.__name__, attr)
42            self.__dict__['__pyobjc_object__'] = value
43
44        def __reduce__(self):
45            return (long, (long(self),))
46
47    class OC_PythonInt(int):
48        __slots__=('__pyobjc_object__',)
49
50        def __new__(cls, obj, value):
51            self = int.__new__(cls, value)
52            self.__pyobjc_object__ = obj
53            return self
54
55        __class__ = property(lambda self: self.__pyobjc_object__.__class__)
56
57        def __getattr__(self, attr):
58            return getattr(self.__pyobjc_object__, attr)
59
60        def __reduce__(self):
61            return (int, (int(self),))
62
63else:
64    class OC_PythonLong(int):
65
66        def __new__(cls, obj, value):
67            self = long.__new__(cls, value)
68            self.__pyobjc_object__ = obj
69            return self
70
71        __class__ = property(lambda self: self.__pyobjc_object__.__class__)
72
73        def __getattr__(self, attr):
74            return getattr(self.__pyobjc_object__, attr)
75
76        # The long type doesn't support __slots__ on subclasses, fake
77        # one part of the effect of __slots__: don't allow setting of attributes.
78        def __setattr__(self, attr, value):
79            if attr != '__pyobjc_object__':
80                raise AttributeError, "'%s' object has no attribute '%s')"%(self.__class__.__name__, attr)
81            self.__dict__['__pyobjc_object__'] = value
82
83        def __reduce__(self):
84            return (long, (long(self),))
85
86NSNumber = _objc.lookUpClass('NSNumber')
87NSDecimalNumber = _objc.lookUpClass('NSDecimalNumber')
88Foundation = None
89
90def numberWrapper(obj):
91    if isinstance(obj, NSDecimalNumber):
92        return obj
93        # ensure that NSDecimal is around
94        global Foundation
95        if Foundation is None:
96            import Foundation
97        # return NSDecimal
98        return Foundation.NSDecimal(obj)
99    try:
100        tp = obj.objCType()
101    except AttributeError:
102        import warnings
103        warnings.warn(RuntimeWarning, "NSNumber instance doesn't implement objCType? %r" % (obj,))
104        return obj
105    if tp in b'qQLfd':
106        if tp == b'q':
107            return OC_PythonLong(obj, obj.longLongValue())
108        elif tp in b'QL':
109            return OC_PythonLong(obj, obj.unsignedLongLongValue())
110        elif tp == 'd':
111            return OC_PythonFloat(obj, obj.doubleValue())
112        else:
113            return OC_PythonFloat(obj, obj.floatValue())
114    elif sys.version_info[0] == 2:
115        return OC_PythonInt(obj, obj.longValue())
116    else:
117        return OC_PythonLong(obj, obj.longValue())
118
119_objc._setNSNumberWrapper(numberWrapper)
120