PageRenderTime 76ms CodeModel.GetById 12ms app.highlight 55ms RepoModel.GetById 1ms app.codeStats 0ms

/pypy/module/__builtin__/interp_classobj.py

https://bitbucket.org/pypy/pypy/
Python | 735 lines | 618 code | 83 blank | 34 comment | 183 complexity | 8a7438dcf0f24594524a22c3cf0fbc22 MD5 | raw file
  1import new
  2from pypy.interpreter.error import OperationError, oefmt
  3from pypy.interpreter.gateway import interp2app, unwrap_spec
  4from pypy.interpreter.typedef import TypeDef, make_weakref_descr
  5from pypy.interpreter.baseobjspace import W_Root
  6from pypy.interpreter.typedef import GetSetProperty, descr_get_dict, descr_set_dict
  7from rpython.rlib.objectmodel import compute_identity_hash
  8from rpython.rlib.debug import make_sure_not_resized
  9from rpython.rlib import jit
 10
 11
 12def raise_type_err(space, argument, expected, w_obj):
 13    raise oefmt(space.w_TypeError,
 14                "argument %s must be %s, not %T", argument, expected, w_obj)
 15
 16def descr_classobj_new(space, w_subtype, w_name, w_bases, w_dict):
 17    if not space.isinstance_w(w_bases, space.w_tuple):
 18        raise_type_err(space, 'bases', 'tuple', w_bases)
 19
 20    if not space.isinstance_w(w_dict, space.w_dict):
 21        raise_type_err(space, 'bases', 'tuple', w_bases)
 22
 23    if not space.contains_w(w_dict, space.wrap("__doc__")):
 24        space.setitem(w_dict, space.wrap("__doc__"), space.w_None)
 25
 26    # XXX missing: lengthy and obscure logic about "__module__"
 27
 28    bases_w = space.fixedview(w_bases)
 29    for w_base in bases_w:
 30        if not isinstance(w_base, W_ClassObject):
 31            w_metaclass = space.type(w_base)
 32            if space.is_true(space.callable(w_metaclass)):
 33                return space.call_function(w_metaclass, w_name,
 34                                           w_bases, w_dict)
 35            raise oefmt(space.w_TypeError, "base must be class")
 36
 37    return W_ClassObject(space, w_name, bases_w, w_dict)
 38
 39
 40class W_ClassObject(W_Root):
 41    def __init__(self, space, w_name, bases, w_dict):
 42        self.name = space.str_w(w_name)
 43        make_sure_not_resized(bases)
 44        self.bases_w = bases
 45        self.w_dict = w_dict
 46
 47    def has_user_del(self, space):
 48        return self.lookup(space, '__del__') is not None
 49
 50    def instantiate(self, space):
 51        cache = space.fromcache(Cache)
 52        return cache.InstanceObjectCls(space, self)
 53
 54    def getdict(self, space):
 55        return self.w_dict
 56
 57    def setdict(self, space, w_dict):
 58        if not space.isinstance_w(w_dict, space.w_dict):
 59            raise oefmt(space.w_TypeError,
 60                        "__dict__ must be a dictionary object")
 61        self.w_dict = w_dict
 62
 63    def setname(self, space, w_newname):
 64        if not space.isinstance_w(w_newname, space.w_str):
 65            raise oefmt(space.w_TypeError, "__name__ must be a string object")
 66        self.name = space.str_w(w_newname)
 67
 68    def setbases(self, space, w_bases):
 69        if not space.isinstance_w(w_bases, space.w_tuple):
 70            raise oefmt(space.w_TypeError, "__bases__ must be a tuple object")
 71        bases_w = space.fixedview(w_bases)
 72        for w_base in bases_w:
 73            if not isinstance(w_base, W_ClassObject):
 74                raise oefmt(space.w_TypeError,
 75                            "__bases__ items must be classes")
 76        self.bases_w = bases_w
 77
 78    def is_subclass_of(self, other):
 79        assert isinstance(other, W_ClassObject)
 80        if self is other:
 81            return True
 82        for base in self.bases_w:
 83            assert isinstance(base, W_ClassObject)
 84            if base.is_subclass_of(other):
 85                return True
 86        return False
 87
 88    @jit.unroll_safe
 89    def lookup(self, space, attr):
 90        # returns w_value or interplevel None
 91        w_result = space.finditem_str(self.w_dict, attr)
 92        if w_result is not None:
 93            return w_result
 94        for base in self.bases_w:
 95            # XXX fix annotation of bases_w to be a list of W_ClassObjects
 96            assert isinstance(base, W_ClassObject)
 97            w_result = base.lookup(space, attr)
 98            if w_result is not None:
 99                return w_result
100        return None
101
102    @unwrap_spec(name=str)
103    def descr_getattribute(self, space, name):
104        if name and name[0] == "_":
105            if name == "__dict__":
106                return self.w_dict
107            elif name == "__name__":
108                return space.wrap(self.name)
109            elif name == "__bases__":
110                return space.newtuple(self.bases_w)
111        w_value = self.lookup(space, name)
112        if w_value is None:
113            raise oefmt(space.w_AttributeError,
114                        "class %s has no attribute '%s'", self.name, name)
115
116        w_descr_get = space.lookup(w_value, '__get__')
117        if w_descr_get is None:
118            return w_value
119        return space.call_function(w_descr_get, w_value, space.w_None, self)
120
121    def descr_setattr(self, space, w_attr, w_value):
122        name = space.str_w(w_attr)
123        if name and name[0] == "_":
124            if name == "__dict__":
125                self.setdict(space, w_value)
126                return
127            elif name == "__name__":
128                self.setname(space, w_value)
129                return
130            elif name == "__bases__":
131                self.setbases(space, w_value)
132                return
133            elif name == "__del__":
134                if not self.has_user_del(space):
135                    msg = ("a __del__ method added to an existing class will "
136                           "only be called on instances made from now on")
137                    space.warn(space.wrap(msg), space.w_RuntimeWarning)
138        space.setitem(self.w_dict, w_attr, w_value)
139
140    def descr_delattr(self, space, w_attr):
141        name = space.str_w(w_attr)
142        if name in ("__dict__", "__name__", "__bases__"):
143            raise oefmt(space.w_TypeError,
144                        "cannot delete attribute '%s'", name)
145        try:
146            space.delitem(self.w_dict, w_attr)
147        except OperationError as e:
148            if not e.match(space, space.w_KeyError):
149                raise
150            raise oefmt(space.w_AttributeError,
151                        "class %s has no attribute '%s'", self.name, name)
152
153    def descr_repr(self, space):
154        mod = self.get_module_string(space)
155        return self.getrepr(space, "class %s.%s" % (mod, self.name))
156
157    def descr_str(self, space):
158        mod = self.get_module_string(space)
159        if mod == "?":
160            return space.wrap(self.name)
161        else:
162            return space.wrap("%s.%s" % (mod, self.name))
163
164    def get_module_string(self, space):
165        try:
166            w_mod = self.descr_getattribute(space, "__module__")
167        except OperationError as e:
168            if not e.match(space, space.w_AttributeError):
169                raise
170            return "?"
171        if space.isinstance_w(w_mod, space.w_str):
172            return space.str_w(w_mod)
173        return "?"
174
175    def __repr__(self):
176        # NOT_RPYTHON
177        return '<W_ClassObject(%s)>' % self.name
178
179class Cache:
180    def __init__(self, space):
181        from pypy.interpreter.typedef import _getusercls
182
183        if hasattr(space, 'is_fake_objspace'):
184            # hack: with the fake objspace, we don't want to see typedef's
185            # _getusercls() at all
186            self.InstanceObjectCls = W_InstanceObject
187            return
188
189        self.InstanceObjectCls = _getusercls(
190                W_InstanceObject, reallywantdict=True)
191
192
193def class_descr_call(space, w_self, __args__):
194    self = space.interp_w(W_ClassObject, w_self)
195    w_inst = self.instantiate(space)
196    w_init = w_inst.getattr_from_class(space, '__init__')
197    if w_init is not None:
198        w_result = space.call_args(w_init, __args__)
199        if not space.is_w(w_result, space.w_None):
200            raise oefmt(space.w_TypeError, "__init__() should return None")
201    elif __args__.arguments_w or __args__.keywords:
202        raise oefmt(space.w_TypeError, "this constructor takes no arguments")
203    return w_inst
204
205W_ClassObject.typedef = TypeDef("classobj",
206    __new__ = interp2app(descr_classobj_new),
207    __repr__ = interp2app(W_ClassObject.descr_repr),
208    __str__ = interp2app(W_ClassObject.descr_str),
209    __call__ = interp2app(class_descr_call),
210    __getattribute__ = interp2app(W_ClassObject.descr_getattribute),
211    __setattr__ = interp2app(W_ClassObject.descr_setattr),
212    __delattr__ = interp2app(W_ClassObject.descr_delattr),
213    __weakref__ = make_weakref_descr(W_ClassObject),
214)
215W_ClassObject.typedef.acceptable_as_base_class = False
216
217
218def make_unary_instance_method(name):
219    def unaryop(self, space):
220        w_meth = self.getattr(space, name, True)
221        return space.call_function(w_meth)
222    unaryop.func_name = name
223    return unaryop
224
225def make_binary_returning_notimplemented_instance_method(name):
226    def binaryop(self, space, w_other):
227        try:
228            w_meth = self.getattr(space, name, False)
229        except OperationError as e:
230            if e.match(space, space.w_AttributeError):
231                return space.w_NotImplemented
232            raise
233        else:
234            if w_meth is None:
235                return space.w_NotImplemented
236            return space.call_function(w_meth, w_other)
237    binaryop.func_name = name
238    return binaryop
239
240def make_binary_instance_method(name):
241    specialname = "__%s__" % (name, )
242    rspecialname = "__r%s__" % (name, )
243    objspacename = name
244    if name in ['and', 'or']:
245        objspacename = name + '_'
246
247    def binaryop(self, space, w_other):
248        w_a, w_b = _coerce_helper(space, self, w_other)
249        if isinstance(w_a, W_InstanceObject):
250            w_meth = w_a.getattr(space, specialname, False)
251            if w_meth is None:
252                return space.w_NotImplemented
253            return space.call_function(w_meth, w_b)
254        else:
255            # fall back to space.xxx() if coerce returns a non-W_Instance
256            # object as first argument
257            return getattr(space, objspacename)(w_a, w_b)
258    binaryop.func_name = name
259
260    def rbinaryop(self, space, w_other):
261        w_a, w_b = _coerce_helper(space, self, w_other)
262        if isinstance(w_a, W_InstanceObject):
263            w_meth = w_a.getattr(space, rspecialname, False)
264            if w_meth is None:
265                return space.w_NotImplemented
266            return space.call_function(w_meth, w_b)
267        else:
268            # fall back to space.xxx() if coerce returns a non-W_Instance
269            # object as first argument
270            return getattr(space, objspacename)(w_b, w_a)
271    rbinaryop.func_name = "r" + name
272    return binaryop, rbinaryop
273
274def _coerce_helper(space, w_self, w_other):
275    try:
276        w_tup = space.coerce(w_self, w_other)
277    except OperationError as e:
278        if not e.match(space, space.w_TypeError):
279            raise
280        return [w_self, w_other]
281    return space.fixedview(w_tup, 2)
282
283def descr_instance_new(space, w_type, w_class, w_dict=None):
284    # w_type is not used at all
285    if not isinstance(w_class, W_ClassObject):
286        raise oefmt(space.w_TypeError, "instance() first arg must be class")
287    w_result = w_class.instantiate(space)
288    if not space.is_none(w_dict):
289        w_result.setdict(space, w_dict)
290    return w_result
291
292
293class W_InstanceObject(W_Root):
294    def __init__(self, space, w_class):
295        # note that user_setup is overridden by the typedef.py machinery
296        self.space = space
297        self.user_setup(space, space.gettypeobject(self.typedef))
298        assert isinstance(w_class, W_ClassObject)
299        self.w_class = w_class
300        if w_class.has_user_del(space):
301            space.finalizer_queue.register_finalizer(self)
302
303    def user_setup(self, space, w_subtype):
304        pass
305
306    def set_oldstyle_class(self, space, w_class):
307        if w_class is None or not isinstance(w_class, W_ClassObject):
308            raise oefmt(space.w_TypeError, "__class__ must be set to a class")
309        self.w_class = w_class
310
311    def getattr_from_class(self, space, name):
312        # Look up w_name in the class dict, and call its __get__.
313        # This method ignores the instance dict and the __getattr__.
314        # Returns None if not found.
315        assert isinstance(name, str)
316        w_value = self.w_class.lookup(space, name)
317        if w_value is None:
318            return None
319        w_descr_get = space.lookup(w_value, '__get__')
320        if w_descr_get is None:
321            return w_value
322        return space.call_function(w_descr_get, w_value, self, self.w_class)
323
324    def getattr(self, space, name, exc=True):
325        # Normal getattr rules: look up w_name in the instance dict,
326        # in the class dict, and then via a call to __getatttr__.
327        assert isinstance(name, str)
328        w_result = self.getdictvalue(space, name)
329        if w_result is not None:
330            return w_result
331        w_result = self.getattr_from_class(space, name)
332        if w_result is not None:
333            return w_result
334        w_meth = self.getattr_from_class(space, '__getattr__')
335        if w_meth is not None:
336            try:
337                return space.call_function(w_meth, space.wrap(name))
338            except OperationError as e:
339                if not exc and e.match(space, space.w_AttributeError):
340                    return None     # eat the AttributeError
341                raise
342        # not found at all
343        if exc:
344            raise oefmt(space.w_AttributeError,
345                        "%s instance has no attribute '%s'",
346                        self.w_class.name, name)
347        else:
348            return None
349
350    @unwrap_spec(name=str)
351    def descr_getattribute(self, space, name):
352        if len(name) >= 8 and name[0] == '_':
353            if name == "__dict__":
354                return self.getdict(space)
355            elif name == "__class__":
356                return self.w_class
357        return self.getattr(space, name)
358
359    def descr_setattr(self, space, w_name, w_value):
360        name = space.str_w(w_name)
361        w_meth = self.getattr_from_class(space, '__setattr__')
362        if name and name[0] == "_":
363            if name == '__dict__':
364                self.setdict(space, w_value)
365                return
366            if name == '__class__':
367                self.set_oldstyle_class(space, w_value)
368                return
369            if name == '__del__' and w_meth is None:
370                if (not self.w_class.has_user_del(space)
371                    and self.getdictvalue(space, '__del__') is None):
372                    msg = ("a __del__ method added to an instance with no "
373                           "__del__ in the class will not be called")
374                    space.warn(space.wrap(msg), space.w_RuntimeWarning)
375        if w_meth is not None:
376            space.call_function(w_meth, w_name, w_value)
377        else:
378            self.setdictvalue(space, name, w_value)
379
380    def descr_delattr(self, space, w_name):
381        name = space.str_w(w_name)
382        if name and name[0] == "_":
383            if name == '__dict__':
384                # use setdict to raise the error
385                self.setdict(space, space.w_None)
386                return
387            elif name == '__class__':
388                # use set_oldstyle_class to raise the error
389                self.set_oldstyle_class(space, None)
390                return
391        w_meth = self.getattr_from_class(space, '__delattr__')
392        if w_meth is not None:
393            space.call_function(w_meth, w_name)
394        else:
395            if not self.deldictvalue(space, name):
396                raise oefmt(space.w_AttributeError,
397                            "%s instance has no attribute '%s'",
398                            self.w_class.name, name)
399
400    def descr_repr(self, space):
401        w_meth = self.getattr(space, '__repr__', False)
402        if w_meth is None:
403            w_class = self.w_class
404            mod = w_class.get_module_string(space)
405            return self.getrepr(space, "%s.%s instance" % (mod, w_class.name))
406        return space.call_function(w_meth)
407
408    def descr_str(self, space):
409        w_meth = self.getattr(space, '__str__', False)
410        if w_meth is None:
411            return self.descr_repr(space)
412        return space.call_function(w_meth)
413
414    def descr_unicode(self, space):
415        w_meth = self.getattr(space, '__unicode__', False)
416        if w_meth is None:
417            return self.descr_str(space)
418        return space.call_function(w_meth)
419
420    def descr_format(self, space, w_format_spec):
421        w_meth = self.getattr(space, "__format__", False)
422        if w_meth is not None:
423            return space.call_function(w_meth, w_format_spec)
424        else:
425            if space.isinstance_w(w_format_spec, space.w_unicode):
426                w_as_str = self.descr_unicode(space)
427            else:
428                w_as_str = self.descr_str(space)
429            if space.len_w(w_format_spec) > 0:
430                msg = ("object.__format__ with a non-empty format string is "
431                       "deprecated")
432                space.warn(space.wrap(msg), space.w_PendingDeprecationWarning)
433            return space.format(w_as_str, w_format_spec)
434
435    def descr_len(self, space):
436        w_meth = self.getattr(space, '__len__')
437        w_result = space.call_function(w_meth)
438        if space.isinstance_w(w_result, space.w_int):
439            if space.is_true(space.lt(w_result, space.wrap(0))):
440                raise oefmt(space.w_ValueError, "__len__() should return >= 0")
441            return w_result
442        raise oefmt(space.w_TypeError, "__len__() should return an int")
443
444    def descr_getitem(self, space, w_key):
445        w_meth = self.getattr(space, '__getitem__')
446        return space.call_function(w_meth, w_key)
447
448    def descr_setitem(self, space, w_key, w_value):
449        w_meth = self.getattr(space, '__setitem__')
450        space.call_function(w_meth, w_key, w_value)
451
452    def descr_delitem(self, space, w_key):
453        w_meth = self.getattr(space, '__delitem__')
454        space.call_function(w_meth, w_key)
455
456    def descr_iter(self, space):
457        w_meth = self.getattr(space, '__iter__', False)
458        if w_meth is not None:
459            return space.call_function(w_meth)
460        w_meth = self.getattr(space, '__getitem__', False)
461        if w_meth is None:
462            raise oefmt(space.w_TypeError, "iteration over non-sequence")
463        return space.newseqiter(self)
464    #XXX do I really need a next method? the old implementation had one, but I
465    # don't see the point
466
467    def descr_getslice(self, space, w_i, w_j):
468        w_meth = self.getattr(space, '__getslice__', False)
469        if w_meth is not None:
470            return space.call_function(w_meth, w_i, w_j)
471        else:
472            return space.getitem(self, space.newslice(w_i, w_j, space.w_None))
473
474    def descr_setslice(self, space, w_i, w_j, w_sequence):
475        w_meth = self.getattr(space, '__setslice__', False)
476        if w_meth is not None:
477            space.call_function(w_meth, w_i, w_j, w_sequence)
478        else:
479            space.setitem(self, space.newslice(w_i, w_j, space.w_None),
480                          w_sequence)
481
482    def descr_delslice(self, space, w_i, w_j):
483        w_meth = self.getattr(space, '__delslice__', False)
484        if w_meth is not None:
485            space.call_function(w_meth, w_i, w_j)
486        else:
487            return space.delitem(self, space.newslice(w_i, w_j, space.w_None))
488
489    def descr_call(self, space, __args__):
490        w_meth = self.getattr(space, '__call__')
491        return space.call_args(w_meth, __args__)
492
493    def descr_nonzero(self, space):
494        w_func = self.getattr(space, '__nonzero__', False)
495        if w_func is None:
496            w_func = self.getattr(space, '__len__', False)
497            if w_func is None:
498                return space.w_True
499        w_result = space.call_function(w_func)
500        if space.isinstance_w(w_result, space.w_int):
501            if space.is_true(space.lt(w_result, space.wrap(0))):
502                raise oefmt(space.w_ValueError,
503                            "__nonzero__() should return >= 0")
504            return w_result
505        raise oefmt(space.w_TypeError, "__nonzero__() should return an int")
506
507    def descr_cmp(self, space, w_other): # do all the work here like CPython
508        w_a, w_b = _coerce_helper(space, self, w_other)
509        if (not isinstance(w_a, W_InstanceObject) and
510            not isinstance(w_b, W_InstanceObject)):
511            return space.cmp(w_a, w_b)
512        if isinstance(w_a, W_InstanceObject):
513            w_func = w_a.getattr(space, '__cmp__', False)
514            if w_func is not None:
515                w_res = space.call_function(w_func, w_b)
516                if space.is_w(w_res, space.w_NotImplemented):
517                    return w_res
518                try:
519                    res = space.int_w(w_res)
520                except OperationError as e:
521                    if e.match(space, space.w_TypeError):
522                        raise oefmt(space.w_TypeError,
523                                    "__cmp__ must return int")
524                    raise
525                if res > 0:
526                    return space.wrap(1)
527                if res < 0:
528                    return space.wrap(-1)
529                return space.wrap(0)
530        if isinstance(w_b, W_InstanceObject):
531            w_func = w_b.getattr(space, '__cmp__', False)
532            if w_func is not None:
533                w_res = space.call_function(w_func, w_a)
534                if space.is_w(w_res, space.w_NotImplemented):
535                    return w_res
536                try:
537                    res = space.int_w(w_res)
538                except OperationError as e:
539                    if e.match(space, space.w_TypeError):
540                        raise oefmt(space.w_TypeError,
541                                    "__cmp__ must return int")
542                    raise
543                if res < 0:
544                    return space.wrap(1)
545                if res > 0:
546                    return space.wrap(-1)
547                return space.wrap(0)
548        return space.w_NotImplemented
549
550    def descr_hash(self, space):
551        w_func = self.getattr(space, '__hash__', False)
552        if w_func is None:
553            w_eq = self.getattr(space, '__eq__', False)
554            w_cmp = self.getattr(space, '__cmp__', False)
555            if w_eq is not None or w_cmp is not None:
556                raise oefmt(space.w_TypeError, "unhashable instance")
557            else:
558                return space.wrap(compute_identity_hash(self))
559        w_ret = space.call_function(w_func)
560        if (not space.isinstance_w(w_ret, space.w_int) and
561            not space.isinstance_w(w_ret, space.w_long)):
562            raise oefmt(space.w_TypeError, "__hash__ must return int or long")
563        return w_ret
564
565    def descr_int(self, space):
566        w_func = self.getattr(space, '__int__', False)
567        if w_func is not None:
568            return space.call_function(w_func)
569
570        w_truncated = space.trunc(self)
571        # int() needs to return an int
572        try:
573            return space.int(w_truncated)
574        except OperationError:
575            # Raise a different error
576            raise oefmt(space.w_TypeError, "__trunc__ returned non-Integral")
577
578    def descr_long(self, space):
579        w_func = self.getattr(space, '__long__', False)
580        if w_func is not None:
581            return space.call_function(w_func)
582        return self.descr_int(space)
583
584    def descr_index(self, space):
585        w_func = self.getattr(space, '__index__', False)
586        if w_func is not None:
587            return space.call_function(w_func)
588        raise oefmt(space.w_TypeError,
589                    "object cannot be interpreted as an index")
590
591    def descr_contains(self, space, w_obj):
592        w_func = self.getattr(space, '__contains__', False)
593        if w_func is not None:
594            return space.wrap(space.is_true(space.call_function(w_func, w_obj)))
595        # now do it ourselves
596        w_iter = space.iter(self)
597        while 1:
598            try:
599                w_x = space.next(w_iter)
600            except OperationError as e:
601                if e.match(space, space.w_StopIteration):
602                    return space.w_False
603                raise
604            if space.eq_w(w_x, w_obj):
605                return space.w_True
606
607    def descr_pow(self, space, w_other, w_modulo=None):
608        if space.is_none(w_modulo):
609            w_a, w_b = _coerce_helper(space, self, w_other)
610            if isinstance(w_a, W_InstanceObject):
611                w_func = w_a.getattr(space, '__pow__', False)
612                if w_func is None:
613                    return space.w_NotImplemented
614                return space.call_function(w_func, w_other)
615            else:
616                return space.pow(w_a, w_b, space.w_None)
617        else:
618            # CPython also doesn't try coercion in this case
619            w_func = self.getattr(space, '__pow__', False)
620            if w_func is None:
621                return space.w_NotImplemented
622            return space.call_function(w_func, w_other, w_modulo)
623
624    def descr_rpow(self, space, w_other, w_modulo=None):
625        if space.is_none(w_modulo):
626            w_a, w_b = _coerce_helper(space, self, w_other)
627            if isinstance(w_a, W_InstanceObject):
628                w_func = w_a.getattr(space, '__rpow__', False)
629                if w_func is None:
630                    return space.w_NotImplemented
631                return space.call_function(w_func, w_other)
632            else:
633                return space.pow(w_b, w_a, space.w_None)
634        else:
635            # CPython also doesn't try coercion in this case
636            w_func = self.getattr(space, '__rpow__', False)
637            if w_func is None:
638                return space.w_NotImplemented
639            return space.call_function(w_func, w_other, w_modulo)
640
641    def descr_next(self, space):
642        w_func = self.getattr(space, 'next', False)
643        if w_func is None:
644            raise oefmt(space.w_TypeError, "instance has no next() method")
645        return space.call_function(w_func)
646
647    def _finalize_(self):
648        space = self.space
649        w_func = self.getdictvalue(space, '__del__')
650        if w_func is None:
651            w_func = self.getattr_from_class(space, '__del__')
652        if w_func is not None:
653            if self.space.user_del_action.gc_disabled(self):
654                return
655            space.call_function(w_func)
656
657    def descr_exit(self, space, w_type, w_value, w_tb):
658        w_func = self.getattr(space, '__exit__', False)
659        if w_func is not None:
660            return space.call_function(w_func, w_type, w_value, w_tb)
661
662rawdict = {}
663
664# unary operations
665for op in "neg pos abs invert trunc float oct hex enter reversed".split():
666    specialname = "__%s__" % (op, )
667    # fool the gateway logic by giving it a real unbound method
668    meth = new.instancemethod(
669        make_unary_instance_method(specialname),
670        None,
671        W_InstanceObject)
672    rawdict[specialname] = interp2app(meth)
673
674# binary operations that return NotImplemented if they fail
675# e.g. rich comparisons, coerce and inplace ops
676for op in 'eq ne gt lt ge le coerce imod iand ipow itruediv ilshift ixor irshift ifloordiv idiv isub imul iadd ior'.split():
677    specialname = "__%s__" % (op, )
678    # fool the gateway logic by giving it a real unbound method
679    meth = new.instancemethod(
680        make_binary_returning_notimplemented_instance_method(specialname),
681        None,
682        W_InstanceObject)
683    rawdict[specialname] = interp2app(meth)
684
685for op in "or and xor lshift rshift add sub mul div mod divmod floordiv truediv".split():
686    specialname = "__%s__" % (op, )
687    rspecialname = "__r%s__" % (op, )
688    func, rfunc = make_binary_instance_method(op)
689    # fool the gateway logic by giving it a real unbound method
690    meth = new.instancemethod(func, None, W_InstanceObject)
691    rawdict[specialname] = interp2app(meth)
692    rmeth = new.instancemethod(rfunc, None, W_InstanceObject)
693    rawdict[rspecialname] = interp2app(rmeth)
694
695
696def descr_del_dict(space, w_inst):
697    # use setdict to raise the error
698    w_inst.setdict(space, space.w_None)
699
700dict_descr = GetSetProperty(descr_get_dict, descr_set_dict, descr_del_dict)
701dict_descr.name = '__dict__'
702
703W_InstanceObject.typedef = TypeDef("instance",
704    __new__ = interp2app(descr_instance_new),
705    __getattribute__ = interp2app(W_InstanceObject.descr_getattribute),
706    __setattr__ = interp2app(W_InstanceObject.descr_setattr),
707    __delattr__ = interp2app(W_InstanceObject.descr_delattr),
708    __repr__ = interp2app(W_InstanceObject.descr_repr),
709    __str__ = interp2app(W_InstanceObject.descr_str),
710    __unicode__ = interp2app(W_InstanceObject.descr_unicode),
711    __format__ = interp2app(W_InstanceObject.descr_format),
712    __len__ = interp2app(W_InstanceObject.descr_len),
713    __getitem__ = interp2app(W_InstanceObject.descr_getitem),
714    __setitem__ = interp2app(W_InstanceObject.descr_setitem),
715    __delitem__ = interp2app(W_InstanceObject.descr_delitem),
716    __iter__ = interp2app(W_InstanceObject.descr_iter),
717    __getslice__ = interp2app(W_InstanceObject.descr_getslice),
718    __setslice__ = interp2app(W_InstanceObject.descr_setslice),
719    __delslice__ = interp2app(W_InstanceObject.descr_delslice),
720    __call__ = interp2app(W_InstanceObject.descr_call),
721    __nonzero__ = interp2app(W_InstanceObject.descr_nonzero),
722    __cmp__ = interp2app(W_InstanceObject.descr_cmp),
723    __hash__ = interp2app(W_InstanceObject.descr_hash),
724    __int__ = interp2app(W_InstanceObject.descr_int),
725    __long__ = interp2app(W_InstanceObject.descr_long),
726    __index__ = interp2app(W_InstanceObject.descr_index),
727    __contains__ = interp2app(W_InstanceObject.descr_contains),
728    __pow__ = interp2app(W_InstanceObject.descr_pow),
729    __rpow__ = interp2app(W_InstanceObject.descr_rpow),
730    next = interp2app(W_InstanceObject.descr_next),
731    __exit__ = interp2app(W_InstanceObject.descr_exit),
732    __dict__ = dict_descr,
733    **rawdict
734)
735W_InstanceObject.typedef.acceptable_as_base_class = False