Author: Valentina Mukhamedzhanova <umi...@gmail.com> Branch: py3.3 Changeset: r72505:4bba41190d41 Date: 2014-07-26 14:48 +0200 http://bitbucket.org/pypy/pypy/changeset/4bba41190d41/
Log: Merge heads. diff --git a/lib-python/3/json/__init__.py b/lib-python/3/json/__init__.py --- a/lib-python/3/json/__init__.py +++ b/lib-python/3/json/__init__.py @@ -104,6 +104,12 @@ __author__ = 'Bob Ippolito <b...@redivi.com>' +try: + # PyPy speedup, the interface is different than CPython's _json + import _pypyjson +except ImportError: + _pypyjson = None + from .decoder import JSONDecoder from .encoder import JSONEncoder @@ -313,7 +319,7 @@ if (cls is None and object_hook is None and parse_int is None and parse_float is None and parse_constant is None and object_pairs_hook is None and not kw): - return _default_decoder.decode(s) + return _pypyjson.loads(s) if _pypyjson else _default_decoder.decode(s) if cls is None: cls = JSONDecoder if object_hook is not None: diff --git a/lib-python/3/test/test_csv.py b/lib-python/3/test/test_csv.py --- a/lib-python/3/test/test_csv.py +++ b/lib-python/3/test/test_csv.py @@ -766,8 +766,9 @@ mydialect.quotechar = "''" with self.assertRaises(csv.Error) as cm: mydialect() + # NOTE: Patched exception message since cpython uses bad grammar (cpython issue22076) self.assertEqual(str(cm.exception), - '"quotechar" must be an 1-character string') + '"quotechar" must be a 1-character string') mydialect.quotechar = 4 with self.assertRaises(csv.Error) as cm: @@ -789,14 +790,16 @@ mydialect.delimiter = ":::" with self.assertRaises(csv.Error) as cm: mydialect() + # NOTE: Patched exception message since cpython uses bad grammar (cpython issue22076) self.assertEqual(str(cm.exception), - '"delimiter" must be an 1-character string') + '"delimiter" must be a 1-character string') mydialect.delimiter = "" with self.assertRaises(csv.Error) as cm: mydialect() + # NOTE: Patched exception message since cpython uses bad grammar (cpython issue22076) self.assertEqual(str(cm.exception), - '"delimiter" must be an 1-character string') + '"delimiter" must be a 1-character string') mydialect.delimiter = b"," with self.assertRaises(csv.Error) as cm: diff --git a/lib-python/stdlib-version.txt b/lib-python/stdlib-version.txt --- a/lib-python/stdlib-version.txt +++ b/lib-python/stdlib-version.txt @@ -6,4 +6,4 @@ 2.7:: 3a1db0d2747e (2.7) v2.7.6 3:: - cef745775b65 (3.2) v3.2.5 + 62cf4e77f785 (3.3) v3.3.5 diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py --- a/pypy/interpreter/pyopcode.py +++ b/pypy/interpreter/pyopcode.py @@ -204,7 +204,7 @@ elif opcode == opcodedesc.BREAK_LOOP.index: next_instr = self.BREAK_LOOP(oparg, next_instr) elif opcode == opcodedesc.CONTINUE_LOOP.index: - next_instr = self.CONTINUE_LOOP(oparg, next_instr) + return self.CONTINUE_LOOP(oparg, next_instr) elif opcode == opcodedesc.FOR_ITER.index: next_instr = self.FOR_ITER(oparg, next_instr) elif opcode == opcodedesc.JUMP_FORWARD.index: @@ -1022,7 +1022,6 @@ raise w_value = space.w_None self.pushvalue(w_value) - return next_instr else: # iter remains on stack, w_retval is value to be yielded. self.pushvalue(w_retval) diff --git a/pypy/interpreter/test/test_generator.py b/pypy/interpreter/test/test_generator.py --- a/pypy/interpreter/test/test_generator.py +++ b/pypy/interpreter/test/test_generator.py @@ -307,13 +307,13 @@ w_co = space.appexec([], '''(): def g(x): yield x + 5 - return g.func_code + return g.__code__ ''') assert should_not_inline(w_co) == False w_co = space.appexec([], '''(): def g(x): yield x + 5 yield x + 6 - return g.func_code + return g.__code__ ''') assert should_not_inline(w_co) == True diff --git a/pypy/module/__builtin__/app_inspect.py b/pypy/module/__builtin__/app_inspect.py --- a/pypy/module/__builtin__/app_inspect.py +++ b/pypy/module/__builtin__/app_inspect.py @@ -53,8 +53,7 @@ if dir_meth is not None: result = dir_meth() if not isinstance(result, list): - raise TypeError("__dir__() must return a list, not %r" % ( - type(result),)) + result = list(result) # Will throw TypeError if not iterable result.sort() return result elif isinstance(obj, types.ModuleType): diff --git a/pypy/module/__builtin__/functional.py b/pypy/module/__builtin__/functional.py --- a/pypy/module/__builtin__/functional.py +++ b/pypy/module/__builtin__/functional.py @@ -482,7 +482,7 @@ def descr_hash(self, space): if space.eq_w(self.w_length, space.wrap(0)): w_tup = space.newtuple([self.w_length, space.w_None, space.w_None]) - elif space.eq_w(self.w_length, space.wrap(0)): + elif space.eq_w(self.w_length, space.wrap(1)): w_tup = space.newtuple([self.w_length, self.w_start, space.w_None]) else: w_tup = space.newtuple([self.w_length, self.w_start, self.w_step]) diff --git a/pypy/module/__builtin__/test/test_construct_singletons.py b/pypy/module/__builtin__/test/test_construct_singletons.py new file mode 100644 --- /dev/null +++ b/pypy/module/__builtin__/test/test_construct_singletons.py @@ -0,0 +1,7 @@ +class AppTestConstructSingletons: + + def test_construct_singletons(self): + none_type = type(None) + assert none_type() is None + raises(TypeError, none_type, 1, 2) + raises(TypeError, none_type, a=1, b=2) diff --git a/pypy/module/__builtin__/test/test_dir.py b/pypy/module/__builtin__/test/test_dir.py new file mode 100644 --- /dev/null +++ b/pypy/module/__builtin__/test/test_dir.py @@ -0,0 +1,26 @@ +class AppTestDir: + + def test_dir_obj__dir__tuple(self): + """If __dir__ method returns a tuple, cpython3 converts it to list.""" + class Foo(object): + def __dir__(self): + return ("b", "c", "a") + res = dir(Foo()) + assert isinstance(res, list) + assert res == ["a", "b", "c"] + + def test_dir_obj__dir__genexp(self): + """Generator expression is also converted to list by cpython3.""" + class Foo(object): + def __dir__(self): + return (i for i in ["b", "c", "a"]) + res = dir(Foo()) + assert isinstance(res, list) + assert res == ["a", "b", "c"] + + def test_dir_obj__dir__noniter(self): + """If result of __dir__ is not iterable, it's an error.""" + class Foo(object): + def __dir__(self): + return 42 + raises(TypeError, dir, Foo()) diff --git a/pypy/module/__builtin__/test/test_functional.py b/pypy/module/__builtin__/test/test_functional.py --- a/pypy/module/__builtin__/test/test_functional.py +++ b/pypy/module/__builtin__/test/test_functional.py @@ -484,7 +484,7 @@ for a in test_ranges: for b in test_ranges: if a == b: - assert (hash(a), hash(b)) + assert hash(a) == hash(b) # Ranges are unequal to other types (even sequence types) assert (range(0) == ()) is False diff --git a/pypy/module/_csv/interp_csv.py b/pypy/module/_csv/interp_csv.py --- a/pypy/module/_csv/interp_csv.py +++ b/pypy/module/_csv/interp_csv.py @@ -34,10 +34,15 @@ return default return space.int_w(w_src) -def _get_str(space, w_src, default): +def _get_str(space, w_src, default, attrname): if w_src is None: return default - return space.unicode_w(w_src) + try: + return space.unicode_w(w_src) + except OperationError as e: + if e.match(space, space.w_TypeError): + raise oefmt(space.w_TypeError, '"%s" must be a string', attrname) + raise def _get_char(space, w_src, default, name): if w_src is None: @@ -91,7 +96,7 @@ dialect.delimiter = _get_char(space, w_delimiter, u',', 'delimiter') dialect.doublequote = _get_bool(space, w_doublequote, True) dialect.escapechar = _get_char(space, w_escapechar, u'\0', 'escapechar') - dialect.lineterminator = _get_str(space, w_lineterminator, u'\r\n') + dialect.lineterminator = _get_str(space, w_lineterminator, u'\r\n', 'lineterminator') dialect.quotechar = _get_char(space, w_quotechar, u'"', 'quotechar') tmp_quoting = _get_int(space, w_quoting, QUOTE_MINIMAL) dialect.skipinitialspace = _get_bool(space, w_skipinitialspace, False) diff --git a/pypy/module/_csv/test/test_dialect.py b/pypy/module/_csv/test/test_dialect.py --- a/pypy/module/_csv/test/test_dialect.py +++ b/pypy/module/_csv/test/test_dialect.py @@ -67,6 +67,9 @@ kwargs = {name: value} raises(TypeError, _csv.register_dialect, 'foo1', **kwargs) + exc_info = raises(TypeError, _csv.register_dialect, 'foo1', lineterminator=4) + assert exc_info.value.args[0] == '"lineterminator" must be a string' + def test_bool_arg(self): # boolean arguments take *any* object and use its truth-value import _csv diff --git a/pypy/module/_io/interp_io.py b/pypy/module/_io/interp_io.py --- a/pypy/module/_io/interp_io.py +++ b/pypy/module/_io/interp_io.py @@ -4,7 +4,6 @@ from pypy.interpreter.gateway import interp2app, unwrap_spec from pypy.interpreter.typedef import ( TypeDef, interp_attrproperty, generic_new_descr) -from pypy.module.exceptions.interp_exceptions import W_IOError from pypy.module._io.interp_fileio import W_FileIO from pypy.module._io.interp_textio import W_TextIOWrapper from rpython.rtyper.module.ll_os_stat import STAT_FIELD_TYPES diff --git a/pypy/module/_pypyjson/interp_decoder.py b/pypy/module/_pypyjson/interp_decoder.py --- a/pypy/module/_pypyjson/interp_decoder.py +++ b/pypy/module/_pypyjson/interp_decoder.py @@ -56,6 +56,7 @@ self.end_ptr = lltype.malloc(rffi.CCHARPP.TO, 1, flavor='raw') self.pos = 0 self.last_type = TYPE_UNKNOWN + self.memo = {} def close(self): rffi.free_charp(self.ll_chars) @@ -261,6 +262,8 @@ w_name = self.decode_any(i) if self.last_type != TYPE_STRING: self._raise("Key name must be string for object starting at char %d", start) + w_name = self.memo.setdefault(self.space.unicode_w(w_name), w_name) + i = self.skip_whitespace(self.pos) ch = self.ll_chars[i] if ch != ':': diff --git a/pypy/module/_pypyjson/test/test__pypyjson.py b/pypy/module/_pypyjson/test/test__pypyjson.py --- a/pypy/module/_pypyjson/test/test__pypyjson.py +++ b/pypy/module/_pypyjson/test/test__pypyjson.py @@ -187,4 +187,12 @@ import _pypyjson # http://json.org/JSON_checker/test/fail25.json s = '["\ttab\tcharacter\tin\tstring\t"]' - raises(ValueError, "_pypyjson.loads(s)") \ No newline at end of file + raises(ValueError, "_pypyjson.loads(s)") + + def test_keys_reuse(self): + import _pypyjson + s = '[{"a_key": 1, "b_\xe9": 2}, {"a_key": 3, "b_\xe9": 4}]' + rval = _pypyjson.loads(s) + (a, b), (c, d) = sorted(rval[0]), sorted(rval[1]) + assert a is c + assert b is d diff --git a/pypy/module/array/interp_array.py b/pypy/module/array/interp_array.py --- a/pypy/module/array/interp_array.py +++ b/pypy/module/array/interp_array.py @@ -244,7 +244,7 @@ """ size = self.len if size == 0: - return space.wrap('') + return space.wrapbytes('') cbuf = self._charbuf_start() s = rffi.charpsize2str(cbuf, size * self.itemsize) self._charbuf_stop() diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py --- a/pypy/module/cpyext/api.py +++ b/pypy/module/cpyext/api.py @@ -454,6 +454,10 @@ # PyExc_NameError, PyExc_MemoryError, PyExc_RuntimeError, # PyExc_UnicodeEncodeError, PyExc_UnicodeDecodeError, ... for exc_name in exceptions.Module.interpleveldefs.keys(): + if exc_name in ('EnvironmentError', 'IOError'): + # FIXME: aliases of OSError cause a clash of names via + # export_struct + continue GLOBALS['PyExc_' + exc_name] = ( 'PyTypeObject*', 'space.gettypeobject(interp_exceptions.W_%s.typedef)'% (exc_name, )) diff --git a/pypy/module/cpyext/include/patchlevel.h b/pypy/module/cpyext/include/patchlevel.h --- a/pypy/module/cpyext/include/patchlevel.h +++ b/pypy/module/cpyext/include/patchlevel.h @@ -20,13 +20,13 @@ /* Version parsed out into numeric values */ #define PY_MAJOR_VERSION 3 -#define PY_MINOR_VERSION 2 +#define PY_MINOR_VERSION 3 #define PY_MICRO_VERSION 5 #define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_FINAL #define PY_RELEASE_SERIAL 0 /* Version as a string */ -#define PY_VERSION "3.2.5" +#define PY_VERSION "3.3.5" /* PyPy version as a string */ #define PYPY_VERSION "2.4.0-alpha0" diff --git a/pypy/module/cpyext/test/test_exception.py b/pypy/module/cpyext/test/test_exception.py --- a/pypy/module/cpyext/test/test_exception.py +++ b/pypy/module/cpyext/test/test_exception.py @@ -1,4 +1,5 @@ from pypy.module.cpyext.test.test_api import BaseApiTest +from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase from pypy.module.cpyext.pyobject import make_ref class TestExceptions(BaseApiTest): @@ -27,3 +28,16 @@ api.PyException_SetCause(w_exc, make_ref(space, w_cause)) assert space.is_w(api.PyException_GetCause(w_exc), w_cause) + +class AppTestExceptions(AppTestCpythonExtensionBase): + + def test_OSError_aliases(self): + module = self.import_extension('foo', [ + ("get_aliases", "METH_NOARGS", + """ + return PyTuple_Pack(2, + PyExc_EnvironmentError, + PyExc_IOError); + """), + ]) + assert module.get_aliases() == (OSError, OSError) diff --git a/pypy/module/exceptions/__init__.py b/pypy/module/exceptions/__init__.py --- a/pypy/module/exceptions/__init__.py +++ b/pypy/module/exceptions/__init__.py @@ -21,14 +21,14 @@ 'ConnectionResetError': 'interp_exceptions.W_ConnectionResetError', 'DeprecationWarning' : 'interp_exceptions.W_DeprecationWarning', 'EOFError' : 'interp_exceptions.W_EOFError', - 'EnvironmentError' : 'interp_exceptions.W_EnvironmentError', + 'EnvironmentError' : 'interp_exceptions.W_OSError', 'Exception' : 'interp_exceptions.W_Exception', 'FileExistsError': 'interp_exceptions.W_FileExistsError', 'FileNotFoundError': 'interp_exceptions.W_FileNotFoundError', 'FloatingPointError' : 'interp_exceptions.W_FloatingPointError', 'FutureWarning' : 'interp_exceptions.W_FutureWarning', 'GeneratorExit' : 'interp_exceptions.W_GeneratorExit', - 'IOError' : 'interp_exceptions.W_IOError', + 'IOError' : 'interp_exceptions.W_OSError', 'ImportError' : 'interp_exceptions.W_ImportError', 'ImportWarning' : 'interp_exceptions.W_ImportWarning', 'IndentationError' : 'interp_exceptions.W_IndentationError', diff --git a/pypy/module/exceptions/interp_exceptions.py b/pypy/module/exceptions/interp_exceptions.py --- a/pypy/module/exceptions/interp_exceptions.py +++ b/pypy/module/exceptions/interp_exceptions.py @@ -497,9 +497,6 @@ filename = readwrite_attrproperty_w('w_filename', W_OSError), ) -W_EnvironmentError = W_OSError -W_IOError = W_OSError - class W_WindowsError(W_OSError): """MS-Windows OS system call failed.""" diff --git a/pypy/module/math/__init__.py b/pypy/module/math/__init__.py --- a/pypy/module/math/__init__.py +++ b/pypy/module/math/__init__.py @@ -23,6 +23,7 @@ 'frexp' : 'interp_math.frexp', 'degrees' : 'interp_math.degrees', 'log' : 'interp_math.log', + 'log2' : 'interp_math.log2', 'log10' : 'interp_math.log10', 'fmod' : 'interp_math.fmod', 'atan' : 'interp_math.atan', diff --git a/pypy/module/math/interp_math.py b/pypy/module/math/interp_math.py --- a/pypy/module/math/interp_math.py +++ b/pypy/module/math/interp_math.py @@ -228,6 +228,11 @@ return math1(space, math.log, w_base) return _log_any(space, w_x, base) +def log2(space, w_x): + """log2(x) -> the base 2 logarithm of x. + """ + return _log_any(space, w_x, 2.0) + def log10(space, w_x): """log10(x) -> the base 10 logarithm of x. """ diff --git a/pypy/module/math/test/test_math.py b/pypy/module/math/test/test_math.py --- a/pypy/module/math/test/test_math.py +++ b/pypy/module/math/test/test_math.py @@ -148,6 +148,19 @@ raises(ValueError, math.log1p, -1) raises(ValueError, math.log1p, -100) + def test_log2(self): + import math + self.ftest(math.log2(0.125), -3) + self.ftest(math.log2(0.5), -1) + self.ftest(math.log2(4), 2) + + def test_log10(self): + import math + self.ftest(math.log10(0.1), -1) + self.ftest(math.log10(10), 1) + self.ftest(math.log10(100), 2) + self.ftest(math.log10(0.01), -2) + def test_acosh(self): import math self.ftest(math.acosh(1), 0) 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 @@ -1,5 +1,6 @@ from pypy.interpreter.mixedmodule import MixedModule from rpython.rtyper.module.ll_os import RegisterOs +from rpython.rlib import rdynload import os exec 'import %s as posix' % os.name @@ -173,6 +174,12 @@ if hasattr(os, name): interpleveldefs[name] = 'interp_posix.' + name + for _name in ["RTLD_LAZY", "RTLD_NOW", "RTLD_GLOBAL", "RTLD_LOCAL", + "RTLD_NODELETE", "RTLD_NOLOAD", "RTLD_DEEPBIND"]: + if getattr(rdynload.cConfig, _name) is not None: + interpleveldefs[_name] = 'space.wrap(%d)' % ( + getattr(rdynload.cConfig, _name),) + # os.py uses this list to build os.supports_dir_fd() and os.supports_fd(). # Fill with e.g. HAVE_FCHDIR, when os.chdir() supports file descriptors. interpleveldefs['_have_functions'] = 'space.newlist([])' 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 @@ -488,8 +488,7 @@ cur = os.getlogin() except OSError, e: raise wrap_oserror(space, e) - else: - return space.wrap(cur) + return space.fsdecode(space.wrapbytes(cur)) # ____________________________________________________________ @@ -702,14 +701,21 @@ except OSError, e: raise wrap_oserror(space, e) -@unwrap_spec(path='fsencode') -def readlink(space, path): +def readlink(space, w_path): "Return a string representing the path to which the symbolic link points." + is_unicode = space.isinstance_w(w_path, space.w_unicode) + if is_unicode: + path = space.fsencode_w(w_path) + else: + path = space.bytes0_w(w_path) try: result = os.readlink(path) except OSError, e: - raise wrap_oserror(space, e, path) - return space.wrap(result) + raise wrap_oserror2(space, e, w_path) + w_result = space.wrapbytes(result) + if is_unicode: + return space.fsdecode(w_result) + return w_result before_fork_hooks = [] after_fork_child_hooks = [] @@ -899,7 +905,8 @@ r = os.uname() except OSError, e: raise wrap_oserror(space, e) - l_w = [space.wrap(i) for i in [r[0], r[1], r[2], r[3], r[4]]] + l_w = [space.fsdecode(space.wrapbytes(i)) + for i in [r[0], r[1], r[2], r[3], r[4]]] w_tuple = space.newtuple(l_w) w_uname_result = space.getattr(space.getbuiltinmodule(os.name), space.wrap('uname_result')) @@ -1229,7 +1236,7 @@ @unwrap_spec(fd=c_int) def ttyname(space, fd): try: - return space.wrap(os.ttyname(fd)) + return space.fsdecode(space.wrapbytes(os.ttyname(fd))) except OSError, e: raise wrap_oserror(space, e) @@ -1364,7 +1371,7 @@ Return the name of the controlling terminal for this process. """ - return space.wrap(os.ctermid()) + return space.fsdecode(space.wrapbytes(os.ctermid())) @unwrap_spec(fd=c_int) def device_encoding(space, fd): 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 @@ -17,7 +17,7 @@ usemodules = ['binascii', 'posix', 'signal', 'struct', 'rctime'] # py3k os.open uses subprocess, requiring the following per platform if os.name != 'nt': - usemodules += ['fcntl', 'select'] + usemodules += ['fcntl', 'select', '_posixsubprocess'] else: usemodules += ['_rawffi', 'thread'] mod.space = gettestobjspace(usemodules=usemodules) @@ -1042,6 +1042,12 @@ # just ensure it returns something reasonable assert encoding is None or type(encoding) is str + def test_rtld_constants(self): + # check presence of major RTLD_* constants + self.posix.RTLD_LAZY + self.posix.RTLD_NOW + self.posix.RTLD_GLOBAL + self.posix.RTLD_LOCAL class AppTestEnvironment(object): def setup_class(cls): diff --git a/pypy/module/sys/version.py b/pypy/module/sys/version.py --- a/pypy/module/sys/version.py +++ b/pypy/module/sys/version.py @@ -6,7 +6,7 @@ from pypy.interpreter import gateway #XXX # the release serial 42 is not in range(16) -CPYTHON_VERSION = (3, 2, 5, "final", 0) +CPYTHON_VERSION = (3, 3, 5, "final", 0) #XXX # sync CPYTHON_VERSION with patchlevel.h, package.py CPYTHON_API_VERSION = 1013 #XXX # sync with include/modsupport.h diff --git a/pypy/objspace/std/nonetype.py b/pypy/objspace/std/nonetype.py --- a/pypy/objspace/std/nonetype.py +++ b/pypy/objspace/std/nonetype.py @@ -1,8 +1,15 @@ from pypy.objspace.std.stdtypedef import StdTypeDef +from pypy.interpreter import gateway +def descr__new__(space, w_type): + return space.w_None + # ____________________________________________________________ none_typedef = StdTypeDef("NoneType", + __new__ = gateway.interp2app(descr__new__) ) none_typedef.acceptable_as_base_class = False + + _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit