File: objectobject.py

package info (click to toggle)
pypy3 7.3.19%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 212,236 kB
  • sloc: python: 2,098,316; ansic: 540,565; sh: 21,462; asm: 14,419; cpp: 4,451; makefile: 4,209; objc: 761; xml: 530; exp: 499; javascript: 314; pascal: 244; lisp: 45; csh: 12; awk: 4
file content (412 lines) | stat: -rw-r--r-- 15,409 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
"""The builtin object type implementation"""

from pypy.interpreter.baseobjspace import W_Root
from pypy.interpreter.error import OperationError, oefmt
from pypy.interpreter.gateway import applevel, interp2app, unwrap_spec
from pypy.interpreter.typedef import (
    GetSetProperty, TypeDef, default_identity_hash)
from pypy.objspace.descroperation import Object
from pypy.interpreter.function import StaticMethod

from rpython.rlib.objectmodel import specialize


app = applevel(r'''
import sys

def _abstract_method_error(typ):
    methods = ", ".join(sorted(typ.__abstractmethods__))
    method_s = 's' if len(typ.__abstractmethods__) > 1 else ''
    err = "Can't instantiate abstract class %s with abstract method%s %s"
    raise TypeError(err % (typ.__name__, method_s, methods))

def reduce_1(obj, proto):
    import copyreg
    return copyreg._reduce_ex(obj, proto)

def reduce_2(obj, proto, args, kwargs):
    cls = obj.__class__

    if not hasattr(type(obj), "__new__"):
        raise TypeError("can't pickle %s objects" % type(obj).__name__)

    try:
        copyreg = sys.modules['copyreg']
    except KeyError:
        import copyreg

    if not isinstance(args, tuple):
        raise TypeError("__getnewargs__ should return a tuple")
    if not kwargs:
       newobj = copyreg.__newobj__
       args2 = (cls,) + args
    else:
       newobj = copyreg.__newobj_ex__
       args2 = (cls, args, kwargs)
    state = obj.__getstate__()
    listitems = iter(obj) if isinstance(obj, list) else None
    dictitems = iter(obj.items()) if isinstance(obj, dict) else None

    return newobj, args2, state, listitems, dictitems


def get_slotvalues(obj):
    names = slotnames(obj.__class__)
    if not names:
        return None
    slots = {}
    for name in names:
        try:
            value = getattr(obj, name)
        except AttributeError:
            pass
        else:
            slots[name] =  value
    return slots


def slotnames(cls):
    if not isinstance(cls, type):
        return None

    try:
        return cls.__dict__["__slotnames__"]
    except KeyError:
        pass

    try:
        copyreg = sys.modules['copyreg']
    except KeyError:
        import copyreg
    slotnames = copyreg._slotnames(cls)
    if not isinstance(slotnames, list) and slotnames is not None:
        raise TypeError("copyreg._slotnames didn't return a list or None")
    return slotnames
''', filename=__file__)

_abstract_method_error = app.interphook("_abstract_method_error")
reduce_1 = app.interphook('reduce_1')
reduce_2 = app.interphook('reduce_2')
get_slotvalues = app.interphook('get_slotvalues')


class W_ObjectObject(W_Root):
    """Instances of this class are what the user can directly see with an
    'object()' call."""


def _excess_args(__args__):
    return bool(__args__.arguments_w) or bool(__args__.keyword_names_w)

@specialize.memo()
def _object_new(space):
    "Utility that returns the function object.__new__."
    w_x = space.lookup_in_type(space.w_object, '__new__')
    assert isinstance(w_x, StaticMethod)
    return w_x.w_function

@specialize.memo()
def _object_init(space):
    "Utility that returns the function object.__init__."
    return space.lookup_in_type(space.w_object, '__init__')

def _same_static_method(space, w_x, w_y):
    # pff pff pff
    if isinstance(w_x, StaticMethod): w_x = w_x.w_function
    return space.is_w(w_x, w_y)

def descr__new__(space, w_type, __args__):
    from pypy.objspace.std.typeobject import _precheck_for_new
    w_type = _precheck_for_new(space, w_type)

    if _excess_args(__args__):
        tp_new = space.lookup_in_type(w_type, '__new__')
        tp_init = space.lookup_in_type(w_type, '__init__')
        if not _same_static_method(space, tp_new, _object_new(space)):
            raise oefmt(space.w_TypeError,
                    "object.__new__() takes exactly one argument (the type to instantiate)")
        if space.is_w(tp_init, _object_init(space)):
            raise oefmt(space.w_TypeError,
                        "%s() takes no arguments", w_type.name)
    if w_type.is_abstract():
        _abstract_method_error(space, w_type)
    return space.allocate_instance(W_ObjectObject, w_type)


def descr___subclasshook__(space, __args__):
    return space.w_NotImplemented

def descr___init_subclass__(space, w_cls):
    return space.w_None

def descr__init__(space, w_obj, __args__):
    if _excess_args(__args__):
        w_type = space.type(w_obj)
        tp_new = space.lookup_in_type(w_type, '__new__')
        tp_init = space.lookup_in_type(w_type, '__init__')
        if not space.is_w(tp_init, _object_init(space)):
            raise oefmt(space.w_TypeError,
                        "object.__init__() takes exactly one argument (the instance to initialize)")
        elif _same_static_method(space, tp_new, _object_new(space)):
            raise oefmt(space.w_TypeError,
                        "%T.__init__() takes exactly one argument (the instance to initialize)",
                        w_obj)


def descr_get___class__(space, w_obj):
    return space.type(w_obj)


def descr_set___class__(space, w_obj, w_newcls):
    from pypy.objspace.std.typeobject import W_TypeObject
    from pypy.interpreter.module import Module
    #
    if not isinstance(w_newcls, W_TypeObject):
        raise oefmt(space.w_TypeError,
                    "__class__ must be set to a class, not '%T' "
                    "object", w_newcls)
    if not (w_newcls.is_heaptype() or
            w_newcls is space.gettypeobject(Module.typedef)):
        raise oefmt(space.w_TypeError,
                    "__class__ assignment only supported for heap types "
                    "or ModuleType subclasses")
    w_oldcls = space.type(w_obj)
    assert isinstance(w_oldcls, W_TypeObject)
    if (w_oldcls.get_full_instance_layout() ==
        w_newcls.get_full_instance_layout()):
        w_obj.setclass(space, w_newcls)
    else:
        raise oefmt(space.w_TypeError,
                    "__class__ assignment: '%N' object layout differs from "
                    "'%N'", w_oldcls, w_newcls)


def descr__repr__(space, w_obj):
    classname = space.getfulltypename(w_obj)
    return w_obj.getrepr(space, '%s object' % (classname,))


def descr__str__(space, w_obj):
    w_type = space.type(w_obj)
    w_impl = w_type.lookup("__repr__")
    if w_impl is None:
        # can it really occur?
        raise oefmt(space.w_TypeError, "operand does not support unary str")
    return space.get_and_call_function(w_impl, w_obj)


def _getnewargs(space, w_obj):
    w_descr = space.lookup(w_obj, '__getnewargs_ex__')
    hasargs = True
    if w_descr is not None:
        w_result = space.get_and_call_function(w_descr, w_obj)
        if not space.isinstance_w(w_result, space.w_tuple):
            raise oefmt(space.w_TypeError,
                "__getnewargs_ex__ should return a tuple, not '%T'", w_result)
        n = space.len_w(w_result)
        if n != 2:
            raise oefmt(space.w_ValueError,
                "__getnewargs_ex__ should return a tuple of length 2, not %d",
                n)
        w_args, w_kwargs = space.fixedview(w_result, 2)
        if not space.isinstance_w(w_args, space.w_tuple):
            raise oefmt(space.w_TypeError,
                "first item of the tuple returned by __getnewargs_ex__ must "
                "be a tuple, not '%T'", w_args)
        if not space.isinstance_w(w_kwargs, space.w_dict):
            raise oefmt(space.w_TypeError,
                "second item of the tuple returned by __getnewargs_ex__ must "
                "be a dict, not '%T'", w_kwargs)
    else:
        w_descr = space.lookup(w_obj, '__getnewargs__')
        if w_descr is not None:
            w_args = space.get_and_call_function(w_descr, w_obj)
            if not space.isinstance_w(w_args, space.w_tuple):
                raise oefmt(space.w_TypeError,
                    "__getnewargs__ should return a tuple, not '%T'", w_args)
        else:
            hasargs = False
            w_args = space.newtuple([])
        w_kwargs = space.w_None
    return hasargs, w_args, w_kwargs

def descr__getstate__(space, w_obj):
    """Helper for pickle"""
    return object_getstate_default(space, w_obj, 0)

def descr__reduce__(space, w_obj):
    """Helper for pickle"""
    w_proto = space.newint(0)
    return reduce_1(space, w_obj, w_proto)

def object_getstate_default(space, w_obj, required):
    w_obj_type = space.type(w_obj)
    if required and w_obj_type.layout.typedef.variable_sized:
        # never reached, required is always 0?
        raise oefmt(space.w_TypeError, "cannot pickle %N objects", w_obj)
    w_objdict = space.findattr(w_obj, space.newtext("__dict__"))
    if w_objdict and space.len_w(w_objdict) > 0:
        w_ret = space.call_method(w_objdict, 'copy')
    else:
        w_ret = space.w_None
    w_slots = get_slotvalues(space, w_obj)
    if w_slots is not space.w_None:
        w_ret = space.newtuple([w_ret, w_slots])
    return w_ret

@unwrap_spec(proto=int)
def descr__reduce_ex__(space, w_obj, proto):
    """Helper for pickle"""
    w_st_reduce = space.newtext('__reduce__')
    w_reduce = space.findattr(w_obj, w_st_reduce)
    if w_reduce is not None:
        # Check if __reduce__ has been overridden:
        # "type(obj).__reduce__ is not object.__reduce__"
        w_cls_reduce = space.getattr(space.type(w_obj), w_st_reduce)
        w_obj_reduce = space.getattr(space.w_object, w_st_reduce)
        override = not space.is_w(w_cls_reduce, w_obj_reduce)
        if override:
            return space.call_function(w_reduce)
    w_proto = space.newint(proto)
    if proto >= 2:
        hasargs, w_args, w_kwargs = _getnewargs(space, w_obj)
        w_getstate = space.lookup(w_obj, '__get_state__')
        if w_getstate is None:
            required = (not hasargs and
                not space.isinstance_w(w_obj, space.w_list) and
                not space.isinstance_w(w_obj, space.w_dict))
            w_obj_type = space.type(w_obj)
            if required and w_obj_type.layout.typedef.variable_sized:
                raise oefmt(
                    space.w_TypeError, "cannot pickle %N objects", w_obj_type)
        return reduce_2(space, w_obj, w_proto, w_args, w_kwargs)
    return reduce_1(space, w_obj, w_proto)

def descr___format__(space, w_obj, w_format_spec):
    if space.isinstance_w(w_format_spec, space.w_unicode):
        w_as_str = space.call_function(space.w_unicode, w_obj)
    elif space.isinstance_w(w_format_spec, space.w_bytes):
        w_as_str = space.str(w_obj)
    else:
        raise oefmt(space.w_TypeError, "format_spec must be a string")
    if space.len_w(w_format_spec) > 0:
        raise oefmt(space.w_TypeError,
                     "unsupported format string passed to %T.__format__",
                     w_obj);
    return space.format(w_as_str, w_format_spec)

def descr__eq__(space, w_self, w_other):
    if space.is_w(w_self, w_other):
        return space.w_True
    # Return NotImplemented instead of False, so if two objects are
    # compared, both get a chance at the comparison (issue #1393)
    return space.w_NotImplemented

def descr__ne__(space, w_self, w_other):
    # By default, __ne__() delegates to __eq__() and inverts the result,
    # unless the latter returns NotImplemented.
    w_eq = space.lookup(w_self, '__eq__')
    w_res = space.get_and_call_function(w_eq, w_self, w_other)
    if space.is_w(w_res, space.w_NotImplemented):
        return w_res
    return space.not_(w_res)

