Author: Antonio Cuni <anto.c...@gmail.com> Branch: py3k Changeset: r52837:303252b916c9 Date: 2012-02-24 10:14 +0100 http://bitbucket.org/pypy/pypy/changeset/303252b916c9/
Log: hg merge default diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py --- a/pypy/interpreter/baseobjspace.py +++ b/pypy/interpreter/baseobjspace.py @@ -329,7 +329,7 @@ raise modname = self.str_w(w_modname) mod = self.interpclass_w(w_mod) - if isinstance(mod, Module): + if isinstance(mod, Module) and not mod.startup_called: self.timer.start("startup " + modname) mod.init(self) self.timer.stop("startup " + modname) diff --git a/pypy/interpreter/test/test_objspace.py b/pypy/interpreter/test/test_objspace.py --- a/pypy/interpreter/test/test_objspace.py +++ b/pypy/interpreter/test/test_objspace.py @@ -314,3 +314,14 @@ space.ALL_BUILTIN_MODULES.pop() del space._builtinmodule_list mods = space.get_builtinmodule_to_install() + + def test_dont_reload_builtin_mods_on_startup(self): + from pypy.tool.option import make_config, make_objspace + config = make_config(None) + space = make_objspace(config) + w_executable = space.wrap('executable') + assert space.str_w(space.getattr(space.sys, w_executable)) == 'py.py' + space.setattr(space.sys, w_executable, space.wrap('foobar')) + assert space.str_w(space.getattr(space.sys, w_executable)) == 'foobar' + space.startup() + assert space.str_w(space.getattr(space.sys, w_executable)) == 'foobar' diff --git a/pypy/interpreter/test/test_zpy.py b/pypy/interpreter/test/test_zpy.py --- a/pypy/interpreter/test/test_zpy.py +++ b/pypy/interpreter/test/test_zpy.py @@ -23,14 +23,14 @@ def test_executable(): """Ensures sys.executable points to the py.py script""" # TODO : watch out for spaces/special chars in pypypath - output = run(sys.executable, pypypath, + output = run(sys.executable, pypypath, '-S', "-c", "import sys;print(sys.executable)") assert output.splitlines()[-1] == pypypath def test_special_names(): """Test the __name__ and __file__ special global names""" cmd = "print(__name__); print('__file__' in globals())" - output = run(sys.executable, pypypath, '-c', cmd) + output = run(sys.executable, pypypath, '-S', '-c', cmd) assert output.splitlines()[-2] == '__main__' assert output.splitlines()[-1] == 'False' @@ -39,24 +39,24 @@ tmpfile.write("print(__name__); print(__file__)\n") tmpfile.close() - output = run(sys.executable, pypypath, tmpfilepath) + output = run(sys.executable, pypypath, '-S', tmpfilepath) assert output.splitlines()[-2] == '__main__' assert output.splitlines()[-1] == str(tmpfilepath) def test_argv_command(): """Some tests on argv""" # test 1 : no arguments - output = run(sys.executable, pypypath, + output = run(sys.executable, pypypath, '-S', "-c", "import sys;print(sys.argv)") assert output.splitlines()[-1] == str(['-c']) # test 2 : some arguments after - output = run(sys.executable, pypypath, + output = run(sys.executable, pypypath, '-S', "-c", "import sys;print(sys.argv)", "hello") assert output.splitlines()[-1] == str(['-c','hello']) # test 3 : additionnal pypy parameters - output = run(sys.executable, pypypath, + output = run(sys.executable, pypypath, '-S', "-O", "-c", "import sys;print(sys.argv)", "hello") assert output.splitlines()[-1] == str(['-c','hello']) @@ -71,15 +71,15 @@ tmpfile.close() # test 1 : no arguments - output = run(sys.executable, pypypath, tmpfilepath) + output = run(sys.executable, pypypath, '-S', tmpfilepath) assert output.splitlines()[-1] == str([tmpfilepath]) # test 2 : some arguments after - output = run(sys.executable, pypypath, tmpfilepath, "hello") + output = run(sys.executable, pypypath, '-S', tmpfilepath, "hello") assert output.splitlines()[-1] == str([tmpfilepath,'hello']) # test 3 : additionnal pypy parameters - output = run(sys.executable, pypypath, "-O", tmpfilepath, "hello") + output = run(sys.executable, pypypath, '-S', "-O", tmpfilepath, "hello") assert output.splitlines()[-1] == str([tmpfilepath,'hello']) diff --git a/pypy/jit/backend/x86/test/test_ztranslation.py b/pypy/jit/backend/x86/test/test_ztranslation.py --- a/pypy/jit/backend/x86/test/test_ztranslation.py +++ b/pypy/jit/backend/x86/test/test_ztranslation.py @@ -52,6 +52,7 @@ set_param(jitdriver, "trace_eagerness", 2) total = 0 frame = Frame(i) + j = float(j) while frame.i > 3: jitdriver.can_enter_jit(frame=frame, total=total, j=j) jitdriver.jit_merge_point(frame=frame, total=total, j=j) diff --git a/pypy/jit/metainterp/test/test_ajit.py b/pypy/jit/metainterp/test/test_ajit.py --- a/pypy/jit/metainterp/test/test_ajit.py +++ b/pypy/jit/metainterp/test/test_ajit.py @@ -2943,11 +2943,18 @@ self.check_resops(arraylen_gc=3) def test_ulonglong_mod(self): - myjitdriver = JitDriver(greens = [], reds = ['n', 'sa', 'i']) + myjitdriver = JitDriver(greens = [], reds = ['n', 'a']) + class A: + pass def f(n): sa = i = rffi.cast(rffi.ULONGLONG, 1) + a = A() while i < rffi.cast(rffi.ULONGLONG, n): - myjitdriver.jit_merge_point(sa=sa, n=n, i=i) + a.sa = sa + a.i = i + myjitdriver.jit_merge_point(n=n, a=a) + sa = a.sa + i = a.i sa += sa % i i += 1 res = self.meta_interp(f, [32]) diff --git a/pypy/jit/tl/tinyframe/tinyframe.py b/pypy/jit/tl/tinyframe/tinyframe.py --- a/pypy/jit/tl/tinyframe/tinyframe.py +++ b/pypy/jit/tl/tinyframe/tinyframe.py @@ -210,7 +210,7 @@ def repr(self): return "<function %s(%s)>" % (self.outer.repr(), self.inner.repr()) -driver = JitDriver(greens = ['code', 'i'], reds = ['self'], +driver = JitDriver(greens = ['i', 'code'], reds = ['self'], virtualizables = ['self']) class Frame(object): diff --git a/pypy/module/_io/interp_iobase.py b/pypy/module/_io/interp_iobase.py --- a/pypy/module/_io/interp_iobase.py +++ b/pypy/module/_io/interp_iobase.py @@ -327,7 +327,12 @@ def autoflush(self, space): w_iobase = self.w_iobase_ref() if w_iobase is not None: - space.call_method(w_iobase, 'flush') # XXX: ignore IOErrors? + try: + space.call_method(w_iobase, 'flush') + except OperationError, e: + # if it's an IOError, ignore it + if not e.match(space, space.w_IOError): + raise class AutoFlusher(object): diff --git a/pypy/module/_io/test/test_fileio.py b/pypy/module/_io/test/test_fileio.py --- a/pypy/module/_io/test/test_fileio.py +++ b/pypy/module/_io/test/test_fileio.py @@ -177,3 +177,20 @@ """) space.finish() assert tmpfile.read() == '42' + +def test_flush_at_exit_IOError(): + from pypy import conftest + from pypy.tool.option import make_config, make_objspace + + config = make_config(conftest.option) + space = make_objspace(config) + space.appexec([], """(): + import io + class MyStream(io.IOBase): + def flush(self): + raise IOError + + s = MyStream() + import sys; sys._keepalivesomewhereobscure = s + """) + space.finish() # the IOError has been ignored 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 @@ -384,6 +384,7 @@ "Tuple": "space.w_tuple", "List": "space.w_list", "Set": "space.w_set", + "FrozenSet": "space.w_frozenset", "Int": "space.w_int", "Bool": "space.w_bool", "Float": "space.w_float", diff --git a/pypy/module/cpyext/eval.py b/pypy/module/cpyext/eval.py --- a/pypy/module/cpyext/eval.py +++ b/pypy/module/cpyext/eval.py @@ -1,16 +1,24 @@ from pypy.interpreter.error import OperationError +from pypy.interpreter.astcompiler import consts from pypy.rpython.lltypesystem import rffi, lltype from pypy.module.cpyext.api import ( cpython_api, CANNOT_FAIL, CONST_STRING, FILEP, fread, feof, Py_ssize_tP, cpython_struct) from pypy.module.cpyext.pyobject import PyObject, borrow_from from pypy.module.cpyext.pyerrors import PyErr_SetFromErrno +from pypy.module.cpyext.funcobject import PyCodeObject from pypy.module.__builtin__ import compiling PyCompilerFlags = cpython_struct( - "PyCompilerFlags", ()) + "PyCompilerFlags", (("cf_flags", rffi.INT),)) PyCompilerFlagsPtr = lltype.Ptr(PyCompilerFlags) +PyCF_MASK = (consts.CO_FUTURE_DIVISION | + consts.CO_FUTURE_ABSOLUTE_IMPORT | + consts.CO_FUTURE_WITH_STATEMENT | + consts.CO_FUTURE_PRINT_FUNCTION | + consts.CO_FUTURE_UNICODE_LITERALS) + @cpython_api([PyObject, PyObject, PyObject], PyObject) def PyEval_CallObjectWithKeywords(space, w_obj, w_arg, w_kwds): return space.call(w_obj, w_arg, w_kwds) @@ -48,6 +56,17 @@ return None return borrow_from(None, caller.w_globals) +@cpython_api([PyCodeObject, PyObject, PyObject], PyObject) +def PyEval_EvalCode(space, w_code, w_globals, w_locals): + """This is a simplified interface to PyEval_EvalCodeEx(), with just + the code object, and the dictionaries of global and local variables. + The other arguments are set to NULL.""" + if w_globals is None: + w_globals = space.w_None + if w_locals is None: + w_locals = space.w_None + return compiling.eval(space, w_code, w_globals, w_locals) + @cpython_api([PyObject, PyObject], PyObject) def PyObject_CallObject(space, w_obj, w_arg): """ @@ -74,7 +93,7 @@ Py_file_input = 257 Py_eval_input = 258 -def compile_string(space, source, filename, start): +def compile_string(space, source, filename, start, flags=0): w_source = space.wrap(source) start = rffi.cast(lltype.Signed, start) if start == Py_file_input: @@ -86,7 +105,7 @@ else: raise OperationError(space.w_ValueError, space.wrap( "invalid mode parameter for compilation")) - return compiling.compile(space, w_source, filename, mode) + return compiling.compile(space, w_source, filename, mode, flags) def run_string(space, source, filename, start, w_globals, w_locals): w_code = compile_string(space, source, filename, start) @@ -109,6 +128,24 @@ filename = "<string>" return run_string(space, source, filename, start, w_globals, w_locals) +@cpython_api([rffi.CCHARP, rffi.INT_real, PyObject, PyObject, + PyCompilerFlagsPtr], PyObject) +def PyRun_StringFlags(space, source, start, w_globals, w_locals, flagsptr): + """Execute Python source code from str in the context specified by the + dictionaries globals and locals with the compiler flags specified by + flags. The parameter start specifies the start token that should be used to + parse the source code. + + Returns the result of executing the code as a Python object, or NULL if an + exception was raised.""" + source = rffi.charp2str(source) + if flagsptr: + flags = rffi.cast(lltype.Signed, flagsptr.c_cf_flags) + else: + flags = 0 + w_code = compile_string(space, source, "<string>", start, flags) + return compiling.eval(space, w_code, w_globals, w_locals) + @cpython_api([FILEP, CONST_STRING, rffi.INT_real, PyObject, PyObject], PyObject) def PyRun_File(space, fp, filename, start, w_globals, w_locals): """This is a simplified interface to PyRun_FileExFlags() below, leaving @@ -150,7 +187,7 @@ @cpython_api([rffi.CCHARP, rffi.CCHARP, rffi.INT_real, PyCompilerFlagsPtr], PyObject) -def Py_CompileStringFlags(space, source, filename, start, flags): +def Py_CompileStringFlags(space, source, filename, start, flagsptr): """Parse and compile the Python source code in str, returning the resulting code object. The start token is given by start; this can be used to constrain the code which can be compiled and should @@ -160,7 +197,30 @@ returns NULL if the code cannot be parsed or compiled.""" source = rffi.charp2str(source) filename = rffi.charp2str(filename) - if flags: - raise OperationError(space.w_NotImplementedError, space.wrap( - "cpyext Py_CompileStringFlags does not accept flags")) - return compile_string(space, source, filename, start) + if flagsptr: + flags = rffi.cast(lltype.Signed, flagsptr.c_cf_flags) + else: + flags = 0 + return compile_string(space, source, filename, start, flags) + +@cpython_api([PyCompilerFlagsPtr], rffi.INT_real, error=CANNOT_FAIL) +def PyEval_MergeCompilerFlags(space, cf): + """This function changes the flags of the current evaluation + frame, and returns true on success, false on failure.""" + flags = rffi.cast(lltype.Signed, cf.c_cf_flags) + result = flags != 0 + current_frame = space.getexecutioncontext().gettopframe_nohidden() + if current_frame: + codeflags = current_frame.pycode.co_flags + compilerflags = codeflags & PyCF_MASK + if compilerflags: + result = 1 + flags |= compilerflags + # No future keyword at the moment + # if codeflags & CO_GENERATOR_ALLOWED: + # result = 1 + # flags |= CO_GENERATOR_ALLOWED + cf.c_cf_flags = rffi.cast(rffi.INT, flags) + return result + + diff --git a/pypy/module/cpyext/funcobject.py b/pypy/module/cpyext/funcobject.py --- a/pypy/module/cpyext/funcobject.py +++ b/pypy/module/cpyext/funcobject.py @@ -1,6 +1,6 @@ from pypy.rpython.lltypesystem import rffi, lltype from pypy.module.cpyext.api import ( - PyObjectFields, generic_cpy_call, CONST_STRING, + PyObjectFields, generic_cpy_call, CONST_STRING, CANNOT_FAIL, cpython_api, bootstrap_function, cpython_struct, build_type_checkers) from pypy.module.cpyext.pyobject import ( PyObject, make_ref, from_ref, Py_DecRef, make_typedescr, borrow_from) @@ -48,6 +48,7 @@ PyFunction_Check, PyFunction_CheckExact = build_type_checkers("Function", Function) PyMethod_Check, PyMethod_CheckExact = build_type_checkers("Method", Method) +PyCode_Check, PyCode_CheckExact = build_type_checkers("Code", PyCode) def function_attach(space, py_obj, w_obj): py_func = rffi.cast(PyFunctionObject, py_obj) @@ -160,3 +161,9 @@ freevars=[], cellvars=[])) +@cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) +def PyCode_GetNumFree(space, w_co): + """Return the number of free variables in co.""" + co = space.interp_w(PyCode, w_co) + return len(co.co_freevars) + diff --git a/pypy/module/cpyext/include/Python.h b/pypy/module/cpyext/include/Python.h --- a/pypy/module/cpyext/include/Python.h +++ b/pypy/module/cpyext/include/Python.h @@ -113,6 +113,7 @@ #include "compile.h" #include "frameobject.h" #include "eval.h" +#include "pymath.h" #include "pymem.h" #include "pycobject.h" #include "pycapsule.h" diff --git a/pypy/module/cpyext/include/code.h b/pypy/module/cpyext/include/code.h --- a/pypy/module/cpyext/include/code.h +++ b/pypy/module/cpyext/include/code.h @@ -13,13 +13,19 @@ /* Masks for co_flags above */ /* These values are also in funcobject.py */ -#define CO_OPTIMIZED 0x0001 -#define CO_NEWLOCALS 0x0002 -#define CO_VARARGS 0x0004 -#define CO_VARKEYWORDS 0x0008 +#define CO_OPTIMIZED 0x0001 +#define CO_NEWLOCALS 0x0002 +#define CO_VARARGS 0x0004 +#define CO_VARKEYWORDS 0x0008 #define CO_NESTED 0x0010 #define CO_GENERATOR 0x0020 +#define CO_FUTURE_DIVISION 0x02000 +#define CO_FUTURE_ABSOLUTE_IMPORT 0x04000 +#define CO_FUTURE_WITH_STATEMENT 0x08000 +#define CO_FUTURE_PRINT_FUNCTION 0x10000 +#define CO_FUTURE_UNICODE_LITERALS 0x20000 + #ifdef __cplusplus } #endif diff --git a/pypy/module/cpyext/include/pymath.h b/pypy/module/cpyext/include/pymath.h new file mode 100644 --- /dev/null +++ b/pypy/module/cpyext/include/pymath.h @@ -0,0 +1,20 @@ +#ifndef Py_PYMATH_H +#define Py_PYMATH_H + +/************************************************************************** +Symbols and macros to supply platform-independent interfaces to mathematical +functions and constants +**************************************************************************/ + +/* HUGE_VAL is supposed to expand to a positive double infinity. Python + * uses Py_HUGE_VAL instead because some platforms are broken in this + * respect. We used to embed code in pyport.h to try to worm around that, + * but different platforms are broken in conflicting ways. If you're on + * a platform where HUGE_VAL is defined incorrectly, fiddle your Python + * config to #define Py_HUGE_VAL to something that works on your platform. + */ +#ifndef Py_HUGE_VAL +#define Py_HUGE_VAL HUGE_VAL +#endif + +#endif /* Py_PYMATH_H */ diff --git a/pypy/module/cpyext/include/pythonrun.h b/pypy/module/cpyext/include/pythonrun.h --- a/pypy/module/cpyext/include/pythonrun.h +++ b/pypy/module/cpyext/include/pythonrun.h @@ -19,6 +19,14 @@ int cf_flags; /* bitmask of CO_xxx flags relevant to future */ } PyCompilerFlags; +#define PyCF_MASK (CO_FUTURE_DIVISION | CO_FUTURE_ABSOLUTE_IMPORT | \ + CO_FUTURE_WITH_STATEMENT | CO_FUTURE_PRINT_FUNCTION | \ + CO_FUTURE_UNICODE_LITERALS) +#define PyCF_MASK_OBSOLETE (CO_NESTED) +#define PyCF_SOURCE_IS_UTF8 0x0100 +#define PyCF_DONT_IMPLY_DEDENT 0x0200 +#define PyCF_ONLY_AST 0x0400 + #define Py_CompileString(str, filename, start) Py_CompileStringFlags(str, filename, start, NULL) #ifdef __cplusplus diff --git a/pypy/module/cpyext/stubs.py b/pypy/module/cpyext/stubs.py --- a/pypy/module/cpyext/stubs.py +++ b/pypy/module/cpyext/stubs.py @@ -182,16 +182,6 @@ used as the positional and keyword parameters to the object's constructor.""" raise NotImplementedError -@cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) -def PyCode_Check(space, co): - """Return true if co is a code object""" - raise NotImplementedError - -@cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) -def PyCode_GetNumFree(space, co): - """Return the number of free variables in co.""" - raise NotImplementedError - @cpython_api([PyObject], rffi.INT_real, error=-1) def PyCodec_Register(space, search_function): """Register a new codec search function. @@ -1853,26 +1843,6 @@ """ raise NotImplementedError -@cpython_api([Py_UNICODE], rffi.INT_real, error=CANNOT_FAIL) -def Py_UNICODE_ISTITLE(space, ch): - """Return 1 or 0 depending on whether ch is a titlecase character.""" - raise NotImplementedError - -@cpython_api([Py_UNICODE], rffi.INT_real, error=CANNOT_FAIL) -def Py_UNICODE_ISDIGIT(space, ch): - """Return 1 or 0 depending on whether ch is a digit character.""" - raise NotImplementedError - -@cpython_api([Py_UNICODE], rffi.INT_real, error=CANNOT_FAIL) -def Py_UNICODE_ISNUMERIC(space, ch): - """Return 1 or 0 depending on whether ch is a numeric character.""" - raise NotImplementedError - -@cpython_api([Py_UNICODE], rffi.INT_real, error=CANNOT_FAIL) -def Py_UNICODE_ISALPHA(space, ch): - """Return 1 or 0 depending on whether ch is an alphabetic character.""" - raise NotImplementedError - @cpython_api([rffi.CCHARP], PyObject) def PyUnicode_FromFormat(space, format): """Take a C printf()-style format string and a variable number of @@ -2317,17 +2287,6 @@ use the default error handling.""" raise NotImplementedError -@cpython_api([PyObject, PyObject, Py_ssize_t, Py_ssize_t, rffi.INT_real], rffi.INT_real, error=-1) -def PyUnicode_Tailmatch(space, str, substr, start, end, direction): - """Return 1 if substr matches str*[*start:end] at the given tail end - (direction == -1 means to do a prefix match, direction == 1 a suffix match), - 0 otherwise. Return -1 if an error occurred. - - This function used an int type for start and end. This - might require changes in your code for properly supporting 64-bit - systems.""" - raise NotImplementedError - @cpython_api([PyObject, PyObject, Py_ssize_t, Py_ssize_t, rffi.INT_real], Py_ssize_t, error=-2) def PyUnicode_Find(space, str, substr, start, end, direction): """Return the first position of substr in str*[*start:end] using the given @@ -2524,17 +2483,6 @@ source code is read from fp instead of an in-memory string.""" raise NotImplementedError -@cpython_api([rffi.CCHARP, rffi.INT_real, PyObject, PyObject, PyCompilerFlags], PyObject) -def PyRun_StringFlags(space, str, start, globals, locals, flags): - """Execute Python source code from str in the context specified by the - dictionaries globals and locals with the compiler flags specified by - flags. The parameter start specifies the start token that should be used to - parse the source code. - - Returns the result of executing the code as a Python object, or NULL if an - exception was raised.""" - raise NotImplementedError - @cpython_api([FILE, rffi.CCHARP, rffi.INT_real, PyObject, PyObject, rffi.INT_real], PyObject) def PyRun_FileEx(space, fp, filename, start, globals, locals, closeit): """This is a simplified interface to PyRun_FileExFlags() below, leaving @@ -2555,13 +2503,6 @@ returns.""" raise NotImplementedError -@cpython_api([PyCodeObject, PyObject, PyObject], PyObject) -def PyEval_EvalCode(space, co, globals, locals): - """This is a simplified interface to PyEval_EvalCodeEx(), with just - the code object, and the dictionaries of global and local variables. - The other arguments are set to NULL.""" - raise NotImplementedError - @cpython_api([PyCodeObject, PyObject, PyObject, PyObjectP, rffi.INT_real, PyObjectP, rffi.INT_real, PyObjectP, rffi.INT_real, PyObject], PyObject) def PyEval_EvalCodeEx(space, co, globals, locals, args, argcount, kws, kwcount, defs, defcount, closure): """Evaluate a precompiled code object, given a particular environment for its @@ -2586,12 +2527,6 @@ throw() methods of generator objects.""" raise NotImplementedError -@cpython_api([PyCompilerFlags], rffi.INT_real, error=CANNOT_FAIL) -def PyEval_MergeCompilerFlags(space, cf): - """This function changes the flags of the current evaluation frame, and returns - true on success, false on failure.""" - raise NotImplementedError - @cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) def PyWeakref_Check(space, ob): """Return true if ob is either a reference or proxy object. diff --git a/pypy/module/cpyext/test/test_eval.py b/pypy/module/cpyext/test/test_eval.py --- a/pypy/module/cpyext/test/test_eval.py +++ b/pypy/module/cpyext/test/test_eval.py @@ -2,9 +2,10 @@ from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase from pypy.module.cpyext.test.test_api import BaseApiTest from pypy.module.cpyext.eval import ( - Py_single_input, Py_file_input, Py_eval_input) + Py_single_input, Py_file_input, Py_eval_input, PyCompilerFlags) from pypy.module.cpyext.api import fopen, fclose, fileno, Py_ssize_tP from pypy.interpreter.gateway import interp2app +from pypy.interpreter.astcompiler import consts from pypy.tool.udir import udir import sys, os @@ -63,6 +64,22 @@ assert space.int_w(w_res) == 10 + def test_evalcode(self, space, api): + w_f = space.appexec([], """(): + def f(*args): + assert isinstance(args, tuple) + return len(args) + 8 + return f + """) + + w_t = space.newtuple([space.wrap(1), space.wrap(2)]) + w_globals = space.newdict() + w_locals = space.newdict() + space.setitem(w_locals, space.wrap("args"), w_t) + w_res = api.PyEval_EvalCode(w_f.code, w_globals, w_locals) + + assert space.int_w(w_res) == 10 + def test_run_simple_string(self, space, api): def run(code): buf = rffi.str2charp(code) @@ -96,6 +113,16 @@ assert 42 * 43 == space.unwrap( api.PyObject_GetItem(w_globals, space.wrap("a"))) + def test_run_string_flags(self, space, api): + flags = lltype.malloc(PyCompilerFlags, flavor='raw') + flags.c_cf_flags = rffi.cast(rffi.INT, consts.PyCF_SOURCE_IS_UTF8) + w_globals = space.newdict() + api.PyRun_StringFlags("a = u'caf\xc3\xa9'", Py_single_input, + w_globals, w_globals, flags) + w_a = space.getitem(w_globals, space.wrap("a")) + assert space.unwrap(w_a) == u'caf\xe9' + lltype.free(flags, flavor='raw') + def test_run_file(self, space, api): filepath = udir / "cpyext_test_runfile.py" filepath.write("raise ZeroDivisionError") @@ -256,3 +283,21 @@ print dir(mod) print mod.__dict__ assert mod.f(42) == 47 + + def test_merge_compiler_flags(self): + module = self.import_extension('foo', [ + ("get_flags", "METH_NOARGS", + """ + PyCompilerFlags flags; + flags.cf_flags = 0; + int result = PyEval_MergeCompilerFlags(&flags); + return Py_BuildValue("ii", result, flags.cf_flags); + """), + ]) + assert module.get_flags() == (0, 0) + + ns = {'module':module} + exec """from __future__ import division \nif 1: + def nested_flags(): + return module.get_flags()""" in ns + assert ns['nested_flags']() == (1, 0x2000) # CO_FUTURE_DIVISION diff --git a/pypy/module/cpyext/test/test_funcobject.py b/pypy/module/cpyext/test/test_funcobject.py --- a/pypy/module/cpyext/test/test_funcobject.py +++ b/pypy/module/cpyext/test/test_funcobject.py @@ -78,6 +78,14 @@ rffi.free_charp(filename) rffi.free_charp(funcname) + def test_getnumfree(self, space, api): + w_function = space.appexec([], """(): + a = 5 + def method(x): return a, x + return method + """) + assert api.PyCode_GetNumFree(w_function.code) == 1 + def test_classmethod(self, space, api): w_function = space.appexec([], """(): def method(x): return x 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 @@ -239,8 +239,18 @@ assert api.Py_UNICODE_ISSPACE(unichr(char)) assert not api.Py_UNICODE_ISSPACE(u'a') + assert api.Py_UNICODE_ISALPHA(u'a') + assert not api.Py_UNICODE_ISALPHA(u'0') + assert api.Py_UNICODE_ISALNUM(u'a') + assert api.Py_UNICODE_ISALNUM(u'0') + assert not api.Py_UNICODE_ISALNUM(u'+') + assert api.Py_UNICODE_ISDECIMAL(u'\u0660') assert not api.Py_UNICODE_ISDECIMAL(u'a') + assert api.Py_UNICODE_ISDIGIT(u'9') + assert not api.Py_UNICODE_ISDIGIT(u'@') + assert api.Py_UNICODE_ISNUMERIC(u'9') + assert not api.Py_UNICODE_ISNUMERIC(u'@') for char in [0x0a, 0x0d, 0x1c, 0x1d, 0x1e, 0x85, 0x2028, 0x2029]: assert api.Py_UNICODE_ISLINEBREAK(unichr(char)) @@ -251,6 +261,9 @@ assert not api.Py_UNICODE_ISUPPER(u'a') assert not api.Py_UNICODE_ISLOWER(u'�') assert api.Py_UNICODE_ISUPPER(u'�') + assert not api.Py_UNICODE_ISTITLE(u'A') + assert api.Py_UNICODE_ISTITLE( + u'\N{LATIN CAPITAL LETTER L WITH SMALL LETTER J}') def test_TOLOWER(self, space, api): assert api.Py_UNICODE_TOLOWER(u'�') == u'�' @@ -472,3 +485,10 @@ api.PyUnicode_Replace(w_str, w_substr, w_replstr, 2)) assert u"zbzbzbzb" == space.unwrap( api.PyUnicode_Replace(w_str, w_substr, w_replstr, -1)) + + def test_tailmatch(self, space, api): + w_str = space.wrap(u"abcdef") + assert api.PyUnicode_Tailmatch(w_str, space.wrap("cde"), 2, 10, 1) == 1 + assert api.PyUnicode_Tailmatch(w_str, space.wrap("cde"), 1, 5, -1) == 1 + self.raises(space, api, TypeError, + api.PyUnicode_Tailmatch, w_str, space.wrap(3), 2, 10, 1) 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 @@ -11,7 +11,8 @@ PyObject, PyObjectP, Py_DecRef, make_ref, from_ref, track_reference, make_typedescr, get_typedescr) from pypy.module.cpyext.stringobject import PyString_Check -from pypy.objspace.std import unicodeobject, unicodetype +from pypy.module.sys.interp_encoding import setdefaultencoding +from pypy.objspace.std import unicodeobject, unicodetype, stringtype from pypy.rlib import runicode from pypy.tool.sourcetools import func_renamer import sys @@ -91,6 +92,11 @@ return unicodedb.isspace(ord(ch)) @cpython_api([Py_UNICODE], rffi.INT_real, error=CANNOT_FAIL) +def Py_UNICODE_ISALPHA(space, ch): + """Return 1 or 0 depending on whether ch is an alphabetic character.""" + return unicodedb.isalpha(ord(ch)) + +@cpython_api([Py_UNICODE], rffi.INT_real, error=CANNOT_FAIL) def Py_UNICODE_ISALNUM(space, ch): """Return 1 or 0 depending on whether ch is an alphanumeric character.""" return unicodedb.isalnum(ord(ch)) @@ -106,6 +112,16 @@ return unicodedb.isdecimal(ord(ch)) @cpython_api([Py_UNICODE], rffi.INT_real, error=CANNOT_FAIL) +def Py_UNICODE_ISDIGIT(space, ch): + """Return 1 or 0 depending on whether ch is a digit character.""" + return unicodedb.isdigit(ord(ch)) + +@cpython_api([Py_UNICODE], rffi.INT_real, error=CANNOT_FAIL) +def Py_UNICODE_ISNUMERIC(space, ch): + """Return 1 or 0 depending on whether ch is a numeric character.""" + return unicodedb.isnumeric(ord(ch)) + +@cpython_api([Py_UNICODE], rffi.INT_real, error=CANNOT_FAIL) def Py_UNICODE_ISLOWER(space, ch): """Return 1 or 0 depending on whether ch is a lowercase character.""" return unicodedb.islower(ord(ch)) @@ -115,6 +131,11 @@ """Return 1 or 0 depending on whether ch is an uppercase character.""" return unicodedb.isupper(ord(ch)) +@cpython_api([Py_UNICODE], rffi.INT_real, error=CANNOT_FAIL) +def Py_UNICODE_ISTITLE(space, ch): + """Return 1 or 0 depending on whether ch is a titlecase character.""" + return unicodedb.istitle(ord(ch)) + @cpython_api([Py_UNICODE], Py_UNICODE, error=CANNOT_FAIL) def Py_UNICODE_TOLOWER(space, ch): """Return the character ch converted to lower case.""" @@ -157,6 +178,11 @@ except KeyError: return -1.0 +@cpython_api([], Py_UNICODE, error=CANNOT_FAIL) +def PyUnicode_GetMax(space): + """Get the maximum ordinal for a Unicode character.""" + return unichr(runicode.MAXUNICODE) + @cpython_api([PyObject], rffi.CCHARP, error=CANNOT_FAIL) def PyUnicode_AS_DATA(space, ref): """Return a pointer to the internal buffer of the object. o has to be a @@ -564,3 +590,16 @@ return space.call_method(w_str, "replace", w_substr, w_replstr, space.wrap(maxcount)) +@cpython_api([PyObject, PyObject, Py_ssize_t, Py_ssize_t, rffi.INT_real], + rffi.INT_real, error=-1) +def PyUnicode_Tailmatch(space, w_str, w_substr, start, end, direction): + """Return 1 if substr matches str[start:end] at the given tail end + (direction == -1 means to do a prefix match, direction == 1 a + suffix match), 0 otherwise. Return -1 if an error occurred.""" + str = space.unicode_w(w_str) + substr = space.unicode_w(w_substr) + if rffi.cast(lltype.Signed, direction) >= 0: + return stringtype.stringstartswith(str, substr, start, end) + else: + return stringtype.stringendswith(str, substr, start, end) + diff --git a/pypy/rlib/debug.py b/pypy/rlib/debug.py --- a/pypy/rlib/debug.py +++ b/pypy/rlib/debug.py @@ -26,6 +26,7 @@ llop.debug_print_traceback(lltype.Void) llop.debug_fatalerror(lltype.Void, msg) fatalerror._dont_inline_ = True +fatalerror._jit_look_inside_ = False fatalerror._annenforceargs_ = [str] def fatalerror_notb(msg): @@ -34,6 +35,7 @@ from pypy.rpython.lltypesystem.lloperation import llop llop.debug_fatalerror(lltype.Void, msg) fatalerror_notb._dont_inline_ = True +fatalerror_notb._jit_look_inside_ = False fatalerror_notb._annenforceargs_ = [str] diff --git a/pypy/translator/sandbox/test/test_sandbox.py b/pypy/translator/sandbox/test/test_sandbox.py --- a/pypy/translator/sandbox/test/test_sandbox.py +++ b/pypy/translator/sandbox/test/test_sandbox.py @@ -145,9 +145,9 @@ g = pipe.stdin f = pipe.stdout expect(f, g, "ll_os.ll_os_getenv", ("PYPY_GENERATIONGC_NURSERY",), None) - if sys.platform.startswith('linux'): # on Mac, uses another (sandboxsafe) approach - expect(f, g, "ll_os.ll_os_open", ("/proc/cpuinfo", 0, 420), - OSError(5232, "xyz")) + #if sys.platform.startswith('linux'): + # expect(f, g, "ll_os.ll_os_open", ("/proc/cpuinfo", 0, 420), + # OSError(5232, "xyz")) expect(f, g, "ll_os.ll_os_getenv", ("PYPY_GC_DEBUG",), None) g.close() tail = f.read() _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit