~ubuntu-branches/ubuntu/karmic/pypy/karmic

« back to all changes in this revision

Viewing changes to pypy/lib/_classobj.py

  • Committer: Bazaar Package Importer
  • Author(s): Alexandre Fayolle
  • Date: 2007-04-13 09:33:09 UTC
  • Revision ID: james.westby@ubuntu.com-20070413093309-yoojh4jcoocu2krz
Tags: upstream-1.0.0
ImportĀ upstreamĀ versionĀ 1.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
import sys, operator
 
2
 
 
3
# producing nicer code objects by exec
 
4
from pypy.tool.sourcetools import NiceCompile
 
5
_compile = NiceCompile(globals())
 
6
 
 
7
def _coerce(left, right):
 
8
    try:
 
9
        return coerce(left, right)
 
10
    except TypeError:
 
11
        return None
 
12
 
 
13
obj_setattr = object.__setattr__
 
14
obj_getattribute = object.__getattribute__
 
15
 
 
16
HMASK = long(sys.maxint)
 
17
 
 
18
def uid(o):
 
19
    v = id(o)
 
20
    if v < 0:
 
21
        v += HMASK
 
22
        v += HMASK
 
23
        v += 2
 
24
    return v
 
25
 
 
26
# we use slots that we remove from type __dict__ for special attributes
 
27
#
 
28
# for classobj they are __bases__ and __name__ (classobj_bases_slot, classobj_name_slot)
 
29
# for instance it's __class__ (instance_class_slot)
 
30
 
 
31
 
 
32
# ____________________________________________________________
 
33
# classobj def
 
34
 
 
35
def type_err(arg, expected, v):
 
36
   return TypeError("argument %s must be %s, not %s" % (arg, expected, type(v).__name__))
 
37
 
 
38
def set_name(cls, name):
 
39
    if not isinstance(name, str):
 
40
        raise TypeError, "__name__ must be a string object"
 
41
    classobj_name_slot.__set__(cls, name)
 
42
 
 
43
def set_bases(cls, bases):
 
44
    if not isinstance(bases, tuple):
 
45
        raise TypeError, "__bases__ must be a tuple object"
 
46
    for b in bases:
 
47
        if not isinstance(b, classobj):
 
48
            raise TypeError, "__bases__ items must be classes"
 
49
    classobj_bases_slot.__set__(cls, bases)
 
50
 
 
51
def set_dict(cls, dic):
 
52
    if not isinstance(dic, dict):
 
53
        raise TypeError, "__dict__ must be a dictionary object"
 
54
    obj_setattr(cls, '__dict__', dic)
 
55
 
 
56
def retrieve(obj, attr):
 
57
    dic = obj_getattribute(obj, '__dict__')
 
58
    try:
 
59
        return dic[attr]
 
60
    except KeyError:
 
61
        raise AttributeError, attr
 
62
 
 
63
def lookup(cls, attr):
 
64
    # returns (value, class it was found in)
 
65
    try:
 
66
        v = retrieve(cls, attr)
 
67
        return v, cls
 
68
    except AttributeError:
 
69
        for b in classobj_bases_slot.__get__(cls):
 
70
            v, found = lookup(b, attr)
 
71
            if found:
 
72
                return v, found
 
73
        return None, None
 
74
 
 
75
def get_class_module(cls):
 
76
    try:
 
77
        mod = retrieve(cls, "__module__")
 
78
    except AttributeError:
 
79
        mod = None
 
80
    if not isinstance(mod, str):
 
81
        return "?"
 
82
    return mod
 
83
 
 
84
def mro_lookup(v, name):
 
85
    try:
 
86
        mro = type(v).__mro__
 
87
    except AttributeError:
 
88
        return None
 
89
    for x in mro:
 
90
        if name in x.__dict__:
 
91
            return x.__dict__[name]
 
92
    return None
 
93
 
 
94
def _seqiter(obj):
 
95
    func = obj.__getitem__
 
96
    i = 0
 
97
    while 1:
 
98
        try:
 
99
            yield func(i)
 
100
        except IndexError:
 
101
            return
 
102
        i += 1
 
103
# let geninterplevel retrieve the PyPy builtin instead
 
104
_seqiter.geninterplevel_name = lambda gen: "space.builtin.get('_seqiter')"
 
105
 
 
106
OLD_STYLE_CLASSES_IMPL = object()
 
107
 
 
108
class classobj(object):
 
109
 
 
110
    __slots__ = ('_name', '_bases', '__dict__')
 
111
 
 
112
    def __new__(subtype, name, bases, dic):
 
113
        if not isinstance(name, str):
 
114
            raise type_err('name', 'string', name)
 
115
 
 
116
        if bases is None:
 
117
            bases = ()
 
118
 
 
119
        if not isinstance(bases, tuple):
 
120
            raise type_err('bases', 'tuple', bases)
 
121
        
 
122
        if not isinstance(dic, dict):
 
123
            raise type_err('dict', 'dict', dic)
 
124
 
 
125
        try:
 
126
            dic['__doc__']
 
127
        except KeyError:
 
128
            dic['__doc__'] = None
 
129
 
 
130
        try:
 
131
            dic['__module__']
 
132
        except KeyError:
 
133
            try:
 
134
                i = 0
 
135
                while 1:
 
136
                    g = sys._getframe(i).f_globals
 
137
                    if not g.get('OLD_STYLE_CLASSES_IMPL',None) is OLD_STYLE_CLASSES_IMPL:
 
138
                        break
 
139
                    i += 1
 
140
            except ValueError:
 
141
                pass
 
142
            else:
 
143
                modname = g.get('__name__', None)
 
144
                if modname is not None:
 
145
                    dic['__module__'] = modname
 
146
            
 
147
        for b in bases:
 
148
            if not isinstance(b, classobj):
 
149
                if callable(type(b)):
 
150
                    return type(b)(name, bases, dic)
 
151
                raise TypeError,"base must be class"
 
152
 
 
153
        
 
154
        new_class = object.__new__(classobj)
 
155
 
 
156
        obj_setattr(new_class, '__dict__', dic)
 
157
        classobj_name_slot.__set__(new_class, name)
 
158
        classobj_bases_slot.__set__(new_class, bases)
 
159
 
 
160
        return new_class
 
161
 
 
162
    def __setattr__(self, attr, value):
 
163
        if attr == '__name__':
 
164
            set_name(self, value)
 
165
        elif attr == '__bases__':
 
166
            set_bases(self, value)
 
167
        elif attr == '__dict__':
 
168
            set_dict(self, value)
 
169
        else:
 
170
            obj_setattr(self, attr, value)
 
171
    
 
172
    def __delattr__(self, attr):
 
173
        if attr in ('__name__', '__bases__', '__dict__'):
 
174
            classobj.__setattr__(self, attr, None)
 
175
        else:
 
176
            object.__delattr__(self, attr)
 
177
    
 
178
 
 
179
    def __getattribute__(self, attr):
 
180
        if attr == '__dict__':
 
181
            return obj_getattribute(self, '__dict__')
 
182
        if attr == '__name__':
 
183
            return classobj_name_slot.__get__(self)
 
184
        if attr == '__bases__':
 
185
            return classobj_bases_slot.__get__(self)
 
186
            
 
187
        v, found = lookup(self, attr)
 
188
        if not found:
 
189
            raise AttributeError, "class %s has no attribute %s" % (self.__name__, attr)
 
190
 
 
191
        descr_get = mro_lookup(v, '__get__')
 
192
        if descr_get is None:
 
193
            return v
 
194
        return descr_get(v, None, self)
 
195
        
 
196
    def __repr__(self):
 
197
        mod = get_class_module(self)
 
