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
24base_class = int if sys.version_info[0] >= 3 else long
25
26class OC_PythonLong(base_class):
27
28    def __new__(cls, obj, value):
29        self = base_class.__new__(cls, value)
30        self.__pyobjc_object__ = obj
31        return self
32
33    __class__ = property(lambda self: self.__pyobjc_object__.__class__)
34
35    def __getattr__(self, attr):
36        return getattr(self.__pyobjc_object__, attr)
37
38    # The long type doesn't support __slots__ on subclasses, fake
39    # one part of the effect of __slots__: don't allow setting of attributes.
40    def __setattr__(self, attr, value):
41        if attr != '__pyobjc_object__':
42            raise AttributeError("'%s' object has no attribute '%s')"%(self.__class__.__name__, attr))
43        self.__dict__['__pyobjc_object__'] = value
44
45    def __reduce__(self):
46        return (base_class, (base_class(self),))
47
48
49if sys.version_info[0] == 2:
50    class OC_PythonInt(int):
51        __slots__=('__pyobjc_object__',)
52
53        def __new__(cls, obj, value):
54            self = int.__new__(cls, value)
55            self.__pyobjc_object__ = obj
56            return self
57
58        __class__ = property(lambda self: self.__pyobjc_object__.__class__)
59
60        def __getattr__(self, attr):
61            return getattr(self.__pyobjc_object__, attr)
62
63        def __reduce__(self):
64            return (int, (int(self),))
65
66
67NSNumber = _objc.lookUpClass('NSNumber')
68NSDecimalNumber = _objc.lookUpClass('NSDecimalNumber')
69Foundation = None
70
71def numberWrapper(obj):
72    if isinstance(obj, NSDecimalNumber):
73        return obj
74
75    try:
76        tp = obj.objCType()
77    except AttributeError:
78        import warnings
79        warnings.warn("NSNumber instance doesn't implement objCType? %r" % (obj,), RuntimeWarning)
80        return obj
81
82    if tp in b'qQLfd':
83        if tp == b'q':
84            return OC_PythonLong(obj, obj.longLongValue())
85        elif tp in b'QL':
86            return OC_PythonLong(obj, obj.unsignedLongLongValue())
87        else:
88            return OC_PythonFloat(obj, obj.doubleValue())
89    elif sys.version_info[0] == 2:
90        return OC_PythonInt(obj, obj.longValue())
91    else: # pragma: no cover (py3k)
92        return OC_PythonLong(obj, obj.longValue())
93
94_objc._setNSNumberWrapper(numberWrapper)
95