def descr_richcompare(space, w_self, w_other):
    return space.w_NotImplemented

def descr__dir__(space, w_obj):
    from pypy.objspace.std.util import _objectdir
    return space.call_function(space.w_list, _objectdir(space, w_obj))

class ObjectObjectDocstrings:

    def __new__():
        """T.__new__(S, ...) -> a new object with type S, a subtype of T"""

    def __subclasshook__():
        """Abstract classes can override this to customize issubclass().

        This is invoked early on by abc.ABCMeta.__subclasscheck__().
        It should return True, False or NotImplemented.  If it returns
        NotImplemented, the normal algorithm is used.  Otherwise, it
        overrides the normal algorithm (and the outcome is cached).
        """

    def __hash__():
        """x.__hash__() <==> hash(x)"""

    def __setattr__():
        """x.__setattr__('name', value) <==> x.name = value"""

    def __getattribute__():
        """"x.__getattribute__('name') <==> x.name"""

    def __delattr__():
        """x.__delattr__('name') <==> del x.name"""

    def __init__():
        """x.__init__(...) initializes x; see help(type(x)) for signature."""

    def __class__():
        """type(object) -> the object's type
        type(name, bases, dict) -> a new type"""

    def __repr__():
        """x.__repr__() <==> repr(x)"""

    def __str__():
        """x.__str__() <==> str(x)"""

    def __reduce__():
        """helper for pickle"""

    def __reduce_ex__():
        """helper for pickle"""

    def __format__():
        """default object formatter"""

W_ObjectObject.typedef = TypeDef("object",
    __rpython_level_class__ = W_ObjectObject,
    _text_signature_='()',
    __doc__ = "The most base type",
    __new__ = interp2app(descr__new__,
                         doc=ObjectObjectDocstrings.__new__.__doc__),
    __subclasshook__ = interp2app(descr___subclasshook__, as_classmethod=True,
                                  doc=ObjectObjectDocstrings.__subclasshook__.__doc__),
    __init_subclass__ = interp2app(descr___init_subclass__, as_classmethod=True),

    # these are actually implemented in pypy.objspace.descroperation
    __getattribute__ = interp2app(Object.descr__getattribute__.im_func,
                                  doc=ObjectObjectDocstrings.__getattribute__.__doc__),
    __setattr__ = interp2app(Object.descr__setattr__.im_func,
                             doc=ObjectObjectDocstrings.__setattr__.__doc__),
    __delattr__ = interp2app(Object.descr__delattr__.im_func,
                             doc=ObjectObjectDocstrings.__delattr__.__doc__),

    __getstate__ = interp2app(descr__getstate__),
    __init__ = interp2app(descr__init__,
                          doc=ObjectObjectDocstrings.__init__.__doc__),
    __class__ = GetSetProperty(descr_get___class__, descr_set___class__,
                               doc=ObjectObjectDocstrings.__class__.__doc__),
    __repr__ = interp2app(descr__repr__,
                          doc=ObjectObjectDocstrings.__repr__.__doc__),
    __str__ = interp2app(descr__str__,
                         doc=ObjectObjectDocstrings.__str__.__doc__),
    __hash__ = interp2app(default_identity_hash,
                          doc=ObjectObjectDocstrings.__hash__.__doc__),
    __reduce__ = interp2app(descr__reduce__,
                            doc=ObjectObjectDocstrings.__reduce__.__doc__),
    __reduce_ex__ = interp2app(descr__reduce_ex__,
                               doc=ObjectObjectDocstrings.__reduce_ex__.__doc__),
    __format__ = interp2app(descr___format__,
                            doc=ObjectObjectDocstrings.__format__.__doc__),
    __dir__ = interp2app(descr__dir__),

    __eq__ = interp2app(descr__eq__),
    __ne__ = interp2app(descr__ne__),
    __le__ = interp2app(descr_richcompare),
    __lt__ = interp2app(descr_richcompare),
    __ge__ = interp2app(descr_richcompare),
    __gt__ = interp2app(descr_richcompare),
)