198
        return "<class %s.%s at 0x%x>" % (mod, self.__name__, uid(self))
 
199
 
 
200
    def __str__(self):
 
201
        mod = get_class_module(self)
 
202
        if mod == "?":
 
203
            return self.__name__
 
204
        else:
 
205
            return "%s.%s" % (mod, self.__name__)
 
206
 
 
207
    def __call__(self, *args, **kwds):
 
208
        inst = object.__new__(instance)
 
209
        dic = inst.__dict__
 
210
        instance_class_slot.__set__(inst, self)
 
211
        init = instance_getattr1(inst,'__init__', False)
 
212
        if init:
 
213
            ret = init(*args, **kwds)
 
214
            if ret is not None:
 
215
                raise TypeError("__init__() should return None")
 
216
        elif args or kwds:
 
217
            raise TypeError("this constructor takes no arguments")
 
218
        return inst
 
219
 
 
220
# capture _name, _bases slots for usage and then hide them!
 
221
 
 
222
classobj_name_slot  = classobj._name
 
223
classobj_bases_slot = classobj._bases
 
224
 
 
225
del classobj._name, classobj._bases
 
226
 
 
227
# ____________________________________________________________
 
228
# instance def
 
229
 
 
230
def instance_getattr1(inst, name, exc=True):
 
231
    if name == "__dict__":
 
232
        return obj_getattribute(inst, name)
 
233
    elif name == "__class__":
 
234
        return instance_class_slot.__get__(inst)
 
235
    try:
 
236
        return retrieve(inst, name)
 
237
    except AttributeError:
 
238
        cls = instance_class_slot.__get__(inst)
 
239
        v, found = lookup(cls, name)
 
240
        if not found:
 
241
            if exc:
 
242
                raise AttributeError, "%s instance has no attribute %s" % (cls.__name__, name)
 
243
            else:
 
244
                return None
 
245
        descr_get = mro_lookup(v, '__get__')
 
246
        if descr_get is None:
 
247
            return v
 
248
        return descr_get(v, inst, cls)
 
249
 
 
250
class instance(object):
 
251
 
 
252
    __slots__ = ('_class', '__dict__')
 
253
    
 
254
    def __getattribute__(self, name):
 
255
        try:
 
256
            return instance_getattr1(self, name)
 
257
        except AttributeError:
 
258
            getattr = instance_getattr1(self, '__getattr__', exc=False)
 
259
            if getattr is not None:
 
260
                return getattr(name)
 
261
            raise
 
262
            
 
263
    def __new__(typ, klass, dic=None):
 
264
        # typ is not used at all
 
265
        if not isinstance(klass,classobj):
 
266
            raise TypeError("instance() first arg must be class")
 
267
        if dic is None:
 
268
            dic = {}
 
269
        elif not isinstance(dic, dict):
 
270
            raise TypeError("instance() second arg must be dictionary or None")
 
271
        inst = object.__new__(instance)
 
272
        instance_class_slot.__set__(inst, klass)
 
273
        obj_setattr(inst, '__dict__', dic)
 
274
        return inst
 
275
 
 
276
    def __del__(self):
 
277
        func = instance_getattr1(self, '__del__', exc=False)
 
278
        if func is not None:
 
279
            func()
 
280
 
 
281
    def __setattr__(self, name, value):
 
282
        if name == '__dict__':
 
283
            if not isinstance(value, dict):
 
284
                raise TypeError("__dict__ must be set to a dictionary")
 
285
            obj_setattr(self, '__dict__', value)
 
286
        elif name == '__class__':
 
287
            if not isinstance(value, classobj):
 
288
                raise TypeError("__class__ must be set to a class")
 
289
            instance_class_slot.__set__(self, value)
 
290
        else:
 
291
            setattr = instance_getattr1(self, '__setattr__', exc=False)
 
292
            if setattr is not None:
 
293
                setattr(name, value)
 
294
            else:
 
295
                self.__dict__[name] = value
 
296
 
 
297
    def __delattr__(self, name):
 
298
        # abuse __setattr__ to get the complaints :-)
 
299
        # this is as funny as in CPython
 
300
        if name in ('__dict__', '__class__'):
 
301
            instance.__setattr__(self, name, None)
 
302
        else:
 
303
            delattr = instance_getattr1(self, '__delattr__', exc=False)
 
304
            if delattr is not None:
 
305
                delattr(name)
 
306
            else:
 
307
                try:
 
308
                    del self.__dict__[name]
 
309
                except KeyError, ex:
 
310
                    raise AttributeError("%s instance has no attribute '%s'" % (
 
311
                        self.__class__.__name__,name) )
 
312
 
 
313
    def __repr__(self):
 
314
        try:
 
315
            func = instance_getattr1(self, '__repr__')
 
316
        except AttributeError:
 
317
            klass = self.__class__
 
318
            mod = get_class_module(klass)
 
319
            return "<%s.%s instance at 0x%x>" % (mod, klass.__name__, uid(self))
 
320
        return func()
 
321
 
 
322
    def __str__(self):
 
323
        try:
 
324
            func = instance_getattr1(self, '__str__')
 
325
        except AttributeError:
 
326
            return instance.__repr__(self)
 
327
        return func()
 
328
 
 
329
    def __hash__(self):
 
330
        _eq = instance_getattr1(self, "__eq__", False)
 
331
        _cmp = instance_getattr1(self, "__cmp__", False)
 
332
        _hash = instance_getattr1(self, "__hash__", False)
 
333
        if (_eq or _cmp) and not _hash:
 
334
            raise TypeError("unhashable instance")
 
335
        if _hash:
 
336
            ret = _hash()
 
337
            if not isinstance(ret, int):
 
338
                raise TypeError("__hash__() should return an int")
 
339
            return ret
 
340
        else:
 
341
            return object.__hash__(self)
 
342
 
 
343
    def __len__(self):
 
344
        ret = instance_getattr1(self,'__len__')()
 
345
        if isinstance(ret, int):
 
346
            if ret < 0:
 
347
                raise ValueError("__len__() should return >= 0")
 
348
            return ret
 
349
        else:
 
350
            raise TypeError("__len__() should return an int")
 
351
 
 
352
    def __getitem__(self, key):
 
353
        return instance_getattr1(self, '__getitem__')(key)
 
354
 
 
355
    def __setitem__(self, key, value):
 
356
        instance_getattr1(self, '__setitem__')(key, value)
 
357
 
 
358
    def __delitem__(self, key):
 
359
        instance_getattr1(self, '__delitem__')(key)
 
360
 
 
361
    def __getslice__(self, i, j):
 
362
        func = instance_getattr1(self, '__getslice__', False)
 
363
        if func:
 
364
            return func(i, j)
 
365
        else:
 
366
            return self[i:j:]
 
367
 
 
368
    def __setslice__(self, i, j, sequence):
 
369
        func = instance_getattr1(self, '__setslice__', False)
 
370
        if func:
 
371
            func(i, j, sequence)
 
372
        else:
 
373
            self[i:j:] = sequence
 
374
 
 
375
    def __delslice__(self, i, j):
 
376
        func = instance_getattr1(self, '__delslice__', False)
 
377
        if func:
 
378
            func(i, j)
 
379
        else:
 
380
            del self[i:j:]
 
381
 
 
382
    def __contains__(self, obj):
 
383
        func = instance_getattr1(self, '__contains__', False)
 
384
        if func:
 
385
            return bool(func(obj))
 
386
        # now do it ourselves
 
387
        for x in self:
 
388
            if x == obj:
 
389
                return True
 
390
        return False
 
391
 
 
392
    # unary operators
 
393
    for op in "neg pos abs invert int long float oct hex".split():
 
394
        exec _compile("""
 
395
 
 
396
    def __%(op)s__(self):
 
397
        return instance_getattr1(self, '__%(op)s__')()
 
398
 
 
399
""", {"op": op})
 
400
    del op
 
401
 
 
402
    def __index__(self):
 
403
        func = instance_getattr1(self, '__index__', False)
 
404
        if func:
 
405
            return func()
 
406
        else:
 
407
            raise TypeError('object cannot be interpreted as an index')
 
408
 
 
409
 
 
410
    # coerce
 
411
    def __coerce__(self, other):
 
412
        func = instance_getattr1(self, '__coerce__', False)
 
413
        if func:
 
414
            return func(other)
 
415
        return NotImplemented
 
416
 
 
417
 
 
418
    # binary operators    
 
419
    for op in "or and xor lshift rshift add sub mul div mod divmod floordiv truediv".split():
 
420
        opref = op
 
421
        if op in ['and', 'or']:
 
422
            opref = op + '_'
 
423
        if op not in ['divmod']:
 
424
            opref = 'operator.' + opref
 
425
        exec _compile("""
 
426
 
 
427
    def __%(op)s__(self, other):
 
428
        coerced = _coerce(self, other)
 
429
        if coerced is None or coerced[0] is self:
 
430
            func = instance_getattr1(self, '__%(op)s__', False)
 
431
            if func:
 
432
                return func(other)
 
433
            return NotImplemented
 
434
        else:
 
435
            return %(opref)s(coerced[0], coerced[1])
 
436
 
 
437
    def __r%(op)s__(self, other):
 
438
        coerced = _coerce(self, other)
 
439
        if coerced is None or coerced[0] is self:
 
440
            func = instance_getattr1(self, '__r%(op)s__', False)
 
441
            if func:
 
442
                return func(other)
 
443
            return NotImplemented
 
444
        else:
 
445
            return %(opref)s(coerced[1], coerced[0])
 
446
 
 
447
""", {"op": op, "opref": opref})
 
448
    del op, opref
 
449
 
 
450
 
 
451
    # inplace operators    
 
452
    for op in 'mod and pow truediv lshift xor rshift floordiv div sub mul add or'.split():
 
453
        exec _compile("""
 
454
 
 
455
    def __i%(op)s__(self, other):
 
456
       func = instance_getattr1(self, '__i%(op)s__', False)
 
457
       if func:
 
458
           return func(other)
 
459
       return NotImplemented
 
460
 
 
461
""", {"op": op})
 
462
    del op
 
463
 
 
464
 
 
465
    def __pow__(self, other, modulo=None):
 
466
        if modulo is None:
 
467
            coerced = _coerce(self, other)
 
468
            if coerced is None or coerced[0] is self:
 
469
                func = instance_getattr1(self, '__pow__', False)
 
470
                if func:
 
471
                    return func(other)
 
472
                return NotImplemented
 
473
            else:
 
474
                return operator.pow(coerced[0], coerced[1], None)
 
475
        else:
 
476
            # CPython also doesn't try coercion in this case
 
477
            func = instance_getattr1(self, '__pow__', False)
 
478
            if func:
 
479
                return func(other, modulo)
 
480
            return NotImplemented
 
481
 
 
482
 
 
483
    def __rpow__(self, other, modulo=None):
 
484
        if modulo is None:
 
485
            coerced = _coerce(self, other)
 
486
            if coerced is None or coerced[0] is self:
 
487
                func = instance_getattr1(self, '__rpow__', False)
 
488
                if func:
 
489
                    return func(other)
 
490
                return NotImplemented
 
491
            else:
 
492
                return operator.pow(coerced[1], coerced[0], None)
 
493
        else:
 
494
            # CPython also doesn't try coercion in this case
 
495
            func = instance_getattr1(self, '__rpow__', False)
 
496
            if func:
 
497
                return func(other, modulo)
 
498
            return NotImplemented
 
499
 
 
500
 
 
501
    def __nonzero__(self):
 
502
        func = instance_getattr1(self, '__nonzero__', False)
 
503
        if not func:
 
504
            func = instance_getattr1(self, '__len__', False)
 
505
            if not func: # default to true
 
506
                return True
 
507
        ret = func()
 
508
        if isinstance(ret, int):
 
509
            if ret < 0:
 
510
                raise ValueError("__nonzero__() should return >= 0")
 
511
            return ret > 0
 
512
        else:
 
513
            raise TypeError("__nonzero__() should return an int")        
 
514
 
 
515
 
 
516
    def __call__(self, *args, **kwds):
 
517
        func = instance_getattr1(self, '__call__', False)
 
518
        if not func:
 
519
            raise AttributeError, "%s instance has no __call__ method" % (self.__class__.__name__)            
 
520
        return func(*args, **kwds)
 
521
 
 
522
    # rich comparison operations
 
523
    for op in 'eq ne gt lt ge le'.split():
 
524
        exec _compile("""
 
525
 
 
526
    def __%(op)s__(self, other):
 
527
        try:
 
528
            return instance_getattr1(self, '__%(op)s__')(other)
 
529
        except AttributeError:
 
530
            return NotImplemented
 
531
 
 
532
""", {"op": op})
 
533
    del op    
 
534
 
 
535
 
 
536
    def __iter__(self):
 
537
        func = instance_getattr1(self, '__iter__', False)
 
538
        if func:
 
539
            ret = func()
 
540
            if not mro_lookup(ret, 'next'):
 
541
                raise TypeError, ("__iter__ returned non-iterator of type %s"
 
542
                                  % type(ret).__name__)
 
543
            return ret
 
544
        func = instance_getattr1(self, '__getitem__', False)
 
545
        if not func:
 
546
            raise TypeError, "iteration over non-sequence"
 
547
        # moved sequiter away from here:
 
548
        # flow space cannot handle nested functions.
 
549
        return _seqiter(self)
 
550
 
 
551
    def next(self):
 
552
        func = instance_getattr1(self, 'next', False)
 
553
        if not func:
 
554
            raise TypeError, "instance has no next() method"
 
555
        return func()
 
556
 
 
557
    def __cmp__(self, other): # do all the work here like CPython
 
558
        coerced = _coerce(self, other)
 
559
        if coerced is None:
 
560
            v = self
 
561
            w = other
 
562
        else:
 
563
            v = coerced[0]
 
564
            w = coerced[1]
 
565
            if not isinstance(v, instance) and not isinstance(w, instance):
 
566
                return cmp(v,w)
 
567
        if isinstance(v, instance):
 
568
            func = instance_getattr1(v, '__cmp__', False)
 
569
            if func:
 
570
                res = func(w)
 
571
                if isinstance(res, int):
 
572
                    if res > 0:
 
573
                        return 1
 
574
                    if res < 0:
 
575
                        return -1
 
576
                    return 0
 
577
                raise TypeError,"__cmp__ must return int"
 
578
        if isinstance(w, instance):
 
579
            func = instance_getattr1(w, '__cmp__', False)
 
580
            if func:
 
581
                res = func(v)
 
582
                if isinstance(res, int):
 
583
                    if res > 0:
 
584
                        return 1
 
585
                    if res < 0:
 
586
                        return -1
 
587
                    return 0
 
588
                raise TypeError,"__cmp__ must return int"
 
589
        return NotImplemented
 
590
 
 
591
# capture _class slot for usage and then hide them!
 
592
instance_class_slot = instance._class
 
593
del instance._class
 
594
 
 
595
def purify(): # to use in geninterplevel case, because global side-effects are lost
 
596
    del classobj._name
 
597
    del classobj._bases
 
598
    del classobj.__slots__
 
599
    del instance._class
 
600
    del instance.__slots__
 
601
 
 
602
    
 
603
del _compile, NiceCompile