[pypy-commit] pypy py3k: merge default
pjenvey
noreply at buildbot.pypy.org
Thu Oct 10 01:22:23 CEST 2013
Author: Philip Jenvey <pjenvey at underboss.org>
Branch: py3k
Changeset: r67271:8dbb46471ccd
Date: 2013-10-09 16:18 -0700
http://bitbucket.org/pypy/pypy/changeset/8dbb46471ccd/
Log: merge default
diff --git a/lib_pypy/numpypy/__init__.py b/lib_pypy/numpypy/__init__.py
--- a/lib_pypy/numpypy/__init__.py
+++ b/lib_pypy/numpypy/__init__.py
@@ -10,8 +10,35 @@
import os
def get_include():
- head, tail = os.path.split(os.path.dirname(os.path.abspath(__file__)))
- return os.path.join(head, '../include')
+ """
+ Return the directory that contains the NumPy \\*.h header files.
+
+ Extension modules that need to compile against NumPy should use this
+ function to locate the appropriate include directory.
+
+ Notes
+ -----
+ When using ``distutils``, for example in ``setup.py``.
+ ::
+
+ import numpy as np
+ ...
+ Extension('extension_name', ...
+ include_dirs=[np.get_include()])
+ ...
+
+ """
+ import numpy
+ if getattr(numpy, 'show_config', None) is None:
+ # running from numpy source directory
+ head, tail = os.path.split(os.path.dirname(os.path.abspath(__file__)))
+ return os.path.join(head, '../include')
+ else:
+ # using installed numpy core headers
+ import numpy.core as core
+ d = os.path.join(os.path.dirname(core.__file__), 'include')
+ return d
+
__all__ = ['__version__', 'get_include']
diff --git a/lib_pypy/numpypy/core/numerictypes.py b/lib_pypy/numpypy/core/numerictypes.py
--- a/lib_pypy/numpypy/core/numerictypes.py
+++ b/lib_pypy/numpypy/core/numerictypes.py
@@ -1,1 +1,75 @@
from _numpypy.numerictypes import *
+import numpypy
+
+def issubclass_(arg1, arg2):
+ """
+ Determine if a class is a subclass of a second class.
+
+ `issubclass_` is equivalent to the Python built-in ``issubclass``,
+ except that it returns False instead of raising a TypeError is one
+ of the arguments is not a class.
+
+ Parameters
+ ----------
+ arg1 : class
+ Input class. True is returned if `arg1` is a subclass of `arg2`.
+ arg2 : class or tuple of classes.
+ Input class. If a tuple of classes, True is returned if `arg1` is a
+ subclass of any of the tuple elements.
+
+ Returns
+ -------
+ out : bool
+ Whether `arg1` is a subclass of `arg2` or not.
+
+ See Also
+ --------
+ issubsctype, issubdtype, issctype
+
+ Examples
+ --------
+ >>> np.issubclass_(np.int32, np.int)
+ True
+ >>> np.issubclass_(np.int32, np.float)
+ False
+
+ """
+ try:
+ return issubclass(arg1, arg2)
+ except TypeError:
+ return False
+
+def issubdtype(arg1, arg2):
+ """
+ Returns True if first argument is a typecode lower/equal in type hierarchy.
+
+ Parameters
+ ----------
+ arg1, arg2 : dtype_like
+ dtype or string representing a typecode.
+
+ Returns
+ -------
+ out : bool
+
+ See Also
+ --------
+ issubsctype, issubclass_
+ numpy.core.numerictypes : Overview of numpy type hierarchy.
+
+ Examples
+ --------
+ >>> np.issubdtype('S1', str)
+ True
+ >>> np.issubdtype(np.float64, np.float32)
+ False
+
+ """
+ if issubclass_(arg2, generic):
+ return issubclass(numpypy.dtype(arg1).type, arg2)
+ mro = numpypy.dtype(arg2).type.mro()
+ if len(mro) > 1:
+ val = mro[1]
+ else:
+ val = mro[0]
+ return issubclass(numpypy.dtype(arg1).type, val)
diff --git a/pypy/module/_socket/test/test_sock_app.py b/pypy/module/_socket/test/test_sock_app.py
--- a/pypy/module/_socket/test/test_sock_app.py
+++ b/pypy/module/_socket/test/test_sock_app.py
@@ -395,6 +395,8 @@
def test_socket_connect_ex(self):
import _socket
s = _socket.socket(_socket.AF_INET, _socket.SOCK_STREAM, 0)
+ # The following might fail if the DNS redirects failed requests to a
+ # catch-all address (i.e. opendns).
# Make sure we get an app-level error, not an interp one.
raises(_socket.gaierror, s.connect_ex, ("wrong.invalid", 80))
s.close()
diff --git a/pypy/module/cpyext/pyerrors.py b/pypy/module/cpyext/pyerrors.py
--- a/pypy/module/cpyext/pyerrors.py
+++ b/pypy/module/cpyext/pyerrors.py
@@ -99,11 +99,13 @@
exc_p[0] = make_ref(space, operr.w_type)
val_p[0] = make_ref(space, operr.get_w_value(space))
- at cpython_api([], lltype.Void)
+ at cpython_api([], rffi.INT_real, error=0)
def PyErr_BadArgument(space):
"""This is a shorthand for PyErr_SetString(PyExc_TypeError, message), where
message indicates that a built-in operation was invoked with an illegal
- argument. It is mostly for internal use."""
+ argument. It is mostly for internal use. In CPython this function always
+ raises an exception and returns 0 in all cases, hence the (ab)use of the
+ error indicator."""
raise OperationError(space.w_TypeError,
space.wrap("bad argument type for built-in operation"))
diff --git a/pypy/module/cpyext/test/test_pyerrors.py b/pypy/module/cpyext/test/test_pyerrors.py
--- a/pypy/module/cpyext/test/test_pyerrors.py
+++ b/pypy/module/cpyext/test/test_pyerrors.py
@@ -61,9 +61,10 @@
api.PyErr_Clear()
def test_BadArgument(self, space, api):
- api.PyErr_BadArgument()
+ ret = api.PyErr_BadArgument()
state = space.fromcache(State)
assert space.eq_w(state.operror.w_type, space.w_TypeError)
+ assert ret == 0
api.PyErr_Clear()
def test_Warning(self, space, api, capfd):
diff --git a/pypy/module/cpyext/test/test_unicodeobject.py b/pypy/module/cpyext/test/test_unicodeobject.py
--- a/pypy/module/cpyext/test/test_unicodeobject.py
+++ b/pypy/module/cpyext/test/test_unicodeobject.py
@@ -435,6 +435,15 @@
rffi.free_charp(b_text)
rffi.free_charp(b_encoding)
+ def test_decode_null_encoding(self, space, api):
+ null_charp = lltype.nullptr(rffi.CCHARP.TO)
+ u_text = u'abcdefg'
+ s_text = space.str_w(api.PyUnicode_AsEncodedString(space.wrap(u_text), null_charp, null_charp))
+ b_text = rffi.str2charp(s_text)
+ assert space.unwrap(api.PyUnicode_Decode(b_text, len(s_text), null_charp, null_charp)) == u_text
+ self.raises(space, api, TypeError, api.PyUnicode_FromEncodedObject, space.wrap(u_text), null_charp, None)
+ rffi.free_charp(b_text)
+
def test_leak(self):
size = 50
raw_buf, gc_buf = rffi.alloc_buffer(size)
diff --git a/pypy/module/cpyext/unicodeobject.py b/pypy/module/cpyext/unicodeobject.py
--- a/pypy/module/cpyext/unicodeobject.py
+++ b/pypy/module/cpyext/unicodeobject.py
@@ -354,6 +354,9 @@
in the unicode() built-in function. The codec to be used is looked up
using the Python codec registry. Return NULL if an exception was raised by
the codec."""
+ if not encoding:
+ # This tracks CPython 2.7, in CPython 3.4 'utf-8' is hardcoded instead
+ encoding = PyUnicode_GetDefaultEncoding(space)
w_str = space.wrapbytes(rffi.charpsize2str(s, size))
w_encoding = space.wrap(rffi.charp2str(encoding))
if errors:
@@ -383,6 +386,9 @@
All other objects, including Unicode objects, cause a TypeError to be
set."""
+ if not encoding:
+ raise OperationError(space.w_TypeError,
+ space.wrap("decoding Unicode is not supported"))
w_encoding = space.wrap(rffi.charp2str(encoding))
if errors:
w_errors = space.wrap(rffi.charp2str(errors))
diff --git a/pypy/module/micronumpy/interp_ufuncs.py b/pypy/module/micronumpy/interp_ufuncs.py
--- a/pypy/module/micronumpy/interp_ufuncs.py
+++ b/pypy/module/micronumpy/interp_ufuncs.py
@@ -319,6 +319,15 @@
else:
self.done_func = None
+ def are_common_types(self, dtype1, dtype2):
+ if dtype1.is_complex_type() and dtype2.is_complex_type():
+ return True
+ elif not (dtype1.is_complex_type() or dtype2.is_complex_type()) and \
+ (dtype1.is_int_type() and dtype2.is_int_type() or dtype1.is_float_type() and dtype2.is_float_type()) and \
+ not (dtype1.is_bool_type() or dtype2.is_bool_type()):
+ return True
+ return False
+
@jit.unroll_safe
def call(self, space, args_w):
if len(args_w) > 2:
@@ -339,6 +348,12 @@
'unsupported operand dtypes %s and %s for "%s"' % \
(w_rdtype.get_name(), w_ldtype.get_name(),
self.name)))
+
+ if self.are_common_types(w_ldtype, w_rdtype):
+ if not w_lhs.is_scalar() and w_rhs.is_scalar():
+ w_rdtype = w_ldtype
+ elif w_lhs.is_scalar() and not w_rhs.is_scalar():
+ w_ldtype = w_rdtype
calc_dtype = find_binop_result_dtype(space,
w_ldtype, w_rdtype,
int_only=self.int_only,
diff --git a/pypy/module/micronumpy/test/test_numarray.py b/pypy/module/micronumpy/test/test_numarray.py
--- a/pypy/module/micronumpy/test/test_numarray.py
+++ b/pypy/module/micronumpy/test/test_numarray.py
@@ -2972,6 +2972,11 @@
dtype=[('bg', 'i8'), ('fg', 'i8'), ('char', 'S1')])
assert c[0][0]["char"] == 'a'
+ def test_scalar_coercion(self):
+ import numpypy as np
+ a = np.array([1,2,3], dtype=np.int16)
+ assert (a * 2).dtype == np.int16
+
class AppTestPyPy(BaseNumpyAppTest):
def setup_class(cls):
if option.runappdirect and '__pypy__' not in sys.builtin_module_names:
diff --git a/pypy/module/posix/__init__.py b/pypy/module/posix/__init__.py
--- a/pypy/module/posix/__init__.py
+++ b/pypy/module/posix/__init__.py
@@ -147,6 +147,8 @@
interpleveldefs['nice'] = 'interp_posix.nice'
if hasattr(os, 'getlogin'):
interpleveldefs['getlogin'] = 'interp_posix.getlogin'
+ if hasattr(os, 'ctermid'):
+ interpleveldefs['ctermid'] = 'interp_posix.ctermid'
for name in ['setsid', 'getuid', 'geteuid', 'getgid', 'getegid', 'setuid',
'seteuid', 'setgid', 'setegid', 'getgroups', 'getpgrp',
diff --git a/pypy/module/posix/interp_posix.py b/pypy/module/posix/interp_posix.py
--- a/pypy/module/posix/interp_posix.py
+++ b/pypy/module/posix/interp_posix.py
@@ -1221,6 +1221,13 @@
except OSError, e:
raise wrap_oserror(space, e)
+def ctermid(space):
+ """ctermid() -> string
+
+ Return the name of the controlling terminal for this process.
+ """
+ return space.wrap(os.ctermid())
+
@unwrap_spec(fd=int)
def device_encoding(space, fd):
"""device_encoding(fd) -> str
diff --git a/pypy/module/pypyjit/policy.py b/pypy/module/pypyjit/policy.py
--- a/pypy/module/pypyjit/policy.py
+++ b/pypy/module/pypyjit/policy.py
@@ -110,7 +110,7 @@
'__pypy__', 'cStringIO', '_collections', 'struct',
'mmap', 'marshal', '_codecs', 'rctime', 'cppyy',
'_cffi_backend', 'pyexpat', '_continuation', '_io',
- 'thread']:
+ 'thread', 'select']:
if modname == 'pypyjit' and 'interp_resop' in rest:
return False
return True
diff --git a/pypy/module/pypyjit/test/test_policy.py b/pypy/module/pypyjit/test/test_policy.py
--- a/pypy/module/pypyjit/test/test_policy.py
+++ b/pypy/module/pypyjit/test/test_policy.py
@@ -49,12 +49,15 @@
from pypy.module.thread.os_lock import Lock
assert pypypolicy.look_inside_function(Lock.descr_lock_acquire.im_func)
+def test_select():
+ from pypy.module.select.interp_select import poll
+ assert pypypolicy.look_inside_function(poll)
+
def test_pypy_module():
from pypy.module._collections.interp_deque import W_Deque
from pypy.module._random.interp_random import W_Random
assert not pypypolicy.look_inside_function(W_Random.random)
assert pypypolicy.look_inside_function(W_Deque.length)
- assert not pypypolicy.look_inside_pypy_module('select.interp_epoll')
assert pypypolicy.look_inside_pypy_module('__builtin__.operation')
assert pypypolicy.look_inside_pypy_module('__builtin__.abstractinst')
assert pypypolicy.look_inside_pypy_module('__builtin__.functional')
diff --git a/pypy/module/select/interp_kqueue.py b/pypy/module/select/interp_kqueue.py
--- a/pypy/module/select/interp_kqueue.py
+++ b/pypy/module/select/interp_kqueue.py
@@ -180,12 +180,12 @@
i = 0
for w_ev in space.listview(w_changelist):
ev = space.interp_w(W_Kevent, w_ev)
- changelist[i].c_ident = ev.event.c_ident
- changelist[i].c_filter = ev.event.c_filter
- changelist[i].c_flags = ev.event.c_flags
- changelist[i].c_fflags = ev.event.c_fflags
- changelist[i].c_data = ev.event.c_data
- changelist[i].c_udata = ev.event.c_udata
+ changelist[i].c_ident = ev.ident
+ changelist[i].c_filter = ev.filter
+ changelist[i].c_flags = ev.flags
+ changelist[i].c_fflags = ev.fflags
+ changelist[i].c_data = ev.data
+ changelist[i].c_udata = ev.udata
i += 1
pchangelist = changelist
else:
@@ -206,13 +206,12 @@
evt = eventlist[i]
w_event = W_Kevent(space)
- w_event.event = lltype.malloc(kevent, flavor="raw")
- w_event.event.c_ident = evt.c_ident
- w_event.event.c_filter = evt.c_filter
- w_event.event.c_flags = evt.c_flags
- w_event.event.c_fflags = evt.c_fflags
- w_event.event.c_data = evt.c_data
- w_event.event.c_udata = evt.c_udata
+ w_event.ident = evt.c_ident
+ w_event.filter = evt.c_filter
+ w_event.flags = evt.c_flags
+ w_event.fflags = evt.c_fflags
+ w_event.data = evt.c_data
+ w_event.udata = evt.c_udata
elist_w[i] = w_event
@@ -234,11 +233,12 @@
class W_Kevent(W_Root):
def __init__(self, space):
- self.event = lltype.nullptr(kevent)
-
- def __del__(self):
- if self.event:
- lltype.free(self.event, flavor="raw")
+ self.ident = rffi.cast(kevent.c_ident, 0)
+ self.filter = rffi.cast(kevent.c_filter, 0)
+ self.flags = rffi.cast(kevent.c_flags, 0)
+ self.fflags = rffi.cast(kevent.c_fflags, 0)
+ self.data = rffi.cast(kevent.c_data, 0)
+ self.udata = lltype.nullptr(rffi.VOIDP.TO)
@unwrap_spec(filter=int, flags='c_uint', fflags='c_uint', data=int, udata=r_uint)
def descr__init__(self, space, w_ident, filter=KQ_FILTER_READ, flags=KQ_EV_ADD, fflags=0, data=0, udata=r_uint(0)):
@@ -247,35 +247,34 @@
else:
ident = r_uint(space.c_filedescriptor_w(w_ident))
- self.event = lltype.malloc(kevent, flavor="raw")
- rffi.setintfield(self.event, "c_ident", ident)
- rffi.setintfield(self.event, "c_filter", filter)
- rffi.setintfield(self.event, "c_flags", flags)
- rffi.setintfield(self.event, "c_fflags", fflags)
- rffi.setintfield(self.event, "c_data", data)
- self.event.c_udata = rffi.cast(rffi.VOIDP, udata)
+ self.ident = rffi.cast(kevent.c_ident, ident)
+ self.filter = rffi.cast(kevent.c_filter, filter)
+ self.flags = rffi.cast(kevent.c_flags, flags)
+ self.fflags = rffi.cast(kevent.c_fflags, fflags)
+ self.data = rffi.cast(kevent.c_data, data)
+ self.udata = rffi.cast(rffi.VOIDP, udata)
def _compare_all_fields(self, other, op):
if IDENT_UINT:
- l_ident = rffi.cast(lltype.Unsigned, self.event.c_ident)
- r_ident = rffi.cast(lltype.Unsigned, other.event.c_ident)
+ l_ident = rffi.cast(lltype.Unsigned, self.ident)
+ r_ident = rffi.cast(lltype.Unsigned, other.ident)
else:
- l_ident = self.event.c_ident
- r_ident = other.event.c_ident
- l_filter = rffi.cast(lltype.Signed, self.event.c_filter)
- r_filter = rffi.cast(lltype.Signed, other.event.c_filter)
- l_flags = rffi.cast(lltype.Unsigned, self.event.c_flags)
- r_flags = rffi.cast(lltype.Unsigned, other.event.c_flags)
- l_fflags = rffi.cast(lltype.Unsigned, self.event.c_fflags)
- r_fflags = rffi.cast(lltype.Unsigned, other.event.c_fflags)
+ l_ident = self.ident
+ r_ident = other.ident
+ l_filter = rffi.cast(lltype.Signed, self.filter)
+ r_filter = rffi.cast(lltype.Signed, other.filter)
+ l_flags = rffi.cast(lltype.Unsigned, self.flags)
+ r_flags = rffi.cast(lltype.Unsigned, other.flags)
+ l_fflags = rffi.cast(lltype.Unsigned, self.fflags)
+ r_fflags = rffi.cast(lltype.Unsigned, other.fflags)
if IDENT_UINT:
- l_data = rffi.cast(lltype.Signed, self.event.c_data)
- r_data = rffi.cast(lltype.Signed, other.event.c_data)
+ l_data = rffi.cast(lltype.Signed, self.data)
+ r_data = rffi.cast(lltype.Signed, other.data)
else:
- l_data = self.event.c_data
- r_data = other.event.c_data
- l_udata = rffi.cast(lltype.Unsigned, self.event.c_udata)
- r_udata = rffi.cast(lltype.Unsigned, other.event.c_udata)
+ l_data = self.data
+ r_data = other.data
+ l_udata = rffi.cast(lltype.Unsigned, self.udata)
+ r_udata = rffi.cast(lltype.Unsigned, other.udata)
if op == "eq":
return l_ident == r_ident and \
@@ -330,22 +329,22 @@
return space.wrap(self.compare_all_fields(space, w_other, "gt"))
def descr_get_ident(self, space):
- return space.wrap(self.event.c_ident)
+ return space.wrap(self.ident)
def descr_get_filter(self, space):
- return space.wrap(self.event.c_filter)
+ return space.wrap(self.filter)
def descr_get_flags(self, space):
- return space.wrap(self.event.c_flags)
+ return space.wrap(self.flags)
def descr_get_fflags(self, space):
- return space.wrap(self.event.c_fflags)
+ return space.wrap(self.fflags)
def descr_get_data(self, space):
- return space.wrap(self.event.c_data)
+ return space.wrap(self.data)
def descr_get_udata(self, space):
- return space.wrap(rffi.cast(rffi.UINTPTR_T, self.event.c_udata))
+ return space.wrap(rffi.cast(rffi.UINTPTR_T, self.udata))
W_Kevent.typedef = TypeDef("select.kevent",
diff --git a/pypy/objspace/std/floatobject.py b/pypy/objspace/std/floatobject.py
--- a/pypy/objspace/std/floatobject.py
+++ b/pypy/objspace/std/floatobject.py
@@ -1,5 +1,5 @@
import operator
-from pypy.interpreter.error import OperationError
+from pypy.interpreter.error import OperationError, operationerrfmt
from pypy.objspace.std import model, newformat
from pypy.objspace.std.floattype import float_typedef, W_AbstractFloatObject
from pypy.objspace.std.multimethod import FailedToImplementArgs
@@ -398,9 +398,18 @@
x = w_float1.floatval
y = w_float2.floatval
- return W_FloatObject(_pow(space, x, y, thirdArg))
+ try:
+ result = _pow(space, x, y)
+ except PowDomainError:
+ raise operationerrfmt(space.w_ValueError,
+ "negative number cannot be raised to a "
+ "fractional power")
+ return W_FloatObject(result)
-def _pow(space, x, y, thirdArg):
+class PowDomainError(ValueError):
+ """Signals a negative number raised to a fractional power"""
+
+def _pow(space, x, y):
# Sort out special cases here instead of relying on pow()
if y == 2.0: # special case for performance:
return x * x # x * x is always correct
@@ -452,18 +461,14 @@
"a negative power"))
negate_result = False
- # special case: "(-1.0) ** bignum" should not raise ValueError,
+ # special case: "(-1.0) ** bignum" should not raise PowDomainError,
# unlike "math.pow(-1.0, bignum)". See http://mail.python.org/
# - pipermail/python-bugs-list/2003-March/016795.html
if x < 0.0:
if isnan(y):
return NAN
if math.floor(y) != y:
- # Negative numbers raised to fractional powers become
- # complex
- return space.pow(space.newcomplex(x, 0.0),
- space.newcomplex(y, 0.0),
- thirdArg)
+ raise PowDomainError
# y is an exact integer, albeit perhaps a very large one.
# Replace x by its absolute value and remember to negate the
# pow result if y is odd.
diff --git a/pypy/objspace/std/listobject.py b/pypy/objspace/std/listobject.py
--- a/pypy/objspace/std/listobject.py
+++ b/pypy/objspace/std/listobject.py
@@ -30,7 +30,7 @@
from rpython.rlib import debug, jit, rerased
from rpython.rlib.listsort import make_timsort_class
from rpython.rlib.objectmodel import (
- instantiate, newlist_hint, resizelist_hint, specialize)
+ instantiate, newlist_hint, resizelist_hint, specialize, import_from_mixin)
from rpython.tool.sourcetools import func_with_new_name
__all__ = ['W_ListObject', 'make_range_list', 'make_empty_list_with_size']
@@ -1149,7 +1149,6 @@
class AbstractUnwrappedStrategy(object):
- _mixin_ = True
def wrap(self, unwrapped):
raise NotImplementedError
@@ -1308,7 +1307,6 @@
def setslice(self, w_list, start, step, slicelength, w_other):
assert slicelength >= 0
- items = self.unerase(w_list.lstorage)
if self is self.space.fromcache(ObjectListStrategy):
w_other = w_other._temporarily_as_objects()
@@ -1320,6 +1318,7 @@
w_list.setslice(start, step, slicelength, w_other_as_object)
return
+ items = self.unerase(w_list.lstorage)
oldsize = len(items)
len2 = w_other.length()
if step == 1: # Support list resizing for non-extended slices
@@ -1435,7 +1434,9 @@
self.unerase(w_list.lstorage).reverse()
-class ObjectListStrategy(AbstractUnwrappedStrategy, ListStrategy):
+class ObjectListStrategy(ListStrategy):
+ import_from_mixin(AbstractUnwrappedStrategy)
+
_none_value = None
_applevel_repr = "object"
@@ -1468,7 +1469,9 @@
return self.unerase(w_list.lstorage)
-class IntegerListStrategy(AbstractUnwrappedStrategy, ListStrategy):
+class IntegerListStrategy(ListStrategy):
+ import_from_mixin(AbstractUnwrappedStrategy)
+
_none_value = 0
_applevel_repr = "int"
@@ -1499,7 +1502,30 @@
return self.unerase(w_list.lstorage)
-class FloatListStrategy(AbstractUnwrappedStrategy, ListStrategy):
+ _base_extend_from_list = _extend_from_list
+
+ def _extend_from_list(self, w_list, w_other):
+ if w_other.strategy is self.space.fromcache(RangeListStrategy):
+ l = self.unerase(w_list.lstorage)
+ other = w_other.getitems_int()
+ assert other is not None
+ l += other
+ return
+ return self._base_extend_from_list(w_list, w_other)
+
+
+ _base_setslice = setslice
+
+ def setslice(self, w_list, start, step, slicelength, w_other):
+ if w_other.strategy is self.space.fromcache(RangeListStrategy):
+ storage = self.erase(w_other.getitems_int())
+ w_other = W_ListObject.from_storage_and_strategy(
+ self.space, storage, self)
+ return self._base_setslice(w_list, start, step, slicelength, w_other)
+
+class FloatListStrategy(ListStrategy):
+ import_from_mixin(AbstractUnwrappedStrategy)
+
_none_value = 0.0
_applevel_repr = "float"
@@ -1527,7 +1553,9 @@
l.reverse()
-class StringListStrategy(AbstractUnwrappedStrategy, ListStrategy):
+class StringListStrategy(ListStrategy):
+ import_from_mixin(AbstractUnwrappedStrategy)
+
_none_value = None
_applevel_repr = "str"
@@ -1558,7 +1586,9 @@
return self.unerase(w_list.lstorage)
-class UnicodeListStrategy(AbstractUnwrappedStrategy, ListStrategy):
+class UnicodeListStrategy(ListStrategy):
+ import_from_mixin(AbstractUnwrappedStrategy)
+
_none_value = None
_applevel_repr = "unicode"
diff --git a/pypy/objspace/std/test/test_liststrategies.py b/pypy/objspace/std/test/test_liststrategies.py
--- a/pypy/objspace/std/test/test_liststrategies.py
+++ b/pypy/objspace/std/test/test_liststrategies.py
@@ -227,6 +227,15 @@
l.setslice(0, 1, 2, W_ListObject(space, [w('a'), w(2), w(3)]))
assert isinstance(l.strategy, ObjectListStrategy)
+ def test_setslice_int_range(self):
+ space = self.space
+ w = space.wrap
+ l = W_ListObject(space, [w(1), w(2), w(3)])
+ assert isinstance(l.strategy, IntegerListStrategy)
+ l.setslice(0, 1, 2, make_range_list(space, 5, 1, 4))
+ assert isinstance(l.strategy, IntegerListStrategy)
+
+
def test_setslice_List(self):
space = self.space
@@ -471,6 +480,12 @@
l4 = W_ListObject(self.space, [self.space.wrap(1), self.space.wrap(2), self.space.wrap(3), self.space.wrap(1), self.space.wrap(2), self.space.wrap(3)])
assert self.space.eq_w(l3, l4)
+ def test_add_of_range_and_int(self):
+ l1 = make_range_list(self.space, 0, 1, 100)
+ l2 = W_ListObject(self.space, [self.space.wrap(1), self.space.wrap(2), self.space.wrap(3)])
+ l3 = self.space.add(l2, l1)
+ assert l3.strategy is l2.strategy
+
def test_mul(self):
l1 = W_ListObject(self.space, [self.space.wrap(1), self.space.wrap(2), self.space.wrap(3)])
l2 = l1.mul(2)
diff --git a/rpython/annotator/test/test_annrpython.py b/rpython/annotator/test/test_annrpython.py
--- a/rpython/annotator/test/test_annrpython.py
+++ b/rpython/annotator/test/test_annrpython.py
@@ -3442,6 +3442,29 @@
a.build_types(f, [str])
+ def test_negative_number_find(self):
+ def f(s, e):
+ return "xyz".find("x", s, e)
+
+ a = self.RPythonAnnotator()
+ py.test.raises(annmodel.AnnotatorError, "a.build_types(f, [int, int])")
+ a.build_types(f, [annmodel.SomeInteger(nonneg=True),
+ annmodel.SomeInteger(nonneg=True)])
+ def f(s, e):
+ return "xyz".rfind("x", s, e)
+
+ py.test.raises(annmodel.AnnotatorError, "a.build_types(f, [int, int])")
+ a.build_types(f, [annmodel.SomeInteger(nonneg=True),
+ annmodel.SomeInteger(nonneg=True)])
+
+ def f(s, e):
+ return "xyz".count("x", s, e)
+
+ py.test.raises(annmodel.AnnotatorError, "a.build_types(f, [int, int])")
+ a.build_types(f, [annmodel.SomeInteger(nonneg=True),
+ annmodel.SomeInteger(nonneg=True)])
+
+
def test_setslice(self):
def f():
lst = [2, 5, 7]
@@ -4080,7 +4103,7 @@
with py.test.raises(annmodel.UnionError) as exc:
a.build_types(f, [int])
- assert ("RPython cannot unify instances with no common base class"
+ assert ("RPython cannot unify instances with no common base class"
in exc.value.msg)
def test_unionerror_iters(self):
@@ -4096,7 +4119,7 @@
with py.test.raises(annmodel.UnionError) as exc:
a.build_types(f, [int])
- assert ("RPython cannot unify incompatible iterator variants" in
+ assert ("RPython cannot unify incompatible iterator variants" in
exc.value.msg)
def test_variable_getattr(self):
diff --git a/rpython/annotator/unaryop.py b/rpython/annotator/unaryop.py
--- a/rpython/annotator/unaryop.py
+++ b/rpython/annotator/unaryop.py
@@ -10,7 +10,7 @@
SomeUnicodeCodePoint, SomeInstance, SomeBuiltin, SomeFloat, SomeIterator,
SomePBC, SomeTypedAddressAccess, SomeAddress, SomeType, s_ImpossibleValue,
s_Bool, s_None, unionof, missing_operation, add_knowntypedata,
- HarmlesslyBlocked, SomeWeakRef, SomeUnicodeString)
+ HarmlesslyBlocked, SomeWeakRef, SomeUnicodeString, SomeByteArray)
from rpython.annotator.bookkeeper import getbookkeeper
from rpython.annotator import builtin
from rpython.annotator.binaryop import _clone ## XXX where to put this?
@@ -333,12 +333,13 @@
check_negative_slice(s_start, s_stop)
lst.listdef.resize()
-def check_negative_slice(s_start, s_stop):
+def check_negative_slice(s_start, s_stop, error="slicing"):
if isinstance(s_start, SomeInteger) and not s_start.nonneg:
- raise AnnotatorError("slicing: not proven to have non-negative start")
+ raise AnnotatorError("%s: not proven to have non-negative start" %
+ error)
if isinstance(s_stop, SomeInteger) and not s_stop.nonneg and \
getattr(s_stop, 'const', 0) != -1:
- raise AnnotatorError("slicing: not proven to have non-negative stop")
+ raise AnnotatorError("%s: not proven to have non-negative stop" % error)
class __extend__(SomeDict):
@@ -448,12 +449,15 @@
return s_Bool
def method_find(str, frag, start=None, end=None):
+ check_negative_slice(start, end, "find")
return SomeInteger()
def method_rfind(str, frag, start=None, end=None):
+ check_negative_slice(start, end, "rfind")
return SomeInteger()
def method_count(str, frag, start=None, end=None):
+ check_negative_slice(start, end, "count")
return SomeInteger(nonneg=True)
def method_strip(str, chr):
@@ -520,6 +524,11 @@
op_contains.can_only_throw = []
+class __extend__(SomeByteArray):
+ def getslice(ba, s_start, s_stop):
+ check_negative_slice(s_start, s_stop)
+ return SomeByteArray()
+
class __extend__(SomeUnicodeString):
def method_encode(uni, s_enc):
if not s_enc.is_constant():
diff --git a/rpython/flowspace/model.py b/rpython/flowspace/model.py
--- a/rpython/flowspace/model.py
+++ b/rpython/flowspace/model.py
@@ -252,6 +252,23 @@
from rpython.translator.tool.graphpage import try_show
try_show(self)
+ def get_graph(self):
+ import gc
+ pending = [self] # pending blocks
+ seen = {self: True, None: True}
+ for x in pending:
+ for y in gc.get_referrers(x):
+ if isinstance(y, FunctionGraph):
+ return y
+ elif isinstance(y, Link):
+ block = y.prevblock
+ if block not in seen:
+ pending.append(block)
+ seen[block] = True
+ elif isinstance(y, dict):
+ pending.append(y) # go back from the dict to the real obj
+ return pending
+
view = show
diff --git a/rpython/flowspace/specialcase.py b/rpython/flowspace/specialcase.py
--- a/rpython/flowspace/specialcase.py
+++ b/rpython/flowspace/specialcase.py
@@ -1,3 +1,4 @@
+import os
from rpython.flowspace.model import Constant, const
SPECIAL_CASES = {}
@@ -37,6 +38,18 @@
return space.frame.do_operation('simple_call', const(isinstance),
w_instance, w_type)
+ at register_flow_sc(open)
+def sc_open(space, *args_w):
+ from rpython.rlib.rfile import create_file
+
+ return space.frame.do_operation("simple_call", const(create_file), *args_w)
+
+ at register_flow_sc(os.tmpfile)
+def sc_os_tmpfile(space):
+ from rpython.rlib.rfile import create_temp_rfile
+
+ return space.frame.do_operation("simple_call", const(create_temp_rfile))
+
# _________________________________________________________________________
# a simplified version of the basic printing routines, for RPython programs
class StdOutBuffer:
diff --git a/rpython/memory/gc/minimark.py b/rpython/memory/gc/minimark.py
--- a/rpython/memory/gc/minimark.py
+++ b/rpython/memory/gc/minimark.py
@@ -1201,6 +1201,7 @@
# ^^^ a fast path of write-barrier
#
if source_hdr.tid & GCFLAG_HAS_CARDS != 0:
+ assert self.card_page_indices > 0
#
if source_hdr.tid & GCFLAG_TRACK_YOUNG_PTRS == 0:
# The source object may have random young pointers.
diff --git a/rpython/rlib/rfile.py b/rpython/rlib/rfile.py
--- a/rpython/rlib/rfile.py
+++ b/rpython/rlib/rfile.py
@@ -1,55 +1,241 @@
-""" This file makes open() and friends RPython
+""" This file makes open() and friends RPython. Note that RFile should not
+be used directly and instead it's magically appearing each time you call
+python builtin open()
"""
import os
-from rpython.annotator.model import SomeObject, SomeString, SomeInteger
-from rpython.rtyper.extregistry import ExtRegistryEntry
-from rpython.rtyper.extfunc import register_external
+from rpython.rtyper.lltypesystem import rffi, lltype
+from rpython.rtyper.tool import rffi_platform as platform
+from rpython.translator.tool.cbuild import ExternalCompilationInfo
+from rpython.rlib.rarithmetic import r_uint, intmask
+from rpython.rlib import rposix
+from rpython.rlib.rstring import StringBuilder
-class SomeFile(SomeObject):
- def method_write(self, s_arg):
- assert isinstance(s_arg, SomeString)
+eci = ExternalCompilationInfo(includes=['stdio.h', 'unistd.h', 'sys/types.h'])
- def method_read(self, s_arg=None):
- if s_arg is not None:
- assert isinstance(s_arg, SomeInteger)
- return SomeString(can_be_None=False)
+def llexternal(*args):
+ return rffi.llexternal(*args, compilation_info=eci)
- def method_close(self):
- pass
+FILE = lltype.Struct('FILE') # opaque type maybe
- def method_seek(self, s_arg, s_whence=None):
- assert isinstance(s_arg, SomeInteger)
- if s_whence is not None:
- assert isinstance(s_whence, SomeInteger)
+class CConfig(object):
+ _compilation_info_ = eci
- def rtyper_makekey(self):
- return self.__class__,
+ off_t = platform.SimpleType('off_t')
- def rtyper_makerepr(self, rtyper):
- from rpython.rtyper.lltypesystem.rfile import FileRepr
+CC = platform.configure(CConfig)
+OFF_T = CC['off_t']
- return FileRepr(rtyper)
+c_open = llexternal('fopen', [rffi.CCHARP, rffi.CCHARP], lltype.Ptr(FILE))
+c_close = llexternal('fclose', [lltype.Ptr(FILE)], rffi.INT)
+c_write = llexternal('fwrite', [rffi.CCHARP, rffi.SIZE_T, rffi.SIZE_T,
+ lltype.Ptr(FILE)], rffi.SIZE_T)
+c_read = llexternal('fread', [rffi.CCHARP, rffi.SIZE_T, rffi.SIZE_T,
+ lltype.Ptr(FILE)], rffi.SIZE_T)
+c_feof = llexternal('feof', [lltype.Ptr(FILE)], rffi.INT)
+c_ferror = llexternal('ferror', [lltype.Ptr(FILE)], rffi.INT)
+c_clearerror = llexternal('clearerr', [lltype.Ptr(FILE)], lltype.Void)
+c_fseek = llexternal('fseek', [lltype.Ptr(FILE), rffi.LONG, rffi.INT],
+ rffi.INT)
+c_tmpfile = llexternal('tmpfile', [], lltype.Ptr(FILE))
+c_fileno = llexternal('fileno', [lltype.Ptr(FILE)], rffi.INT)
+c_ftell = llexternal('ftell', [lltype.Ptr(FILE)], lltype.Signed)
+c_fflush = llexternal('fflush', [lltype.Ptr(FILE)], rffi.INT)
+c_ftruncate = llexternal('ftruncate', [rffi.INT, OFF_T], rffi.INT)
+c_fgets = llexternal('fgets', [rffi.CCHARP, rffi.INT, lltype.Ptr(FILE)],
+ rffi.CCHARP)
-class FileEntry(ExtRegistryEntry):
- _about_ = open
+BASE_BUF_SIZE = 4096
+BASE_LINE_SIZE = 100
- def compute_result_annotation(self, s_name, s_mode=None):
- assert isinstance(s_name, SomeString)
- if s_mode is not None:
- assert isinstance(s_mode, SomeString)
- return SomeFile()
+def create_file(filename, mode="r", buffering=-1):
+ assert buffering == -1
+ assert filename is not None
+ assert mode is not None
+ ll_name = rffi.str2charp(filename)
+ try:
+ ll_mode = rffi.str2charp(mode)
+ try:
+ ll_f = c_open(ll_name, ll_mode)
+ if not ll_f:
+ errno = rposix.get_errno()
+ raise OSError(errno, os.strerror(errno))
+ finally:
+ lltype.free(ll_mode, flavor='raw')
+ finally:
+ lltype.free(ll_name, flavor='raw')
+ return RFile(ll_f)
- def specialize_call(self, hop):
- return hop.r_result.rtype_constructor(hop)
+def create_temp_rfile():
+ res = c_tmpfile()
+ if not res:
+ errno = rposix.get_errno()
+ raise OSError(errno, os.strerror(errno))
+ return RFile(res)
-class OSTempfileEntry(ExtRegistryEntry):
- _about_ = os.tmpfile
+class RFile(object):
+ def __init__(self, ll_file):
+ self.ll_file = ll_file
- def compute_result_annotation(self):
- return SomeFile()
+ def write(self, value):
+ assert value is not None
+ ll_file = self.ll_file
+ if not ll_file:
+ raise ValueError("I/O operation on closed file")
+ assert value is not None
+ ll_value = rffi.get_nonmovingbuffer(value)
+ try:
+ # note that since we got a nonmoving buffer, it is either raw
+ # or already cannot move, so the arithmetics below are fine
+ total_bytes = 0
+ ll_current = ll_value
+ while total_bytes < len(value):
+ bytes = c_write(ll_current, 1, len(value) - r_uint(total_bytes),
+ ll_file)
+ if bytes == 0:
+ errno = rposix.get_errno()
+ raise OSError(errno, os.strerror(errno))
+ total_bytes += bytes
+ ll_current = rffi.cast(rffi.CCHARP,
+ rffi.cast(lltype.Unsigned, ll_value) +
+ total_bytes)
+ finally:
+ rffi.free_nonmovingbuffer(value, ll_value)
- def specialize_call(self, hop):
- return hop.r_result.rtype_tempfile(hop)
+ def close(self):
+ if self.ll_file:
+ # double close is allowed
+ res = c_close(self.ll_file)
+ self.ll_file = lltype.nullptr(FILE)
+ if res == -1:
+ errno = rposix.get_errno()
+ raise OSError(errno, os.strerror(errno))
+ def read(self, size=-1):
+ # XXX CPython uses a more delicate logic here
+ ll_file = self.ll_file
+ if not ll_file:
+ raise ValueError("I/O operation on closed file")
+ if size < 0:
+ # read the entire contents
+ buf = lltype.malloc(rffi.CCHARP.TO, BASE_BUF_SIZE, flavor='raw')
+ try:
+ s = StringBuilder()
+ while True:
+ returned_size = c_read(buf, 1, BASE_BUF_SIZE, ll_file)
+ if returned_size == 0:
+ if c_feof(ll_file):
+ # ok, finished
+ return s.build()
+ errno = c_ferror(ll_file)
+ c_clearerror(ll_file)
+ raise OSError(errno, os.strerror(errno))
+ s.append_charpsize(buf, returned_size)
+ finally:
+ lltype.free(buf, flavor='raw')
+ else:
+ raw_buf, gc_buf = rffi.alloc_buffer(size)
+ try:
+ returned_size = c_read(raw_buf, 1, size, ll_file)
+ if returned_size == 0:
+ if not c_feof(ll_file):
+ errno = c_ferror(ll_file)
+ raise OSError(errno, os.strerror(errno))
+ s = rffi.str_from_buffer(raw_buf, gc_buf, size,
+ rffi.cast(lltype.Signed, returned_size))
+ finally:
+ rffi.keep_buffer_alive_until_here(raw_buf, gc_buf)
+ return s
+
+ def seek(self, pos, whence=0):
+ ll_file = self.ll_file
+ if not ll_file:
+ raise ValueError("I/O operation on closed file")
+ res = c_fseek(ll_file, pos, whence)
+ if res == -1:
+ errno = rposix.get_errno()
+ raise OSError(errno, os.strerror(errno))
+
+ def fileno(self):
+ if self.ll_file:
+ return intmask(c_fileno(self.ll_file))
+ raise ValueError("I/O operation on closed file")
+
+ def tell(self):
+ if self.ll_file:
+ res = intmask(c_ftell(self.ll_file))
+ if res == -1:
+ errno = rposix.get_errno()
+ raise OSError(errno, os.strerror(errno))
+ return res
+ raise ValueError("I/O operation on closed file")
+
+ def flush(self):
+ if self.ll_file:
+ res = c_fflush(self.ll_file)
+ if res != 0:
+ errno = rposix.get_errno()
+ raise OSError(errno, os.strerror(errno))
+ return
+ raise ValueError("I/O operation on closed file")
+
+ def truncate(self, arg=-1):
+ if self.ll_file:
+ if arg == -1:
+ arg = self.tell()
+ res = c_ftruncate(self.fileno(), arg)
+ if res == -1:
+ errno = rposix.get_errno()
+ raise OSError(errno, os.strerror(errno))
+ return
+ raise ValueError("I/O operation on closed file")
+
+ def __del__(self):
+ self.close()
+
+ def _readline1(self, raw_buf):
+ result = c_fgets(raw_buf, BASE_LINE_SIZE, self.ll_file)
+ if not result:
+ if c_feof(self.ll_file): # ok
+ return 0
+ errno = c_ferror(self.ll_file)
+ raise OSError(errno, os.strerror(errno))
+ #
+ # Assume that fgets() works as documented, and additionally
+ # never writes beyond the final \0, which the CPython
+ # fileobject.c says appears to be the case everywhere.
+ # The only case where the buffer was not big enough is the
+ # case where the buffer is full, ends with \0, and doesn't
+ # end with \n\0.
+ strlen = 0
+ while raw_buf[strlen] != '\0':
+ strlen += 1
+ if (strlen == BASE_LINE_SIZE - 1 and
+ raw_buf[BASE_LINE_SIZE - 2] != '\n'):
+ return -1 # overflow!
+ # common case
+ return strlen
+
+ def readline(self):
+ if self.ll_file:
+ raw_buf, gc_buf = rffi.alloc_buffer(BASE_LINE_SIZE)
+ try:
+ c = self._readline1(raw_buf)
+ if c >= 0:
+ return rffi.str_from_buffer(raw_buf, gc_buf,
+ BASE_LINE_SIZE, c)
+ #
+ # this is the rare case: the line is longer than BASE_LINE_SIZE
+ s = StringBuilder()
+ while True:
+ s.append_charpsize(raw_buf, BASE_LINE_SIZE - 1)
+ c = self._readline1(raw_buf)
+ if c >= 0:
+ break
+ #
+ s.append_charpsize(raw_buf, c)
+ return s.build()
+ finally:
+ rffi.keep_buffer_alive_until_here(raw_buf, gc_buf)
+ raise ValueError("I/O operation on closed file")
diff --git a/rpython/rlib/test/test_rfile.py b/rpython/rlib/test/test_rfile.py
--- a/rpython/rlib/test/test_rfile.py
+++ b/rpython/rlib/test/test_rfile.py
@@ -78,3 +78,100 @@
f()
self.interpret(f, [])
+
+ def test_fileno(self):
+ fname = str(self.tmpdir.join('file_5'))
+
+ def f():
+ f = open(fname, "w")
+ try:
+ return f.fileno()
+ finally:
+ f.close()
+
+ res = self.interpret(f, [])
+ assert res > 2
+
+ def test_tell(self):
+ fname = str(self.tmpdir.join('file_tell'))
+
+ def f():
+ f = open(fname, "w")
+ f.write("xyz")
+ try:
+ return f.tell()
+ finally:
+ f.close()
+
+ res = self.interpret(f, [])
+ assert res == 3
+
+ def test_flush(self):
+ fname = str(self.tmpdir.join('file_flush'))
+
+ def f():
+ f = open(fname, "w")
+ f.write("xyz")
+ f.flush()
+ f2 = open(fname)
+ assert f2.read() == "xyz"
+ f2.close()
+ f.close()
+
+ self.interpret(f, [])
+
+ def test_truncate(self):
+ fname = str(self.tmpdir.join('file_trunc'))
+
+ def f():
+ f = open(fname, "w")
+ f.write("xyz")
+ f.seek(0)
+ f.truncate(2)
+ f.close()
+ f2 = open(fname)
+ assert f2.read() == "xy"
+ f2.close()
+
+ f()
+ self.interpret(f, [])
+
+
+class TestDirect:
+ def setup_class(cls):
+ cls.tmpdir = udir.join('test_rfile_direct')
+ cls.tmpdir.ensure(dir=True)
+
+ def test_readline(self):
+ fname = str(self.tmpdir.join('file_readline'))
+ j = 0
+ expected = []
+ with open(fname, 'w') as f:
+ for i in range(250):
+ s = ''.join([chr(32+(k&63)) for k in range(j, j + i)])
+ j += 1
+ print >> f, s
+ expected = open(fname).readlines()
+ expected += ['', '']
+ assert len(expected) == 252
+
+ f = rfile.create_file(fname, 'r')
+ for j in range(252):
+ got = f.readline()
+ assert got == expected[j]
+ f.close()
+
+ def test_readline_without_eol_at_the_end(self):
+ fname = str(self.tmpdir.join('file_readline_without_eol_at_the_end'))
+ for n in [1, 10, 97, 98, 99, 100, 101, 102, 103, 150,
+ 196, 197, 198, 199, 200, 201, 202, 203, 204, 250]:
+ s = ''.join([chr(32+(k&63)) for k in range(n)])
+ with open(fname, 'wb') as f:
+ f.write(s)
+
+ f = rfile.create_file(fname, 'r')
+ got = f.readline()
+ assert got == s
+ got = f.readline()
+ assert got == ''
+ f.close()
diff --git a/rpython/rlib/test/test_rsocket.py b/rpython/rlib/test/test_rsocket.py
--- a/rpython/rlib/test/test_rsocket.py
+++ b/rpython/rlib/test/test_rsocket.py
@@ -301,6 +301,8 @@
addr.get_port() == 80):
found = True
assert found, lst
+ # The following might fail if the DNS redirects failed requests to a
+ # catch-all address (i.e. opendns).
e = py.test.raises(GAIError, getaddrinfo, 'www.very-invalidaddress.com', None)
assert isinstance(e.value.get_msg(), str)
diff --git a/rpython/rlib/types.py b/rpython/rlib/types.py
--- a/rpython/rlib/types.py
+++ b/rpython/rlib/types.py
@@ -39,8 +39,12 @@
return model.SomeUnicodeString(no_nul=True)
-def str():
- return model.SomeString()
+def str(can_be_None=False):
+ return model.SomeString(can_be_None=can_be_None)
+
+
+def bytearray():
+ return model.SomeByteArray()
def str0():
diff --git a/rpython/rtyper/lltypesystem/rbytearray.py b/rpython/rtyper/lltypesystem/rbytearray.py
--- a/rpython/rtyper/lltypesystem/rbytearray.py
+++ b/rpython/rtyper/lltypesystem/rbytearray.py
@@ -16,6 +16,9 @@
lltype.Char,
'bytearray_from_str')
+def _empty_bytearray():
+ return empty
+
BYTEARRAY.become(lltype.GcStruct('rpy_bytearray',
('chars', lltype.Array(lltype.Char)), adtmeths={
'malloc' : lltype.staticAdtMethod(mallocbytearray),
@@ -23,8 +26,11 @@
'copy_contents_from_str': lltype.staticAdtMethod(
copy_bytearray_contents_from_str),
'length': rstr.LLHelpers.ll_length,
+ 'empty': lltype.staticAdtMethod(_empty_bytearray),
}))
+empty = lltype.malloc(BYTEARRAY, 0, immortal=True)
+
class LLHelpers(rstr.LLHelpers):
@classmethod
def ll_strsetitem(cls, s, i, item):
diff --git a/rpython/rtyper/lltypesystem/rfile.py b/rpython/rtyper/lltypesystem/rfile.py
deleted file mode 100644
--- a/rpython/rtyper/lltypesystem/rfile.py
+++ /dev/null
@@ -1,195 +0,0 @@
-
-import os
-from rpython.rlib import rposix
-from rpython.rlib.rarithmetic import r_uint
-from rpython.annotator import model as annmodel
-from rpython.rtyper.rtyper import Repr
-from rpython.rlib.rstring import StringBuilder
-from rpython.rtyper.lltypesystem import lltype, rffi, llmemory
-from rpython.rtyper.lltypesystem.rstr import string_repr, STR
-from rpython.translator.tool.cbuild import ExternalCompilationInfo
-from rpython.rtyper.annlowlevel import hlstr
-from rpython.rtyper.lltypesystem.lloperation import llop
-
-FILE = lltype.Struct('FILE') # opaque type maybe
-FILE_WRAPPER = lltype.GcStruct("FileWrapper", ('file', lltype.Ptr(FILE)))
-
-eci = ExternalCompilationInfo(includes=['stdio.h'])
-
-def llexternal(*args):
- return rffi.llexternal(*args, compilation_info=eci)
-
-c_open = llexternal('fopen', [rffi.CCHARP, rffi.CCHARP], lltype.Ptr(FILE))
-c_close = llexternal('fclose', [lltype.Ptr(FILE)], rffi.INT)
-c_write = llexternal('fwrite', [rffi.CCHARP, rffi.SIZE_T, rffi.SIZE_T,
- lltype.Ptr(FILE)], rffi.SIZE_T)
-c_read = llexternal('fread', [rffi.CCHARP, rffi.SIZE_T, rffi.SIZE_T,
- lltype.Ptr(FILE)], rffi.SIZE_T)
-c_feof = llexternal('feof', [lltype.Ptr(FILE)], rffi.INT)
-c_ferror = llexternal('ferror', [lltype.Ptr(FILE)], rffi.INT)
-c_clearerror = llexternal('clearerr', [lltype.Ptr(FILE)], lltype.Void)
-c_fseek = llexternal('fseek', [lltype.Ptr(FILE), rffi.LONG, rffi.INT],
- rffi.INT)
-c_tmpfile = llexternal('tmpfile', [], lltype.Ptr(FILE))
-
-def ll_open(name, mode):
- file_wrapper = lltype.malloc(FILE_WRAPPER)
- ll_name = rffi.str2charp(name)
- ll_mode = rffi.str2charp(mode)
- try:
- ll_f = c_open(ll_name, ll_mode)
- if not ll_f:
- errno = rposix.get_errno()
- raise OSError(errno, os.strerror(errno))
- file_wrapper.file = ll_f
- finally:
- lltype.free(ll_name, flavor='raw')
- lltype.free(ll_mode, flavor='raw')
- return file_wrapper
-
-def ll_tmpfile():
- file_wrapper = lltype.malloc(FILE_WRAPPER)
- res = c_tmpfile()
- if not res:
- errno = rposix.get_errno()
- raise OSError(errno, os.strerror(errno))
- file_wrapper.file = res
- return file_wrapper
-
-def ll_write(file_wrapper, value):
- ll_file = file_wrapper.file
- if not ll_file:
- raise ValueError("I/O operation on closed file")
- value = hlstr(value)
- assert value is not None
- ll_value = rffi.get_nonmovingbuffer(value)
- try:
- # note that since we got a nonmoving buffer, it is either raw
- # or already cannot move, so the arithmetics below are fine
- total_bytes = 0
- ll_current = ll_value
- while total_bytes < len(value):
- bytes = c_write(ll_current, 1, len(value) - r_uint(total_bytes),
- ll_file)
- if bytes == 0:
- errno = rposix.get_errno()
- raise OSError(errno, os.strerror(errno))
- total_bytes += bytes
- ll_current = rffi.cast(rffi.CCHARP,
- rffi.cast(lltype.Unsigned, ll_value) +
- total_bytes)
- finally:
- rffi.free_nonmovingbuffer(value, ll_value)
-
-BASE_BUF_SIZE = 4096
-
-def ll_read(file_wrapper, size):
- ll_file = file_wrapper.file
- if not ll_file:
- raise ValueError("I/O operation on closed file")
- if size < 0:
- # read the entire contents
- buf = lltype.malloc(rffi.CCHARP.TO, BASE_BUF_SIZE, flavor='raw')
- try:
- s = StringBuilder()
- while True:
- returned_size = c_read(buf, 1, BASE_BUF_SIZE, ll_file)
- if returned_size == 0:
- if c_feof(ll_file):
- # ok, finished
- return s.build()
- errno = c_ferror(ll_file)
- c_clearerror(ll_file)
- raise OSError(errno, os.strerror(errno))
- s.append_charpsize(buf, returned_size)
- finally:
- lltype.free(buf, flavor='raw')
- else:
- raw_buf, gc_buf = rffi.alloc_buffer(size)
- try:
- returned_size = c_read(raw_buf, 1, size, ll_file)
- if returned_size == 0:
- if not c_feof(ll_file):
- errno = c_ferror(ll_file)
- raise OSError(errno, os.strerror(errno))
- s = rffi.str_from_buffer(raw_buf, gc_buf, size,
- rffi.cast(lltype.Signed, returned_size))
- finally:
- rffi.keep_buffer_alive_until_here(raw_buf, gc_buf)
- return s
-def ll_seek(file_wrapper, pos, whence):
- ll_file = file_wrapper.file
- if not ll_file:
- raise ValueError("I/O operation on closed file")
- res = c_fseek(ll_file, pos, whence)
- if res == -1:
- errno = rposix.get_errno()
- raise OSError(errno, os.strerror(errno))
-
-def ll_close(file_wrapper):
- if file_wrapper.file:
- # double close is allowed
- res = c_close(file_wrapper.file)
- file_wrapper.file = lltype.nullptr(FILE)
- if res == -1:
- errno = rposix.get_errno()
- raise OSError(errno, os.strerror(errno))
-
-class FileRepr(Repr):
- lowleveltype = lltype.Ptr(FILE_WRAPPER)
-
- def __init__(self, typer):
- Repr.__init__(self)
-
- def rtype_constructor(self, hop):
- repr = hop.rtyper.getrepr(annmodel.SomeString())
- arg_0 = hop.inputarg(repr, 0)
- if len(hop.args_v) == 1:
- arg_1 = hop.inputconst(string_repr, "r")
- else:
- arg_1 = hop.inputarg(repr, 1)
- hop.exception_is_here()
- open = hop.rtyper.getannmixlevel().delayedfunction(
- ll_open, [annmodel.SomeString()] * 2,
- annmodel.SomePtr(self.lowleveltype))
- v_open = hop.inputconst(lltype.typeOf(open), open)
- return hop.genop('direct_call', [v_open, arg_0, arg_1],
- resulttype=self)
-
- def rtype_tempfile(self, hop):
- tmpfile = hop.rtyper.getannmixlevel().delayedfunction(
- ll_tmpfile, [], annmodel.SomePtr(self.lowleveltype))
- v_tmpfile = hop.inputconst(lltype.typeOf(tmpfile), tmpfile)
- hop.exception_is_here()
- return hop.genop('direct_call', [v_tmpfile], resulttype=self)
-
-
- def rtype_method_write(self, hop):
- args_v = hop.inputargs(self, string_repr)
- hop.exception_is_here()
- return hop.gendirectcall(ll_write, *args_v)
-
- def rtype_method_close(self, hop):
- r_self = hop.inputarg(self, 0)
- hop.exception_is_here()
- return hop.gendirectcall(ll_close, r_self)
-
- def rtype_method_read(self, hop):
- r_self = hop.inputarg(self, 0)
- if len(hop.args_v) != 2:
- arg_1 = hop.inputconst(lltype.Signed, -1)
- else:
- arg_1 = hop.inputarg(lltype.Signed, 1)
- hop.exception_is_here()
- return hop.gendirectcall(ll_read, r_self, arg_1)
-
- def rtype_method_seek(self, hop):
- r_self = hop.inputarg(self, 0)
- arg_1 = hop.inputarg(lltype.Signed, 1)
- if len(hop.args_v) != 3:
- arg_2 = hop.inputconst(lltype.Signed, os.SEEK_SET)
- else:
- arg_2 = hop.inputarg(lltype.Signed, 2)
- hop.exception_is_here()
- return hop.gendirectcall(ll_seek, r_self, arg_1, arg_2)
-
diff --git a/rpython/rtyper/module/ll_os.py b/rpython/rtyper/module/ll_os.py
--- a/rpython/rtyper/module/ll_os.py
+++ b/rpython/rtyper/module/ll_os.py
@@ -1685,7 +1685,7 @@
def tmpnam_llimpl():
return rffi.charp2str(os_tmpnam(lltype.nullptr(rffi.CCHARP.TO)))
- return extdef([], None, llimpl=tmpnam_llimpl,
+ return extdef([], str, llimpl=tmpnam_llimpl,
export_name="ll_os.ll_os_tmpnam")
# --------------------------- os.stat & variants ---------------------------
diff --git a/rpython/rtyper/rstr.py b/rpython/rtyper/rstr.py
--- a/rpython/rtyper/rstr.py
+++ b/rpython/rtyper/rstr.py
@@ -187,13 +187,15 @@
if hop.nb_args > 2:
v_start = hop.inputarg(Signed, arg=2)
if not hop.args_s[2].nonneg:
- raise TyperError("str.find() start must be proven non-negative")
+ raise TyperError("str.%s() start must be proven non-negative"
+ % (reverse and 'rfind' or 'find',))
else:
v_start = hop.inputconst(Signed, 0)
if hop.nb_args > 3:
v_end = hop.inputarg(Signed, arg=3)
if not hop.args_s[3].nonneg:
- raise TyperError("str.find() end must be proven non-negative")
+ raise TyperError("str.%s() end must be proven non-negative"
+ % (reverse and 'rfind' or 'find',))
else:
v_end = hop.gendirectcall(self.ll.ll_strlen, v_str)
hop.exception_cannot_occur()
diff --git a/rpython/rtyper/test/test_rbytearray.py b/rpython/rtyper/test/test_rbytearray.py
--- a/rpython/rtyper/test/test_rbytearray.py
+++ b/rpython/rtyper/test/test_rbytearray.py
@@ -50,3 +50,10 @@
ll_res = self.interpret(f, [123])
assert hlstr(ll_res) == "123"
+
+ def test_getslice(self):
+ def f(x):
+ return str(bytearray(str(x))[1:2])
+
+ ll_res = self.interpret(f, [123])
+ assert hlstr(ll_res) == "2"
diff --git a/rpython/rtyper/test/test_rint.py b/rpython/rtyper/test/test_rint.py
--- a/rpython/rtyper/test/test_rint.py
+++ b/rpython/rtyper/test/test_rint.py
@@ -85,6 +85,14 @@
res = self.ll_to_string(res)
assert res == '-0x8' + '0' * (len(res)-4)
+ def test_hex_of_uint(self):
+ def dummy(i):
+ return hex(r_uint(i))
+
+ res = self.interpret(dummy, [-5])
+ res = self.ll_to_string(res)
+ assert res == '0x' + 'f' * (len(res)-3) + 'b'
+
def test_oct_of_int(self):
def dummy(i):
return oct(i)
diff --git a/rpython/rtyper/test/test_rstr.py b/rpython/rtyper/test/test_rstr.py
--- a/rpython/rtyper/test/test_rstr.py
+++ b/rpython/rtyper/test/test_rstr.py
@@ -416,6 +416,14 @@
res = self.interpret(f, [i])
assert res == expected
+ def test_rfind_error_message(self):
+ const = self.const
+ def f(i):
+ return const("abc").rfind(const(''), i)
+ e = py.test.raises(TyperError, self.interpret, f, [-5])
+ assert str(e.value).startswith(
+ 'str.rfind() start must be proven non-negative')
+
def test_find_char(self):
const = self.const
def fn(ch):
@@ -1134,4 +1142,4 @@
array = lltype.malloc(TP, 12, flavor='raw')
self.interpret(f, [array, 4])
assert list(array) == list('abc'*4)
- lltype.free(array, flavor='raw')
\ No newline at end of file
+ lltype.free(array, flavor='raw')
diff --git a/rpython/translator/c/src/stacklet/switch_arm_gcc.h b/rpython/translator/c/src/stacklet/switch_arm_gcc.h
--- a/rpython/translator/c/src/stacklet/switch_arm_gcc.h
+++ b/rpython/translator/c/src/stacklet/switch_arm_gcc.h
@@ -1,9 +1,8 @@
-#if __ARM_ARCH__ >= 5
-# define call_reg(x) "blx " #x "\n"
-#elif defined (__ARM_ARCH_4T__)
+#if defined(__ARM_ARCH_4__) || defined (__ARM_ARCH_4T__)
# define call_reg(x) "mov lr, pc ; bx " #x "\n"
#else
-# define call_reg(x) "mov lr, pc ; mov pc, " #x "\n"
+/* ARM >= 5 */
+# define call_reg(x) "blx " #x "\n"
#endif
static void __attribute__((optimize("O3"))) *slp_switch(void *(*save_state)(void*, void*),
diff --git a/rpython/translator/tool/graphpage.py b/rpython/translator/tool/graphpage.py
--- a/rpython/translator/tool/graphpage.py
+++ b/rpython/translator/tool/graphpage.py
@@ -200,7 +200,7 @@
dotgen.emit_edge(nameof(cdef), nameof(prevcdef), color="red")
prevcdef = cdef
cdef = cdef.basedef
-
+
self.source = dotgen.generate(target=None)
def followlink(self, name):
@@ -224,7 +224,7 @@
dotgen.emit('mclimit=15.0')
self.do_compute(dotgen, *args, **kwds)
-
+
self.source = dotgen.generate(target=None)
# link the function names to the individual flow graphs
@@ -264,7 +264,7 @@
data = self.labelof(classdef, classdef.shortname)
dotgen.emit_node(nameof(classdef), label=data, shape="box")
dotgen.emit_edge(nameof(classdef.basedef), nameof(classdef))
-
+
def labelof(self, obj, objname):
name = objname
i = 1
@@ -409,22 +409,11 @@
elif isinstance(obj, Link):
try_show(obj.prevblock)
elif isinstance(obj, Block):
- import gc
- pending = [obj] # pending blocks
- seen = {obj: True, None: True}
- for x in pending:
- for y in gc.get_referrers(x):
- if isinstance(y, FunctionGraph):
- y.show()
- return
- elif isinstance(y, Link):
- block = y.prevblock
- if block not in seen:
- pending.append(block)
- seen[block] = True
- elif isinstance(y, dict):
- pending.append(y) # go back from the dict to the real obj
- graph = IncompleteGraph(pending)
+ graph = obj.get_graph()
+ if isinstance(graph, FunctionGraph):
+ graph.show()
+ return
+ graph = IncompleteGraph(graph)
SingleGraphPage(graph).display()
else:
raise TypeError("try_show(%r object)" % (type(obj).__name__,))
@@ -449,7 +438,7 @@
seen[block] = True
return pending
else:
- raise TypeError("try_get_functiongraph(%r object)" % (type(obj).__name__,))
+ raise TypeError("try_get_functiongraph(%r object)" % (type(obj).__name__,))
class IncompleteGraph:
name = '(incomplete graph)'
More information about the pypy-commit
mailing list