Author: Christian Tismer <tis...@stackless.com> Branch: win64-stage1 Changeset: r49358:cddd6dcfc376 Date: 2011-11-12 13:22 +0100 http://bitbucket.org/pypy/pypy/changeset/cddd6dcfc376/
Log: merge diff --git a/lib-python/modified-2.7/test/test_import.py b/lib-python/modified-2.7/test/test_import.py --- a/lib-python/modified-2.7/test/test_import.py +++ b/lib-python/modified-2.7/test/test_import.py @@ -64,6 +64,7 @@ except ImportError, err: self.fail("import from %s failed: %s" % (ext, err)) else: + # XXX importing .pyw is missing on Windows self.assertEqual(mod.a, a, "module loaded (%s) but contents invalid" % mod) self.assertEqual(mod.b, b, diff --git a/lib-python/modified-2.7/test/test_repr.py b/lib-python/modified-2.7/test/test_repr.py --- a/lib-python/modified-2.7/test/test_repr.py +++ b/lib-python/modified-2.7/test/test_repr.py @@ -254,8 +254,14 @@ eq = self.assertEqual touch(os.path.join(self.subpkgname, self.pkgname + os.extsep + 'py')) from areallylongpackageandmodulenametotestreprtruncation.areallylongpackageandmodulenametotestreprtruncation import areallylongpackageandmodulenametotestreprtruncation - eq(repr(areallylongpackageandmodulenametotestreprtruncation), - "<module '%s' from '%s'>" % (areallylongpackageandmodulenametotestreprtruncation.__name__, areallylongpackageandmodulenametotestreprtruncation.__file__)) + # On PyPy, we use %r to format the file name; on CPython it is done + # with '%s'. It seems to me that %r is safer <arigo>. + if '__pypy__' in sys.builtin_module_names: + eq(repr(areallylongpackageandmodulenametotestreprtruncation), + "<module %r from %r>" % (areallylongpackageandmodulenametotestreprtruncation.__name__, areallylongpackageandmodulenametotestreprtruncation.__file__)) + else: + eq(repr(areallylongpackageandmodulenametotestreprtruncation), + "<module '%s' from '%s'>" % (areallylongpackageandmodulenametotestreprtruncation.__name__, areallylongpackageandmodulenametotestreprtruncation.__file__)) eq(repr(sys), "<module 'sys' (built-in)>") def test_type(self): diff --git a/lib-python/2.7/test/test_subprocess.py b/lib-python/modified-2.7/test/test_subprocess.py copy from lib-python/2.7/test/test_subprocess.py copy to lib-python/modified-2.7/test/test_subprocess.py --- a/lib-python/2.7/test/test_subprocess.py +++ b/lib-python/modified-2.7/test/test_subprocess.py @@ -16,11 +16,11 @@ # Depends on the following external programs: Python # -if mswindows: - SETBINARY = ('import msvcrt; msvcrt.setmode(sys.stdout.fileno(), ' - 'os.O_BINARY);') -else: - SETBINARY = '' +#if mswindows: +# SETBINARY = ('import msvcrt; msvcrt.setmode(sys.stdout.fileno(), ' +# 'os.O_BINARY);') +#else: +# SETBINARY = '' try: @@ -420,8 +420,9 @@ self.assertStderrEqual(stderr, "") def test_universal_newlines(self): - p = subprocess.Popen([sys.executable, "-c", - 'import sys,os;' + SETBINARY + + # NB. replaced SETBINARY with the -u flag + p = subprocess.Popen([sys.executable, "-u", "-c", + 'import sys,os;' + #SETBINARY + 'sys.stdout.write("line1\\n");' 'sys.stdout.flush();' 'sys.stdout.write("line2\\r");' @@ -448,8 +449,9 @@ def test_universal_newlines_communicate(self): # universal newlines through communicate() - p = subprocess.Popen([sys.executable, "-c", - 'import sys,os;' + SETBINARY + + # NB. replaced SETBINARY with the -u flag + p = subprocess.Popen([sys.executable, "-u", "-c", + 'import sys,os;' + #SETBINARY + 'sys.stdout.write("line1\\n");' 'sys.stdout.flush();' 'sys.stdout.write("line2\\r");' diff --git a/pypy/jit/codewriter/call.py b/pypy/jit/codewriter/call.py --- a/pypy/jit/codewriter/call.py +++ b/pypy/jit/codewriter/call.py @@ -212,7 +212,10 @@ elidable = False loopinvariant = False if op.opname == "direct_call": - func = getattr(get_funcobj(op.args[0].value), '_callable', None) + funcobj = get_funcobj(op.args[0].value) + assert getattr(funcobj, 'calling_conv', 'c') == 'c', ( + "%r: getcalldescr() with a non-default call ABI" % (op,)) + func = getattr(funcobj, '_callable', None) elidable = getattr(func, "_elidable_function_", False) loopinvariant = getattr(func, "_jit_loop_invariant_", False) if loopinvariant: diff --git a/pypy/module/_rawffi/structure.py b/pypy/module/_rawffi/structure.py --- a/pypy/module/_rawffi/structure.py +++ b/pypy/module/_rawffi/structure.py @@ -212,6 +212,8 @@ while count + basic_size <= total_size: fieldtypes.append(basic_ffi_type) count += basic_size + if basic_size == 0: # corner case. get out of this infinite + break # loop after 1 iteration ("why not") self.ffi_struct = clibffi.make_struct_ffitype_e(self.size, self.alignment, fieldtypes) diff --git a/pypy/module/imp/importing.py b/pypy/module/imp/importing.py --- a/pypy/module/imp/importing.py +++ b/pypy/module/imp/importing.py @@ -513,7 +513,7 @@ space.warn(msg, space.w_ImportWarning) modtype, suffix, filemode = find_modtype(space, filepart) try: - if modtype in (PY_SOURCE, PY_COMPILED): + if modtype in (PY_SOURCE, PY_COMPILED, C_EXTENSION): assert suffix is not None filename = filepart + suffix stream = streamio.open_file_as_stream(filename, filemode) @@ -522,9 +522,6 @@ except: stream.close() raise - if modtype == C_EXTENSION: - filename = filepart + suffix - return FindInfo(modtype, filename, None, suffix, filemode) except StreamErrors: pass # XXX! must not eat all exceptions, e.g. # Out of file descriptors. 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 @@ -137,6 +137,8 @@ interpleveldefs['execve'] = 'interp_posix.execve' if hasattr(posix, 'spawnv'): interpleveldefs['spawnv'] = 'interp_posix.spawnv' + if hasattr(posix, 'spawnve'): + interpleveldefs['spawnve'] = 'interp_posix.spawnve' if hasattr(os, 'uname'): interpleveldefs['uname'] = 'interp_posix.uname' if hasattr(os, 'sysconf'): 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 @@ -760,6 +760,14 @@ except OSError, e: raise wrap_oserror(space, e) +def _env2interp(space, w_env): + env = {} + w_keys = space.call_method(w_env, 'keys') + for w_key in space.unpackiterable(w_keys): + w_value = space.getitem(w_env, w_key) + env[space.str_w(w_key)] = space.str_w(w_value) + return env + def execve(space, w_command, w_args, w_env): """ execve(path, args, env) @@ -771,11 +779,7 @@ """ command = fsencode_w(space, w_command) args = [fsencode_w(space, w_arg) for w_arg in space.unpackiterable(w_args)] - env = {} - w_keys = space.call_method(w_env, 'keys') - for w_key in space.unpackiterable(w_keys): - w_value = space.getitem(w_env, w_key) - env[space.str_w(w_key)] = space.str_w(w_value) + env = _env2interp(space, w_env) try: os.execve(command, args, env) except OSError, e: @@ -790,6 +794,16 @@ raise wrap_oserror(space, e) return space.wrap(ret) +@unwrap_spec(mode=int, path=str) +def spawnve(space, mode, path, w_args, w_env): + args = [space.str_w(w_arg) for w_arg in space.unpackiterable(w_args)] + env = _env2interp(space, w_env) + try: + ret = os.spawnve(mode, path, args, env) + except OSError, e: + raise wrap_oserror(space, e) + return space.wrap(ret) + def utime(space, w_path, w_tuple): """ utime(path, (atime, mtime)) utime(path, None) diff --git a/pypy/module/posix/test/test_posix2.py b/pypy/module/posix/test/test_posix2.py --- a/pypy/module/posix/test/test_posix2.py +++ b/pypy/module/posix/test/test_posix2.py @@ -471,6 +471,17 @@ ['python', '-c', 'raise(SystemExit(42))']) assert ret == 42 + if hasattr(__import__(os.name), "spawnve"): + def test_spawnve(self): + os = self.posix + import sys + print self.python + ret = os.spawnve(os.P_WAIT, self.python, + ['python', '-c', + "raise(SystemExit(int(__import__('os').environ['FOOBAR'])))"], + {'FOOBAR': '42'}) + assert ret == 42 + def test_popen(self): os = self.posix for i in range(5): diff --git a/pypy/module/pypyjit/test_pypy_c/model.py b/pypy/module/pypyjit/test_pypy_c/model.py --- a/pypy/module/pypyjit/test_pypy_c/model.py +++ b/pypy/module/pypyjit/test_pypy_c/model.py @@ -285,6 +285,11 @@ guard_false(ticker_cond1, descr=...) """ src = src.replace('--EXC-TICK--', exc_ticker_check) + # + # ISINF is done as a macro; fix it here + r = re.compile('(\w+) = --ISINF--[(](\w+)[)]') + src = r.sub(r'\2\B999 = float_add(\2, ...)\n\1 = float_eq(\2\B999, \2)', + src) return src @classmethod diff --git a/pypy/module/pypyjit/test_pypy_c/test_math.py b/pypy/module/pypyjit/test_pypy_c/test_math.py --- a/pypy/module/pypyjit/test_pypy_c/test_math.py +++ b/pypy/module/pypyjit/test_pypy_c/test_math.py @@ -1,3 +1,4 @@ +import py from pypy.module.pypyjit.test_pypy_c.test_00_model import BaseTestPyPyC @@ -49,10 +50,7 @@ guard_true(i2, descr=...) guard_not_invalidated(descr=...) f1 = cast_int_to_float(i0) - i3 = float_eq(f1, inf) - i4 = float_eq(f1, -inf) - i5 = int_or(i3, i4) - i6 = int_is_true(i5) + i6 = --ISINF--(f1) guard_false(i6, descr=...) f2 = call(ConstClass(sin), f1, descr=<FloatCallDescr>) f3 = call(ConstClass(cos), f1, descr=<FloatCallDescr>) @@ -64,6 +62,7 @@ """) def test_fmod(self): + py.test.skip("test relies on the old and broken ll_math_fmod") def main(n): import math @@ -90,4 +89,4 @@ i6 = int_sub(i0, 1) --TICK-- jump(..., descr=) - """) \ No newline at end of file + """) diff --git a/pypy/objspace/std/bytearraytype.py b/pypy/objspace/std/bytearraytype.py --- a/pypy/objspace/std/bytearraytype.py +++ b/pypy/objspace/std/bytearraytype.py @@ -122,10 +122,11 @@ return -1 def descr_fromhex(space, w_type, w_hexstring): - "bytearray.fromhex(string) -> bytearray\n\nCreate a bytearray object " - "from a string of hexadecimal numbers.\nSpaces between two numbers are " - "accepted.\nExample: bytearray.fromhex('B9 01EF') -> " - "bytearray(b'\\xb9\\x01\\xef')." + "bytearray.fromhex(string) -> bytearray\n" + "\n" + "Create a bytearray object from a string of hexadecimal numbers.\n" + "Spaces between two numbers are accepted.\n" + "Example: bytearray.fromhex('B9 01EF') -> bytearray(b'\\xb9\\x01\\xef')." hexstring = space.str_w(w_hexstring) hexstring = hexstring.lower() data = [] diff --git a/pypy/objspace/std/intobject.py b/pypy/objspace/std/intobject.py --- a/pypy/objspace/std/intobject.py +++ b/pypy/objspace/std/intobject.py @@ -16,7 +16,10 @@ something CPython does not do anymore. """ -class W_IntObject(W_Object): +class W_AbstractIntObject(W_Object): + pass + +class W_IntObject(W_AbstractIntObject): __slots__ = 'intval' _immutable_fields_ = ['intval'] diff --git a/pypy/objspace/std/iterobject.py b/pypy/objspace/std/iterobject.py --- a/pypy/objspace/std/iterobject.py +++ b/pypy/objspace/std/iterobject.py @@ -4,7 +4,10 @@ from pypy.objspace.std.register_all import register_all -class W_AbstractSeqIterObject(W_Object): +class W_AbstractIterObject(W_Object): + pass + +class W_AbstractSeqIterObject(W_AbstractIterObject): from pypy.objspace.std.itertype import iter_typedef as typedef def __init__(w_self, w_seq, index=0): 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 @@ -11,7 +11,10 @@ from pypy.rlib.listsort import make_timsort_class from pypy.interpreter.argument import Signature -class W_ListObject(W_Object): +class W_AbstractListObject(W_Object): + pass + +class W_ListObject(W_AbstractListObject): from pypy.objspace.std.listtype import list_typedef as typedef def __init__(w_self, wrappeditems): diff --git a/pypy/objspace/std/longobject.py b/pypy/objspace/std/longobject.py --- a/pypy/objspace/std/longobject.py +++ b/pypy/objspace/std/longobject.py @@ -8,7 +8,10 @@ from pypy.objspace.std.noneobject import W_NoneObject from pypy.rlib.rbigint import rbigint, SHIFT -class W_LongObject(W_Object): +class W_AbstractLongObject(W_Object): + pass + +class W_LongObject(W_AbstractLongObject): """This is a wrapper of rbigint.""" from pypy.objspace.std.longtype import long_typedef as typedef _immutable_fields_ = ['num'] diff --git a/pypy/objspace/std/objspace.py b/pypy/objspace/std/objspace.py --- a/pypy/objspace/std/objspace.py +++ b/pypy/objspace/std/objspace.py @@ -83,12 +83,7 @@ if self.config.objspace.std.withtproxy: transparent.setup(self) - interplevel_classes = {} - for type, classes in self.model.typeorder.iteritems(): - if len(classes) >= 3: # XXX what does this 3 mean??! - # W_Root, AnyXxx and actual object - interplevel_classes[self.gettypefor(type)] = classes[0][0] - self._interplevel_classes = interplevel_classes + self.setup_isinstance_cache() def get_builtin_types(self): return self.builtin_types @@ -592,6 +587,63 @@ def isinstance_w(space, w_inst, w_type): return space._type_isinstance(w_inst, w_type) + def setup_isinstance_cache(self): + # This assumes that all classes in the stdobjspace implementing a + # particular app-level type are distinguished by a common base class. + # Alternatively, you can turn off the cache on specific classes, + # like e.g. proxyobject. It is just a bit less performant but + # should not have any bad effect. + from pypy.objspace.std.model import W_Root, W_Object + # + # Build a dict {class: w_typeobject-or-None}. The value None is used + # on classes that are known to be abstract base classes. + class2type = {} + class2type[W_Root] = None + class2type[W_Object] = None + for cls in self.model.typeorder.keys(): + if getattr(cls, 'typedef', None) is None: + continue + if getattr(cls, 'ignore_for_isinstance_cache', False): + continue + w_type = self.gettypefor(cls) + w_oldtype = class2type.setdefault(cls, w_type) + assert w_oldtype is w_type + # + # Build the real dict {w_typeobject: class-or-base-class}. For every + # w_typeobject we look for the most precise common base class of all + # the registered classes. If no such class is found, we will find + # W_Object or W_Root, and complain. Then you must either add an + # artificial common base class, or disable caching on one of the + # two classes with ignore_for_isinstance_cache. + def getmro(cls): + while True: + yield cls + if cls is W_Root: + break + cls = cls.__bases__[0] + self._interplevel_classes = {} + for cls, w_type in class2type.items(): + if w_type is None: + continue + if w_type not in self._interplevel_classes: + self._interplevel_classes[w_type] = cls + else: + cls1 = self._interplevel_classes[w_type] + mro1 = list(getmro(cls1)) + for base in getmro(cls): + if base in mro1: + break + if base in class2type and class2type[base] is not w_type: + if class2type.get(base) is None: + msg = ("cannot find a common interp-level base class" + " between %r and %r" % (cls1, cls)) + else: + msg = ("%s is a base class of both %r and %r" % ( + class2type[base], cls1, cls)) + raise AssertionError("%r: %s" % (w_type, msg)) + class2type[base] = w_type + self._interplevel_classes[w_type] = base + @specialize.memo() def _get_interplevel_cls(self, w_type): if not hasattr(self, "_interplevel_classes"): diff --git a/pypy/objspace/std/proxyobject.py b/pypy/objspace/std/proxyobject.py --- a/pypy/objspace/std/proxyobject.py +++ b/pypy/objspace/std/proxyobject.py @@ -16,6 +16,8 @@ def transparent_class(name, BaseCls): class W_Transparent(BaseCls): + ignore_for_isinstance_cache = True + def __init__(self, space, w_type, w_controller): self.w_type = w_type self.w_controller = w_controller diff --git a/pypy/objspace/std/rangeobject.py b/pypy/objspace/std/rangeobject.py --- a/pypy/objspace/std/rangeobject.py +++ b/pypy/objspace/std/rangeobject.py @@ -5,7 +5,7 @@ from pypy.objspace.std.noneobject import W_NoneObject from pypy.objspace.std.inttype import wrapint from pypy.objspace.std.sliceobject import W_SliceObject, normalize_simple_slice -from pypy.objspace.std.listobject import W_ListObject +from pypy.objspace.std.listobject import W_AbstractListObject, W_ListObject from pypy.objspace.std import listtype, iterobject, slicetype from pypy.interpreter import gateway, baseobjspace @@ -21,7 +21,7 @@ return (start - stop - step - 1)/-step -class W_RangeListObject(W_Object): +class W_RangeListObject(W_AbstractListObject): typedef = listtype.list_typedef def __init__(w_self, start, step, length): diff --git a/pypy/objspace/std/ropeobject.py b/pypy/objspace/std/ropeobject.py --- a/pypy/objspace/std/ropeobject.py +++ b/pypy/objspace/std/ropeobject.py @@ -6,7 +6,7 @@ from pypy.rlib.objectmodel import we_are_translated from pypy.objspace.std.inttype import wrapint from pypy.objspace.std.sliceobject import W_SliceObject, normalize_simple_slice -from pypy.objspace.std import slicetype +from pypy.objspace.std import stringobject, slicetype, iterobject from pypy.objspace.std.listobject import W_ListObject from pypy.objspace.std.noneobject import W_NoneObject from pypy.objspace.std.tupleobject import W_TupleObject @@ -19,7 +19,7 @@ str_format__String as str_format__Rope, _upper, _lower, DEFAULT_NOOP_TABLE) -class W_RopeObject(W_Object): +class W_RopeObject(stringobject.W_AbstractStringObject): from pypy.objspace.std.stringtype import str_typedef as typedef _immutable_fields_ = ['_node'] @@ -59,7 +59,7 @@ registerimplementation(W_RopeObject) -class W_RopeIterObject(W_Object): +class W_RopeIterObject(iterobject.W_AbstractIterObject): from pypy.objspace.std.itertype import iter_typedef as typedef def __init__(w_self, w_rope, index=0): diff --git a/pypy/objspace/std/ropeunicodeobject.py b/pypy/objspace/std/ropeunicodeobject.py --- a/pypy/objspace/std/ropeunicodeobject.py +++ b/pypy/objspace/std/ropeunicodeobject.py @@ -9,7 +9,7 @@ from pypy.objspace.std.noneobject import W_NoneObject from pypy.rlib import rope from pypy.objspace.std.sliceobject import W_SliceObject, normalize_simple_slice -from pypy.objspace.std import slicetype +from pypy.objspace.std import unicodeobject, slicetype, iterobject from pypy.objspace.std.tupleobject import W_TupleObject from pypy.rlib.rarithmetic import intmask, ovfcheck from pypy.module.unicodedata import unicodedb @@ -76,7 +76,7 @@ return encode_object(space, w_unistr, encoding, errors) -class W_RopeUnicodeObject(W_Object): +class W_RopeUnicodeObject(unicodeobject.W_AbstractUnicodeObject): from pypy.objspace.std.unicodetype import unicode_typedef as typedef _immutable_fields_ = ['_node'] @@ -117,7 +117,7 @@ return rope.LiteralUnicodeNode(space.unicode_w(w_str)) -class W_RopeUnicodeIterObject(W_Object): +class W_RopeUnicodeIterObject(iterobject.W_AbstractIterObject): from pypy.objspace.std.itertype import iter_typedef as typedef def __init__(w_self, w_rope, index=0): diff --git a/pypy/objspace/std/smallintobject.py b/pypy/objspace/std/smallintobject.py --- a/pypy/objspace/std/smallintobject.py +++ b/pypy/objspace/std/smallintobject.py @@ -6,7 +6,7 @@ from pypy.objspace.std.model import registerimplementation, W_Object from pypy.objspace.std.register_all import register_all from pypy.objspace.std.noneobject import W_NoneObject -from pypy.objspace.std.intobject import W_IntObject +from pypy.objspace.std.intobject import W_AbstractIntObject, W_IntObject from pypy.interpreter.error import OperationError from pypy.rlib.objectmodel import UnboxedValue from pypy.rlib.rbigint import rbigint @@ -14,7 +14,7 @@ from pypy.tool.sourcetools import func_with_new_name from pypy.objspace.std.inttype import wrapint -class W_SmallIntObject(W_Object, UnboxedValue): +class W_SmallIntObject(W_AbstractIntObject, UnboxedValue): __slots__ = 'intval' from pypy.objspace.std.inttype import int_typedef as typedef diff --git a/pypy/objspace/std/smalllongobject.py b/pypy/objspace/std/smalllongobject.py --- a/pypy/objspace/std/smalllongobject.py +++ b/pypy/objspace/std/smalllongobject.py @@ -9,7 +9,7 @@ from pypy.rlib.rarithmetic import r_longlong, r_int, r_uint from pypy.rlib.rarithmetic import intmask, LONGLONG_BIT from pypy.rlib.rbigint import rbigint -from pypy.objspace.std.longobject import W_LongObject +from pypy.objspace.std.longobject import W_AbstractLongObject, W_LongObject from pypy.objspace.std.intobject import W_IntObject from pypy.objspace.std.noneobject import W_NoneObject from pypy.interpreter.error import OperationError @@ -17,7 +17,7 @@ LONGLONG_MIN = r_longlong((-1) << (LONGLONG_BIT-1)) -class W_SmallLongObject(W_Object): +class W_SmallLongObject(W_AbstractLongObject): from pypy.objspace.std.longtype import long_typedef as typedef _immutable_fields_ = ['longlong'] diff --git a/pypy/objspace/std/smalltupleobject.py b/pypy/objspace/std/smalltupleobject.py --- a/pypy/objspace/std/smalltupleobject.py +++ b/pypy/objspace/std/smalltupleobject.py @@ -9,9 +9,9 @@ from pypy.interpreter import gateway from pypy.rlib.debug import make_sure_not_resized from pypy.rlib.unroll import unrolling_iterable -from pypy.objspace.std.tupleobject import W_TupleObject +from pypy.objspace.std.tupleobject import W_AbstractTupleObject, W_TupleObject -class W_SmallTupleObject(W_Object): +class W_SmallTupleObject(W_AbstractTupleObject): from pypy.objspace.std.tupletype import tuple_typedef as typedef def tolist(self): diff --git a/pypy/objspace/std/strbufobject.py b/pypy/objspace/std/strbufobject.py --- a/pypy/objspace/std/strbufobject.py +++ b/pypy/objspace/std/strbufobject.py @@ -1,11 +1,12 @@ from pypy.objspace.std.model import registerimplementation, W_Object from pypy.objspace.std.register_all import register_all +from pypy.objspace.std.stringobject import W_AbstractStringObject from pypy.objspace.std.stringobject import W_StringObject from pypy.objspace.std.unicodeobject import delegate_String2Unicode from pypy.rlib.rstring import StringBuilder from pypy.interpreter.buffer import Buffer -class W_StringBufferObject(W_Object): +class W_StringBufferObject(W_AbstractStringObject): from pypy.objspace.std.stringtype import str_typedef as typedef w_str = None diff --git a/pypy/objspace/std/stringobject.py b/pypy/objspace/std/stringobject.py --- a/pypy/objspace/std/stringobject.py +++ b/pypy/objspace/std/stringobject.py @@ -19,7 +19,10 @@ from pypy.objspace.std.formatting import mod_format -class W_StringObject(W_Object): +class W_AbstractStringObject(W_Object): + pass + +class W_StringObject(W_AbstractStringObject): from pypy.objspace.std.stringtype import str_typedef as typedef _immutable_fields_ = ['_value'] diff --git a/pypy/objspace/std/strjoinobject.py b/pypy/objspace/std/strjoinobject.py --- a/pypy/objspace/std/strjoinobject.py +++ b/pypy/objspace/std/strjoinobject.py @@ -1,11 +1,12 @@ from pypy.objspace.std.model import registerimplementation, W_Object from pypy.objspace.std.register_all import register_all +from pypy.objspace.std.stringobject import W_AbstractStringObject from pypy.objspace.std.stringobject import W_StringObject from pypy.objspace.std.unicodeobject import delegate_String2Unicode from pypy.objspace.std.stringtype import wrapstr -class W_StringJoinObject(W_Object): +class W_StringJoinObject(W_AbstractStringObject): from pypy.objspace.std.stringtype import str_typedef as typedef def __init__(w_self, joined_strs, until=-1): diff --git a/pypy/objspace/std/strsliceobject.py b/pypy/objspace/std/strsliceobject.py --- a/pypy/objspace/std/strsliceobject.py +++ b/pypy/objspace/std/strsliceobject.py @@ -1,6 +1,7 @@ from pypy.interpreter.error import OperationError from pypy.objspace.std.model import registerimplementation, W_Object from pypy.objspace.std.register_all import register_all +from pypy.objspace.std.stringobject import W_AbstractStringObject from pypy.objspace.std.stringobject import W_StringObject from pypy.objspace.std.unicodeobject import delegate_String2Unicode from pypy.objspace.std.sliceobject import W_SliceObject, normalize_simple_slice @@ -12,7 +13,7 @@ stringendswith, stringstartswith -class W_StringSliceObject(W_Object): +class W_StringSliceObject(W_AbstractStringObject): from pypy.objspace.std.stringtype import str_typedef as typedef def __init__(w_self, str, start, stop): diff --git a/pypy/objspace/std/test/test_stdobjspace.py b/pypy/objspace/std/test/test_stdobjspace.py --- a/pypy/objspace/std/test/test_stdobjspace.py +++ b/pypy/objspace/std/test/test_stdobjspace.py @@ -50,6 +50,8 @@ def test_fastpath_isinstance(self): from pypy.objspace.std.stringobject import W_StringObject from pypy.objspace.std.intobject import W_IntObject + from pypy.objspace.std.iterobject import W_AbstractSeqIterObject + from pypy.objspace.std.iterobject import W_SeqIterObject space = self.space assert space._get_interplevel_cls(space.w_str) is W_StringObject @@ -62,9 +64,13 @@ assert space.isinstance_w(X(), space.w_str) + w_sequenceiterator = space.gettypefor(W_SeqIterObject) + cls = space._get_interplevel_cls(w_sequenceiterator) + assert cls is W_AbstractSeqIterObject + def test_withstrbuf_fastpath_isinstance(self): - from pypy.objspace.std.stringobject import W_StringObject + from pypy.objspace.std.stringobject import W_AbstractStringObject - space = gettestobjspace(withstrbuf=True) - assert space._get_interplevel_cls(space.w_str) is W_StringObject - + space = gettestobjspace(withstrbuf=True) + cls = space._get_interplevel_cls(space.w_str) + assert cls is W_AbstractStringObject diff --git a/pypy/objspace/std/tupleobject.py b/pypy/objspace/std/tupleobject.py --- a/pypy/objspace/std/tupleobject.py +++ b/pypy/objspace/std/tupleobject.py @@ -9,7 +9,10 @@ from pypy.interpreter import gateway from pypy.rlib.debug import make_sure_not_resized -class W_TupleObject(W_Object): +class W_AbstractTupleObject(W_Object): + pass + +class W_TupleObject(W_AbstractTupleObject): from pypy.objspace.std.tupletype import tuple_typedef as typedef _immutable_fields_ = ['wrappeditems[*]'] diff --git a/pypy/objspace/std/unicodeobject.py b/pypy/objspace/std/unicodeobject.py --- a/pypy/objspace/std/unicodeobject.py +++ b/pypy/objspace/std/unicodeobject.py @@ -19,7 +19,10 @@ from pypy.objspace.std.formatting import mod_format from pypy.objspace.std.stringtype import stringstartswith, stringendswith -class W_UnicodeObject(W_Object): +class W_AbstractUnicodeObject(W_Object): + pass + +class W_UnicodeObject(W_AbstractUnicodeObject): from pypy.objspace.std.unicodetype import unicode_typedef as typedef _immutable_fields_ = ['_value'] diff --git a/pypy/rlib/clibffi.py b/pypy/rlib/clibffi.py --- a/pypy/rlib/clibffi.py +++ b/pypy/rlib/clibffi.py @@ -30,6 +30,9 @@ _MAC_OS = platform.name == "darwin" _FREEBSD_7 = platform.name == "freebsd7" +_LITTLE_ENDIAN = sys.byteorder == 'little' +_BIG_ENDIAN = sys.byteorder == 'big' + if _WIN32: from pypy.rlib import rwin32 @@ -338,15 +341,38 @@ cast_type_to_ffitype._annspecialcase_ = 'specialize:memo' def push_arg_as_ffiptr(ffitp, arg, ll_buf): - # this is for primitive types. For structures and arrays - # would be something different (more dynamic) + # This is for primitive types. Note that the exact type of 'arg' may be + # different from the expected 'c_size'. To cope with that, we fall back + # to a byte-by-byte copy. TP = lltype.typeOf(arg) TP_P = lltype.Ptr(rffi.CArray(TP)) - buf = rffi.cast(TP_P, ll_buf) - buf[0] = arg + TP_size = rffi.sizeof(TP) + c_size = intmask(ffitp.c_size) + # if both types have the same size, we can directly write the + # value to the buffer + if c_size == TP_size: + buf = rffi.cast(TP_P, ll_buf) + buf[0] = arg + else: + # needs byte-by-byte copying. Make sure 'arg' is an integer type. + # Note that this won't work for rffi.FLOAT/rffi.DOUBLE. + assert TP is not rffi.FLOAT and TP is not rffi.DOUBLE + if TP_size <= rffi.sizeof(lltype.Signed): + arg = rffi.cast(lltype.Unsigned, arg) + else: + arg = rffi.cast(lltype.UnsignedLongLong, arg) + if _LITTLE_ENDIAN: + for i in range(c_size): + ll_buf[i] = chr(arg & 0xFF) + arg >>= 8 + elif _BIG_ENDIAN: + for i in range(c_size-1, -1, -1): + ll_buf[i] = chr(arg & 0xFF) + arg >>= 8 + else: + raise AssertionError push_arg_as_ffiptr._annspecialcase_ = 'specialize:argtype(1)' - # type defs for callback and closure userdata USERDATA_P = lltype.Ptr(lltype.ForwardReference()) CALLBACK_TP = lltype.Ptr(lltype.FuncType([rffi.VOIDPP, rffi.VOIDP, USERDATA_P], diff --git a/pypy/rlib/libffi.py b/pypy/rlib/libffi.py --- a/pypy/rlib/libffi.py +++ b/pypy/rlib/libffi.py @@ -234,7 +234,7 @@ # It is important that there is no other operation in the middle, else # the optimizer will fail to recognize the pattern and won't turn it # into a fast CALL. Note that "arg = arg.next" is optimized away, - # assuming that archain is completely virtual. + # assuming that argchain is completely virtual. self = jit.promote(self) if argchain.numargs != len(self.argtypes): raise TypeError, 'Wrong number of arguments: %d expected, got %d' %\ diff --git a/pypy/rlib/test/test_libffi.py b/pypy/rlib/test/test_libffi.py --- a/pypy/rlib/test/test_libffi.py +++ b/pypy/rlib/test/test_libffi.py @@ -179,6 +179,17 @@ res = self.call(func, [chr(20), 22], rffi.LONG) assert res == 42 + def test_char_args(self): + """ + char sum_args(char a, char b) { + return a + b; + } + """ + libfoo = self.get_libfoo() + func = (libfoo, 'sum_args', [types.schar, types.schar], types.schar) + res = self.call(func, [123, 43], rffi.CHAR) + assert res == chr(166) + def test_unsigned_short_args(self): """ unsigned short sum_xy_us(unsigned short x, unsigned short y) diff --git a/pypy/rpython/lltypesystem/ll2ctypes.py b/pypy/rpython/lltypesystem/ll2ctypes.py --- a/pypy/rpython/lltypesystem/ll2ctypes.py +++ b/pypy/rpython/lltypesystem/ll2ctypes.py @@ -1178,10 +1178,14 @@ value = value.adr if isinstance(value, llmemory.fakeaddress): value = value.ptr or 0 + if isinstance(value, r_singlefloat): + value = float(value) TYPE1 = lltype.typeOf(value) cvalue = lltype2ctypes(value) cresulttype = get_ctypes_type(RESTYPE) - if isinstance(TYPE1, lltype.Ptr): + if RESTYPE == TYPE1: + return value + elif isinstance(TYPE1, lltype.Ptr): if isinstance(RESTYPE, lltype.Ptr): # shortcut: ptr->ptr cast cptr = ctypes.cast(cvalue, cresulttype) diff --git a/pypy/rpython/lltypesystem/rffi.py b/pypy/rpython/lltypesystem/rffi.py --- a/pypy/rpython/lltypesystem/rffi.py +++ b/pypy/rpython/lltypesystem/rffi.py @@ -126,6 +126,7 @@ canraise=False, random_effects_on_gcobjs= random_effects_on_gcobjs, + calling_conv=calling_conv, **kwds) if isinstance(_callable, ll2ctypes.LL2CtypesCallable): _callable.funcptr = funcptr @@ -865,11 +866,12 @@ try: unsigned = not tp._type.SIGNED except AttributeError: - if tp in [lltype.Char, lltype.Float, lltype.Signed] or\ - isinstance(tp, lltype.Ptr): + if (not isinstance(tp, lltype.Primitive) or + tp in (FLOAT, DOUBLE) or + cast(lltype.SignedLongLong, cast(tp, -1)) < 0): unsigned = False else: - unsigned = False + unsigned = True return size, unsigned def sizeof(tp): diff --git a/pypy/rpython/lltypesystem/test/test_rffi.py b/pypy/rpython/lltypesystem/test/test_rffi.py --- a/pypy/rpython/lltypesystem/test/test_rffi.py +++ b/pypy/rpython/lltypesystem/test/test_rffi.py @@ -18,6 +18,7 @@ from pypy.conftest import option from pypy.objspace.flow.model import summary from pypy.translator.tool.cbuild import ExternalCompilationInfo +from pypy.rlib.rarithmetic import r_singlefloat class BaseTestRffi: def test_basic(self): @@ -704,6 +705,14 @@ res = cast(lltype.Signed, 42.5) assert res == 42 + res = cast(lltype.SingleFloat, 12.3) + assert res == r_singlefloat(12.3) + res = cast(lltype.SingleFloat, res) + assert res == r_singlefloat(12.3) + + res = cast(lltype.Float, r_singlefloat(12.)) + assert res == 12. + def test_rffi_sizeof(self): try: import ctypes @@ -733,7 +742,7 @@ assert sizeof(ll) == ctypes.sizeof(ctp) assert sizeof(lltype.Typedef(ll, 'test')) == sizeof(ll) assert not size_and_sign(lltype.Signed)[1] - assert not size_and_sign(lltype.Char)[1] + assert size_and_sign(lltype.Char) == (1, True) assert not size_and_sign(lltype.UniChar)[1] assert size_and_sign(UINT)[1] diff --git a/pypy/rpython/module/ll_os.py b/pypy/rpython/module/ll_os.py --- a/pypy/rpython/module/ll_os.py +++ b/pypy/rpython/module/ll_os.py @@ -356,6 +356,32 @@ return extdef([int, str, [str]], int, llimpl=spawnv_llimpl, export_name="ll_os.ll_os_spawnv") + @registering_if(os, 'spawnve') + def register_os_spawnve(self): + os_spawnve = self.llexternal('spawnve', + [rffi.INT, rffi.CCHARP, rffi.CCHARPP, + rffi.CCHARPP], + rffi.INT) + + def spawnve_llimpl(mode, path, args, env): + envstrs = [] + for item in env.iteritems(): + envstrs.append("%s=%s" % item) + + mode = rffi.cast(rffi.INT, mode) + l_args = rffi.liststr2charpp(args) + l_env = rffi.liststr2charpp(envstrs) + childpid = os_spawnve(mode, path, l_args, l_env) + rffi.free_charpp(l_env) + rffi.free_charpp(l_args) + if childpid == -1: + raise OSError(rposix.get_errno(), "os_spawnve failed") + return rffi.cast(lltype.Signed, childpid) + + return extdef([int, str, [str], {str: str}], int, + llimpl=spawnve_llimpl, + export_name="ll_os.ll_os_spawnve") + @registering(os.dup) def register_os_dup(self): os_dup = self.llexternal(underscore_on_windows+'dup', [rffi.INT], rffi.INT) diff --git a/pypy/translator/c/test/test_extfunc.py b/pypy/translator/c/test/test_extfunc.py --- a/pypy/translator/c/test/test_extfunc.py +++ b/pypy/translator/c/test/test_extfunc.py @@ -818,6 +818,24 @@ func() assert open(filename).read() == "2" +if hasattr(posix, 'spawnve'): + def test_spawnve(): + filename = str(udir.join('test_spawnve.txt')) + progname = str(sys.executable) + scriptpath = udir.join('test_spawnve.py') + scriptpath.write('import os\n' + + 'f=open(%r,"w")\n' % filename + + 'f.write(os.environ["FOOBAR"])\n' + + 'f.close\n') + scriptname = str(scriptpath) + def does_stuff(): + l = [progname, scriptname] + pid = os.spawnve(os.P_NOWAIT, progname, l, {'FOOBAR': '42'}) + os.waitpid(pid, 0) + func = compile(does_stuff, []) + func() + assert open(filename).read() == "42" + def test_utime(): path = str(udir.ensure("test_utime.txt")) from time import time, sleep diff --git a/pypy/translator/test/test_simplify.py b/pypy/translator/test/test_simplify.py --- a/pypy/translator/test/test_simplify.py +++ b/pypy/translator/test/test_simplify.py @@ -42,24 +42,6 @@ assert graph.startblock.operations[0].opname == 'int_mul_ovf' assert graph.startblock.operations[1].opname == 'int_sub' -def test_remove_ovfcheck_lshift(): - # check that ovfcheck_lshift() is handled - from pypy.rlib.rarithmetic import ovfcheck_lshift - def f(x): - try: - return ovfcheck_lshift(x, 2) - except OverflowError: - return -42 - graph, _ = translate(f, [int]) - assert len(graph.startblock.operations) == 1 - assert graph.startblock.operations[0].opname == 'int_lshift_ovf' - assert len(graph.startblock.operations[0].args) == 2 - assert len(graph.startblock.exits) == 2 - assert [link.exitcase for link in graph.startblock.exits] == \ - [None, OverflowError] - assert [link.target.operations for link in graph.startblock.exits] == \ - [(), ()] - def test_remove_ovfcheck_floordiv(): # check that ovfcheck() is handled even if the operation raises # and catches another exception too, here ZeroDivisionError _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit