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

« back to all changes in this revision

Viewing changes to pypy/module/__builtin__/operation.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
"""
 
2
Interp-level implementation of the basic space operations.
 
3
"""
 
4
 
 
5
from pypy.interpreter import gateway
 
6
from pypy.interpreter.baseobjspace import ObjSpace
 
7
from pypy.interpreter.error import OperationError 
 
8
NoneNotWrapped = gateway.NoneNotWrapped
 
9
 
 
10
def abs(space, w_val):
 
11
    "abs(number) -> number\n\nReturn the absolute value of the argument."
 
12
    return space.abs(w_val)
 
13
 
 
14
def chr(space, w_ascii):
 
15
    "Return a string of one character with the given ascii code."
 
16
    w_character = space.newstring([w_ascii])
 
17
    return w_character
 
18
 
 
19
def unichr(space, w_code):
 
20
    "Return a Unicode string of one character with the given ordinal."
 
21
    return space.newunicode([space.int_w(w_code)])
 
22
 
 
23
def len(space, w_obj):
 
24
    "len(object) -> integer\n\nReturn the number of items of a sequence or mapping."
 
25
    return space.len(w_obj)
 
26
 
 
27
 
 
28
def checkattrname(space, w_name):
 
29
    # This is a check to ensure that getattr/setattr/delattr only pass a
 
30
    # string to the rest of the code.  XXX not entirely sure if these three
 
31
    # functions are the only way for non-string objects to reach
 
32
    # space.{get,set,del}attr()...
 
33
    # Note that if w_name is already a string (or a subclass of str),
 
34
    # it must be returned unmodified (and not e.g. unwrapped-rewrapped).
 
35
    if not space.is_true(space.isinstance(w_name, space.w_str)):
 
36
        name = space.str_w(w_name)    # typecheck
 
37
        w_name = space.wrap(name)     # rewrap as a real string
 
38
    return w_name
 
39
 
 
40
def delattr(space, w_object, w_name):
 
41
    """Delete a named attribute on an object.
 
42
delattr(x, 'y') is equivalent to ``del x.y''."""
 
43
    w_name = checkattrname(space, w_name)
 
44
    space.delattr(w_object, w_name)
 
45
    return space.w_None
 
46
 
 
47
def getattr(space, w_object, w_name, w_defvalue=NoneNotWrapped):
 
48
    """Get a named attribute from an object.
 
49
getattr(x, 'y') is equivalent to ``x.y''."""
 
50
    w_name = checkattrname(space, w_name)
 
51
    try:
 
52
        return space.getattr(w_object, w_name)
 
53
    except OperationError, e:
 
54
        if w_defvalue is not None:
 
55
            if e.match(space, space.w_AttributeError):
 
56
                return w_defvalue
 
57
        raise
 
58
 
 
59
def hasattr(space, w_object, w_name):
 
60
    """Return whether the object has an attribute with the given name.
 
61
    (This is done by calling getattr(object, name) and catching exceptions.)"""
 
62
    w_name = checkattrname(space, w_name)
 
63
    if space.findattr(w_object, w_name) is not None:
 
64
        return space.w_True
 
65
    else:
 
66
        return space.w_False
 
67
 
 
68
def hash(space, w_object):
 
69
    """Return a hash value for the object.  Two objects which compare as
 
70
equal have the same hash value.  It is possible, but unlikely, for
 
71
two un-equal objects to have the same hash value."""
 
72
    return space.hash(w_object)
 
73
 
 
74
def oct(space, w_val):
 
75
    """Return the octal representation of an integer."""
 
76
    # XXX does this need to be a space operation?
 
77
    return space.oct(w_val)
 
78
 
 
79
def hex(space, w_val):
 
80
    """Return the hexadecimal representation of an integer."""
 
81
    return space.hex(w_val)
 
82
 
 
83
def id(space, w_object):
 
84
    "Return the identity of an object: id(x) == id(y) if and only if x is y."
 
85
    return space.id(w_object)
 
86
 
 
87
def cmp(space, w_x, w_y):
 
88
    """return 0 when x == y, -1 when x < y and 1 when x > y """
 
89
    return space.cmp(w_x, w_y)
 
90
 
 
91
def coerce(space, w_x, w_y):
 
92
    """coerce(x, y) -> (x1, y1)
 
93
 
 
94
Return a tuple consisting of the two numeric arguments converted to
 
95
a common type, using the same rules as used by arithmetic operations.
 
96
If coercion is not possible, raise TypeError."""
 
97
    return space.coerce(w_x, w_y)
 
98
 
 
99
def divmod(space, w_x, w_y):
 
100
    """Return the tuple ((x-x%y)/y, x%y).  Invariant: div*y + mod == x."""
 
101
    return space.divmod(w_x, w_y)
 
102
 
 
103
# semi-private: works only for new-style classes.
 
104
def _issubtype(space, w_cls1, w_cls2):
 
105
    return space.issubtype(w_cls1, w_cls2)
 
106
 
 
107
# ____________________________________________________________
 
108
 
 
109
from math import floor as _floor
 
110
from math import ceil as _ceil
 
111
 
 
112
def round(space, number, ndigits=0):
 
113
    """round(number[, ndigits]) -> floating point number
 
114
 
 
115
Round a number to a given precision in decimal digits (default 0 digits).
 
116
This always returns a floating point number.  Precision may be negative."""
 
117
    # Algortithm copied directly from CPython
 
118
    f = 1.0
 
119
    if ndigits < 0:
 
120
        i = -ndigits
 
121
    else:
 
122
        i = ndigits
 
123
    while i > 0:
 
124
        f = f*10.0
 
125
        i -= 1
 
126
    if ndigits < 0:
 
127
        number /= f
 
128
    else:
 
129
        number *= f
 
130
    if number >= 0.0:
 
131
        number = _floor(number + 0.5)
 
132
    else:
 
133
        number = _ceil(number - 0.5)
 
134
    if ndigits < 0:
 
135
        number *= f
 
136
    else:
 
137
        number /= f
 
138
    return space.wrap(number)
 
139
#
 
140
round.unwrap_spec = [ObjSpace, float, int]
 
141
 
 
142
# ____________________________________________________________
 
143
 
 
144
iter_sentinel = gateway.applevel('''
 
145
    # NOT_RPYTHON  -- uses yield
 
146
    # App-level implementation of the iter(callable,sentinel) operation.
 
147
 
 
148
    def iter_generator(callable_, sentinel):
 
149
        while 1:
 
150
            result = callable_()
 
151
            if result == sentinel:
 
152
                return
 
153
            yield result
 
154
 
 
155
    def iter_sentinel(callable_, sentinel):
 
156
        if not callable(callable_):
 
157
            raise TypeError, 'iter(v, w): v must be callable'
 
158
        return iter_generator(callable_, sentinel)
 
159
 
 
160
''', filename=__file__).interphook("iter_sentinel")
 
161
 
 
162
def iter(space, w_collection_or_callable, w_sentinel=NoneNotWrapped):
 
163
    """iter(collection) -> iterator over the elements of the collection.
 
164
 
 
165
iter(callable, sentinel) -> iterator calling callable() until it returns
 
166
                            the sentinal.
 
167
"""
 
168
    if w_sentinel is None:
 
169
        return space.iter(w_collection_or_callable) 
 
170
        # XXX it seems that CPython checks the following 
 
171
        #     for newstyle but doesn't for oldstyle classes :-( 
 
172
        #w_res = space.iter(w_collection_or_callable)
 
173
        #w_typeres = space.type(w_res) 
 
174
        #try: 
 
175
        #    space.getattr(w_typeres, space.wrap('next'))
 
176
        #except OperationError, e: 
 
177
        #    if not e.match(space, space.w_AttributeError): 
 
178
        #        raise 
 
179
        #    raise OperationError(space.w_TypeError, 
 
180
        #        space.wrap("iter() returned non-iterator of type '%s'" % 
 
181
        #                   w_typeres.name))
 
182
        #else: 
 
183
        #    return w_res 
 
184
    else:
 
185
        return iter_sentinel(space, w_collection_or_callable, w_sentinel)
 
186
 
 
187
def _seqiter(space, w_obj):
 
188
    return space.newseqiter(w_obj)
 
189
 
 
190
def ord(space, w_val):
 
191
    """Return the integer ordinal of a character."""
 
192
    return space.ord(w_val)
 
193
 
 
194
def pow(space, w_base, w_exponent, w_modulus=None):
 
195
    """With two arguments, equivalent to ``base**exponent''.
 
196
With three arguments, equivalent to ``(base**exponent) % modulus'',
 
197
but much more efficient for large exponents."""
 
198
    return space.pow(w_base, w_exponent, w_modulus)
 
199
 
 
200
def repr(space, w_object):
 
201
    """Return a canonical string representation of the object.
 
202
For simple object types, eval(repr(object)) == object."""
 
203
    return space.repr(w_object)
 
204
 
 
205
def setattr(space, w_object, w_name, w_val):
 
206
    """Store a named attribute into an object.
 
207
setattr(x, 'y', z) is equivalent to ``x.y = z''."""
 
208
    w_name = checkattrname(space, w_name)
 
209
    space.setattr(w_object, w_name, w_val)
 
210
    return space.w_None
 
211
 
 
212
def intern(space, w_str):
 
213
    """``Intern'' the given string.  This enters the string in the (global)
 
214
table of interned strings whose purpose is to speed up dictionary lookups.
 
215
Return the string itself or the previously interned string object with the
 
216
same value."""
 
217
    if space.is_w(space.type(w_str), space.w_str):
 
218
        return space.new_interned_w_str(w_str)
 
219
    raise OperationError(space.w_TypeError, space.wrap("intern() argument must be string."))
 
220
 
 
221
def callable(space, w_object):
 
222
    """Check whether the object appears to be callable (i.e., some kind of
 
223
function).  Note that classes are callable."""
 
224
    return space.callable(w_object)
 
225
 
 
226
 
 
227
 
 
228
def _recursive_issubclass(space, w_cls, w_klass_or_tuple): # returns interp-level bool
 
229
    if space.is_w(w_cls, w_klass_or_tuple):
 
230
        return True
 
231
    try:
 
232
        w_bases = space.getattr(w_cls, space.wrap("__bases__"))
 
233
    except OperationError, e:
 
234
        if e.match(space, space.w_AttributeError):
 
235
            return False
 
236
        else:
 
237
            raise
 
238
    w_iterator = space.iter(w_bases)
 
239
    while True:
 
240
        try:
 
241
            w_base = space.next(w_iterator)
 
242
        except OperationError, e:
 
243
            if not e.match(space, space.w_StopIteration):
 
244
                raise
 
245
            break
 
246
        if _recursive_issubclass(space, w_base, w_klass_or_tuple):
 
247
            return True
 
248
    return False
 
249
 
 
250
def _issubclass(space, w_cls, w_klass_or_tuple, check_cls, depth): # returns interp-level bool
 
251
    if depth == 0:
 
252
        # XXX overzealous test compliance hack
 
253
        raise OperationError(space.w_RuntimeError, space.wrap("maximum recursion depth exceeded"))
 
254
    if space.is_true(space.issubtype(space.type(w_klass_or_tuple), space.w_tuple)):
 
255
        w_iter = space.iter(w_klass_or_tuple)
 
256
        while True:
 
257
            try:
 
258
                w_klass = space.next(w_iter)
 
259
            except OperationError, e:
 
260
                if not e.match(space, space.w_StopIteration):
 
261
                   raise
 
262
                break
 
263
            if _issubclass(space, w_cls, w_klass, True, depth - 1):
 
264
                return True
 
265
        return False
 
266
 
 
267
    try:
 
268
        return space.is_true(space.issubtype(w_cls, w_klass_or_tuple))
 
269
    except OperationError, e:
 
270
        if e.match(space, space.w_TypeError):
 
271
            w_bases = space.wrap('__bases__')
 
272
            if check_cls:
 
273
                try:
 
274
                    space.getattr(w_cls, w_bases)
 
275
                except OperationError, e:
 
276
                    if not e.match(space, space.w_AttributeError):
 
277
                        raise
 
278
                    raise OperationError(space.w_TypeError, space.wrap('arg 1 must be a class or type'))
 
279
            try:
 
280
                space.getattr(w_klass_or_tuple, w_bases)
 
281
            except OperationError, e:
 
282
                if not e.match(space, space.w_AttributeError):
 
283
                    raise
 
284
                raise OperationError(space.w_TypeError, space.wrap('arg 2 must be a class or type or a tuple thereof'))
 
285
            return _recursive_issubclass(space, w_cls, w_klass_or_tuple)
 
286
        else:
 
287
            raise
 
288
 
 
289
 
 
290
def issubclass(space, w_cls, w_klass_or_tuple):
 
291
    """Check whether a class 'cls' is a subclass (i.e., a derived class) of
 
292
another class.  When using a tuple as the second argument, check whether
 
293
'cls' is a subclass of any of the classes listed in the tuple."""
 
294
    return space.wrap(issubclass_w(space, w_cls, w_klass_or_tuple))
 
295
 
 
296
def issubclass_w(space, w_cls, w_klass_or_tuple):
 
297
    return _issubclass(space, w_cls, w_klass_or_tuple, True, space.sys.recursionlimit)
 
298
 
 
299
 
 
300
def isinstance(space, w_obj, w_klass_or_tuple):
 
301
    """Check whether an object is an instance of a class (or of a subclass
 
302
thereof).  When using a tuple as the second argument, check whether 'obj'
 
303
is an instance of any of the classes listed in the tuple."""
 
304
    w_objtype = space.type(w_obj)
 
305
    if issubclass_w(space, w_objtype, w_klass_or_tuple):
 
306
        return space.w_True
 
307
    try:
 
308
        w_objcls = space.getattr(w_obj, space.wrap("__class__"))
 
309
    except OperationError, e:
 
310
        if e.match(space, space.w_AttributeError):
 
311
            return space.w_False
 
312
        else:
 
313
            raise
 
314
    if space.is_w(w_objcls, w_objtype):
 
315
        return space.w_False
 
316
    else:
 
317
        return space.wrap(_issubclass(space, w_objcls, w_klass_or_tuple, False, space.sys.recursionlimit))