2
Interp-level implementation of the basic space operations.
5
from pypy.interpreter import gateway
6
from pypy.interpreter.baseobjspace import ObjSpace
7
from pypy.interpreter.error import OperationError
8
NoneNotWrapped = gateway.NoneNotWrapped
10
def abs(space, w_val):
11
"abs(number) -> number\n\nReturn the absolute value of the argument."
12
return space.abs(w_val)
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])
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)])
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)
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
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)
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)
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):
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:
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)
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)
79
def hex(space, w_val):
80
"""Return the hexadecimal representation of an integer."""
81
return space.hex(w_val)
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)
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)
91
def coerce(space, w_x, w_y):
92
"""coerce(x, y) -> (x1, y1)
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)
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)
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)
107
# ____________________________________________________________
109
from math import floor as _floor
110
from math import ceil as _ceil
112
def round(space, number, ndigits=0):
113
"""round(number[, ndigits]) -> floating point number
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
131
number = _floor(number + 0.5)
133
number = _ceil(number - 0.5)
138
return space.wrap(number)
140
round.unwrap_spec = [ObjSpace, float, int]
142
# ____________________________________________________________
144
iter_sentinel = gateway.applevel('''
145
# NOT_RPYTHON -- uses yield
146
# App-level implementation of the iter(callable,sentinel) operation.
148
def iter_generator(callable_, sentinel):
151
if result == sentinel:
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)
160
''', filename=__file__).interphook("iter_sentinel")
162
def iter(space, w_collection_or_callable, w_sentinel=NoneNotWrapped):
163
"""iter(collection) -> iterator over the elements of the collection.
165
iter(callable, sentinel) -> iterator calling callable() until it returns
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)
175
# space.getattr(w_typeres, space.wrap('next'))
176
#except OperationError, e:
177
# if not e.match(space, space.w_AttributeError):
179
# raise OperationError(space.w_TypeError,
180
# space.wrap("iter() returned non-iterator of type '%s'" %
185
return iter_sentinel(space, w_collection_or_callable, w_sentinel)
187
def _seqiter(space, w_obj):
188
return space.newseqiter(w_obj)
190
def ord(space, w_val):
191
"""Return the integer ordinal of a character."""
192
return space.ord(w_val)
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)
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)
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)
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
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."))
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)
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):
232
w_bases = space.getattr(w_cls, space.wrap("__bases__"))
233
except OperationError, e:
234
if e.match(space, space.w_AttributeError):
238
w_iterator = space.iter(w_bases)
241
w_base = space.next(w_iterator)
242
except OperationError, e:
243
if not e.match(space, space.w_StopIteration):
246
if _recursive_issubclass(space, w_base, w_klass_or_tuple):
250
def _issubclass(space, w_cls, w_klass_or_tuple, check_cls, depth): # returns interp-level bool
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)
258
w_klass = space.next(w_iter)
259
except OperationError, e:
260
if not e.match(space, space.w_StopIteration):
263
if _issubclass(space, w_cls, w_klass, True, depth - 1):
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__')
274
space.getattr(w_cls, w_bases)
275
except OperationError, e:
276
if not e.match(space, space.w_AttributeError):
278
raise OperationError(space.w_TypeError, space.wrap('arg 1 must be a class or type'))
280
space.getattr(w_klass_or_tuple, w_bases)
281
except OperationError, e:
282
if not e.match(space, space.w_AttributeError):
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)
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))
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)
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):
308
w_objcls = space.getattr(w_obj, space.wrap("__class__"))
309
except OperationError, e:
310
if e.match(space, space.w_AttributeError):
314
if space.is_w(w_objcls, w_objtype):
317
return space.wrap(_issubclass(space, w_objcls, w_klass_or_tuple, False, space.sys.recursionlimit))