Author: Matti Picus <[email protected]>
Branch: winconsoleio
Changeset: r97495:905c730547a7
Date: 2019-09-16 17:20 +0300
http://bitbucket.org/pypy/pypy/changeset/905c730547a7/

Log:    merge py3.6 into branch

diff too long, truncating to 2000 out of 5141 lines

diff --git a/lib-python/3/stat.py b/lib-python/3/stat.py
--- a/lib-python/3/stat.py
+++ b/lib-python/3/stat.py
@@ -40,6 +40,10 @@
 S_IFIFO  = 0o010000  # fifo (named pipe)
 S_IFLNK  = 0o120000  # symbolic link
 S_IFSOCK = 0o140000  # socket file
+# Fallbacks for uncommon platform-specific constants
+S_IFDOOR = 0
+S_IFPORT = 0
+S_IFWHT = 0
 
 # Functions to test for each file type
 
@@ -71,6 +75,18 @@
     """Return True if mode is from a socket."""
     return S_IFMT(mode) == S_IFSOCK
 
+def S_ISDOOR(mode):
+    """Return True if mode is from a door."""
+    return False
+
+def S_ISPORT(mode):
+    """Return True if mode is from an event port."""
+    return False
+
+def S_ISWHT(mode):
+    """Return True if mode is from a whiteout."""
+    return False
+
 # Names for permission bits
 
 S_ISUID = 0o4000  # set UID bit
diff --git a/lib-python/3/test/test_concurrent_futures.py 
b/lib-python/3/test/test_concurrent_futures.py
--- a/lib-python/3/test/test_concurrent_futures.py
+++ b/lib-python/3/test/test_concurrent_futures.py
@@ -428,6 +428,7 @@
                 futures_list.remove(future)
                 wr = weakref.ref(future)
                 del future
+                test.support.gc_collect()
                 self.assertIsNone(wr())
 
         futures_list[0].set_result("test")
@@ -435,6 +436,7 @@
             futures_list.remove(future)
             wr = weakref.ref(future)
             del future
+            test.support.gc_collect()
             self.assertIsNone(wr())
             if futures_list:
                 futures_list[0].set_result("test")
@@ -533,6 +535,7 @@
         for obj in self.executor.map(make_dummy_object, range(10)):
             wr = weakref.ref(obj)
             del obj
+            test.support.gc_collect()
             self.assertIsNone(wr())
 
 
diff --git a/lib-python/3/test/test_readline.py 
b/lib-python/3/test/test_readline.py
--- a/lib-python/3/test/test_readline.py
+++ b/lib-python/3/test/test_readline.py
@@ -227,7 +227,7 @@
     #   See https://cnswww.cns.cwru.edu/php/chet/readline/CHANGES
     # - editline: history size is broken on OS X 10.11.6.
     #   Newer versions were not tested yet.
-    @unittest.skipIf(readline._READLINE_VERSION < 0x600,
+    @unittest.skipIf(getattr(readline, "_READLINE_VERSION", 0x601) < 0x600,
                      "this readline version does not support history-size")
     @unittest.skipIf(is_editline,
                      "editline history size configuration is broken")
diff --git a/lib-python/3/test/test_regrtest.py 
b/lib-python/3/test/test_regrtest.py
--- a/lib-python/3/test/test_regrtest.py
+++ b/lib-python/3/test/test_regrtest.py
@@ -260,7 +260,6 @@
                 self.checkError([opt, '0', '-l'], "don't go together")
                 self.checkError([opt, '0', '-T'], "don't go together")
                 self.checkError([opt, '0', '-l'], "don't go together")
-                self.checkError([opt, '0', '-M', '4G'], "don't go together")
 
     def test_coverage(self):
         for opt in '-T', '--coverage':
diff --git a/lib_pypy/_curses_build.py b/lib_pypy/_curses_build.py
--- a/lib_pypy/_curses_build.py
+++ b/lib_pypy/_curses_build.py
@@ -34,6 +34,13 @@
 #define NCURSES_OPAQUE 0
 #endif
 
+
+/* ncurses 6 change behaviour  and makes all pointers opaque, 
+  lets define backward compatibility. It doesn't harm 
+  previous versions */
+
+#define NCURSES_INTERNALS 1
+#define NCURSES_REENTRANT 0
 #include <ncurses.h>
 #include <panel.h>
 #include <term.h>
diff --git a/lib_pypy/_dbm.py b/lib_pypy/_dbm.py
--- a/lib_pypy/_dbm.py
+++ b/lib_pypy/_dbm.py
@@ -149,7 +149,7 @@
     lib = CDLL("/usr/lib/libdbm.dylib") # OS X
     _platform = 'osx'
 
-library = "GNU gdbm"
+library = "Berkeley DB"
 
 funcs = {}
 _init_func('open', (c_char_p, c_int, c_int), restype=c_void_p)
diff --git a/lib_pypy/_pypy_testcapi.py b/lib_pypy/_pypy_testcapi.py
--- a/lib_pypy/_pypy_testcapi.py
+++ b/lib_pypy/_pypy_testcapi.py
@@ -61,6 +61,8 @@
     assert output_dir is not None
 
     from distutils.ccompiler import new_compiler
+    from distutils import log
+    log.set_verbosity(3)
 
     compiler = new_compiler()
     compiler.output_dir = output_dir
@@ -72,7 +74,8 @@
         ccflags = ['-fPIC', '-Wimplicit-function-declaration']
     res = compiler.compile([os.path.join(thisdir, csource)],
                            include_dirs=[include_dir],
-                           extra_preargs=ccflags)
+                           extra_preargs=ccflags,
+                          )
     object_filename = res[0]
 
     # set link options
diff --git a/lib_pypy/_stat.py b/lib_pypy/_stat.py
deleted file mode 100644
--- a/lib_pypy/_stat.py
+++ /dev/null
@@ -1,6 +0,0 @@
-# Assume not Solaris
-
-S_IFDOOR = 0
-
-def S_ISDOOR(mode):
-    return False
diff --git a/lib_pypy/_testcapimodule.c b/lib_pypy/_testcapimodule.c
--- a/lib_pypy/_testcapimodule.c
+++ b/lib_pypy/_testcapimodule.c
@@ -3009,6 +3009,8 @@
     return PyLong_FromLong(r);
 }
 
+#endif  /* PYPY_VERSION */
+
 static int
 check_time_rounding(int round)
 {
@@ -3069,6 +3071,8 @@
     return Py_BuildValue("Nl", _PyLong_FromTime_t(sec), nsec);
 }
 
+#ifndef PYPY_VERSION
+
 static void
 slot_tp_del(PyObject *self)
 {
@@ -3902,8 +3906,6 @@
     Py_RETURN_NONE;
 }
 
-#ifndef PYPY_VERSION
-
 static PyObject *
 test_pytime_fromseconds(PyObject *self, PyObject *args)
 {
@@ -4022,6 +4024,8 @@
     return _PyTime_AsNanosecondsObject(ms);
 }
 
+#ifndef PYPY_VERSION
+
 static PyObject*
 get_recursion_depth(PyObject *self, PyObject *args)
 {
@@ -4445,9 +4449,11 @@
     {"crash_no_current_thread", (PyCFunction)crash_no_current_thread, 
METH_NOARGS},
 #ifndef PYPY_VERSION
     {"run_in_subinterp",        run_in_subinterp,                METH_VARARGS},
+#endif
     {"pytime_object_to_time_t", test_pytime_object_to_time_t,  METH_VARARGS},
     {"pytime_object_to_timeval", test_pytime_object_to_timeval,  METH_VARARGS},
     {"pytime_object_to_timespec", test_pytime_object_to_timespec,  
METH_VARARGS},
+#ifndef PYPY_VERSION
     {"with_tp_del",             with_tp_del,                     METH_VARARGS},
 #endif
     {"create_cfunction",        create_cfunction,                METH_NOARGS},
@@ -4515,7 +4521,6 @@
         return_null_without_error, METH_NOARGS},
     {"return_result_with_error",
         return_result_with_error, METH_NOARGS},
-#ifndef PYPY_VERSION
     {"PyTime_FromSeconds", test_pytime_fromseconds,  METH_VARARGS},
     {"PyTime_FromSecondsObject", test_pytime_fromsecondsobject,  METH_VARARGS},
     {"PyTime_AsSecondsDouble", test_pytime_assecondsdouble, METH_VARARGS},
@@ -4525,6 +4530,7 @@
 #endif
     {"PyTime_AsMilliseconds", test_PyTime_AsMilliseconds, METH_VARARGS},
     {"PyTime_AsMicroseconds", test_PyTime_AsMicroseconds, METH_VARARGS},
+#ifndef PYPY_VERSION
     {"get_recursion_depth", get_recursion_depth, METH_NOARGS},
     {"pymem_buffer_overflow", pymem_buffer_overflow, METH_NOARGS},
     {"pymem_api_misuse", pymem_api_misuse, METH_NOARGS},
@@ -4538,10 +4544,10 @@
     {"pyobject_fastcalldict", test_pyobject_fastcalldict, METH_VARARGS},
     {"pyobject_fastcallkeywords", test_pyobject_fastcallkeywords, 
METH_VARARGS},
     {"raise_SIGINT_then_send_None", raise_SIGINT_then_send_None, METH_VARARGS},
+#endif
 #ifdef W_STOPCODE
     {"W_STOPCODE", py_w_stopcode, METH_VARARGS},
 #endif
-#endif /* PYPY_VERSION */
     {NULL, NULL} /* sentinel */
 };
 
diff --git a/lib_pypy/_tkinter/tklib_build.py b/lib_pypy/_tkinter/tklib_build.py
--- a/lib_pypy/_tkinter/tklib_build.py
+++ b/lib_pypy/_tkinter/tklib_build.py
@@ -36,8 +36,11 @@
         for _ver in ['8.6', '8.5', '']:
             incdirs = []
             linklibs = ['tcl' + _ver, 'tk' + _ver]
-            if os.path.isfile(''.join(['/usr/lib/lib', linklibs[1], '.so'])):
-                found = True
+            for lib in ['/usr/lib/lib', '/usr/lib64/lib']: 
+                if os.path.isfile(''.join([lib, linklibs[1], '.so'])):
+                    found = True
+                    break
+            if found:
                 break
     if not found:
         sys.stderr.write("*** TCL libraries not found!  Falling back...\n")
diff --git a/pypy/config/test/test_pypyoption.py 
b/pypy/config/test/test_pypyoption.py
--- a/pypy/config/test/test_pypyoption.py
+++ b/pypy/config/test/test_pypyoption.py
@@ -8,14 +8,13 @@
 def test_required():
     conf = get_pypy_config()
     assert not conf.translating
-
     assert conf.objspace.usemodules.gc
 
 def test_conflicting_gcrootfinder():
     conf = get_pypy_config()
     conf.translation.gc = "boehm"
-    py.test.raises(ConfigError, "conf.translation.gcrootfinder = 'asmgcc'")
-
+    with py.test.raises(ConfigError):
+        conf.translation.gcrootfinder = 'asmgcc'
 
 def test_frameworkgc():
     for name in ["minimark", "semispace"]:
diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst
--- a/pypy/doc/whatsnew-head.rst
+++ b/pypy/doc/whatsnew-head.rst
@@ -70,3 +70,15 @@
 .. branch: cryptograhpt-2.7
 
 Update vendored cryptography used for _ssl to 2.7
+
+.. branch: compile_ncurses_tcl_tk_suse_latest
+
+Check for headers and runtime libraries in more locations to support other 
linuxes
+
+.. branch: openssl-for-macos
+
+Update _ssl on macos to statically link to openssl-1.1.1c
+
+.. branch: more-cpyext
+
+Add more datetime C functions and definitions
diff --git a/pypy/interpreter/astcompiler/ast.py 
b/pypy/interpreter/astcompiler/ast.py
--- a/pypy/interpreter/astcompiler/ast.py
+++ b/pypy/interpreter/astcompiler/ast.py
@@ -2740,9 +2740,9 @@
         w_metavar = get_field(space, w_node, 'metavar', False)
         w_lineno = get_field(space, w_node, 'lineno', False)
         w_col_offset = get_field(space, w_node, 'col_offset', False)
-        _metavar = space.int_w(w_metavar)
-        _lineno = space.int_w(w_lineno)
-        _col_offset = space.int_w(w_col_offset)
+        _metavar = obj_to_int(space, w_metavar, False)
+        _lineno = obj_to_int(space, w_lineno, False)
+        _col_offset = obj_to_int(space, w_col_offset, False)
         return RevDBMetaVar(_metavar, _lineno, _col_offset)
 
 State.ast_type('RevDBMetaVar', 'expr', ['metavar'])
@@ -4291,19 +4291,27 @@
 
 class GenericASTVisitor(ASTVisitor):
 
+    def visited(self, node):
+        pass  # base implementation
+
     def visit_Module(self, node):
+        self.visited(node)
         self.visit_sequence(node.body)
 
     def visit_Interactive(self, node):
+        self.visited(node)
         self.visit_sequence(node.body)
 
     def visit_Expression(self, node):
+        self.visited(node)
         node.body.walkabout(self)
 
     def visit_Suite(self, node):
+        self.visited(node)
         self.visit_sequence(node.body)
 
     def visit_FunctionDef(self, node):
+        self.visited(node)
         node.args.walkabout(self)
         self.visit_sequence(node.body)
         self.visit_sequence(node.decorator_list)
@@ -4311,6 +4319,7 @@
             node.returns.walkabout(self)
 
     def visit_AsyncFunctionDef(self, node):
+        self.visited(node)
         node.args.walkabout(self)
         self.visit_sequence(node.body)
         self.visit_sequence(node.decorator_list)
@@ -4318,214 +4327,269 @@
             node.returns.walkabout(self)
 
     def visit_ClassDef(self, node):
+        self.visited(node)
         self.visit_sequence(node.bases)
         self.visit_sequence(node.keywords)
         self.visit_sequence(node.body)
         self.visit_sequence(node.decorator_list)
 
     def visit_Return(self, node):
+        self.visited(node)
         if node.value:
             node.value.walkabout(self)
 
     def visit_Delete(self, node):
+        self.visited(node)
         self.visit_sequence(node.targets)
 
     def visit_Assign(self, node):
+        self.visited(node)
         self.visit_sequence(node.targets)
         node.value.walkabout(self)
 
     def visit_AugAssign(self, node):
+        self.visited(node)
         node.target.walkabout(self)
         node.value.walkabout(self)
 
     def visit_AnnAssign(self, node):
+        self.visited(node)
         node.target.walkabout(self)
         node.annotation.walkabout(self)
         if node.value:
             node.value.walkabout(self)
 
     def visit_For(self, node):
+        self.visited(node)
         node.target.walkabout(self)
         node.iter.walkabout(self)
         self.visit_sequence(node.body)
         self.visit_sequence(node.orelse)
 
     def visit_AsyncFor(self, node):
+        self.visited(node)
         node.target.walkabout(self)
         node.iter.walkabout(self)
         self.visit_sequence(node.body)
         self.visit_sequence(node.orelse)
 
     def visit_While(self, node):
+        self.visited(node)
         node.test.walkabout(self)
         self.visit_sequence(node.body)
         self.visit_sequence(node.orelse)
 
     def visit_If(self, node):
+        self.visited(node)
         node.test.walkabout(self)
         self.visit_sequence(node.body)
         self.visit_sequence(node.orelse)
 
     def visit_With(self, node):
+        self.visited(node)
         self.visit_sequence(node.items)
         self.visit_sequence(node.body)
 
     def visit_AsyncWith(self, node):
+        self.visited(node)
         self.visit_sequence(node.items)
         self.visit_sequence(node.body)
 
     def visit_Raise(self, node):
+        self.visited(node)
         if node.exc:
             node.exc.walkabout(self)
         if node.cause:
             node.cause.walkabout(self)
 
     def visit_Try(self, node):
+        self.visited(node)
         self.visit_sequence(node.body)
         self.visit_sequence(node.handlers)
         self.visit_sequence(node.orelse)
         self.visit_sequence(node.finalbody)
 
     def visit_Assert(self, node):
+        self.visited(node)
         node.test.walkabout(self)
         if node.msg:
             node.msg.walkabout(self)
 
     def visit_Import(self, node):
+        self.visited(node)
         self.visit_sequence(node.names)
 
     def visit_ImportFrom(self, node):
+        self.visited(node)
         self.visit_sequence(node.names)
 
     def visit_Global(self, node):
+        self.visited(node)
         pass
 
     def visit_Nonlocal(self, node):
+        self.visited(node)
         pass
 
     def visit_Expr(self, node):
+        self.visited(node)
         node.value.walkabout(self)
 
     def visit_Pass(self, node):
+        self.visited(node)
         pass
 
     def visit_Break(self, node):
+        self.visited(node)
         pass
 
     def visit_Continue(self, node):
+        self.visited(node)
         pass
 
     def visit_BoolOp(self, node):
+        self.visited(node)
         self.visit_sequence(node.values)
 
     def visit_BinOp(self, node):
+        self.visited(node)
         node.left.walkabout(self)
         node.right.walkabout(self)
 
     def visit_UnaryOp(self, node):
+        self.visited(node)
         node.operand.walkabout(self)
 
     def visit_Lambda(self, node):
+        self.visited(node)
         node.args.walkabout(self)
         node.body.walkabout(self)
 
     def visit_IfExp(self, node):
+        self.visited(node)
         node.test.walkabout(self)
         node.body.walkabout(self)
         node.orelse.walkabout(self)
 
     def visit_Dict(self, node):
+        self.visited(node)
         self.visit_sequence(node.keys)
         self.visit_sequence(node.values)
 
     def visit_Set(self, node):
+        self.visited(node)
         self.visit_sequence(node.elts)
 
     def visit_ListComp(self, node):
+        self.visited(node)
         node.elt.walkabout(self)
         self.visit_sequence(node.generators)
 
     def visit_SetComp(self, node):
+        self.visited(node)
         node.elt.walkabout(self)
         self.visit_sequence(node.generators)
 
     def visit_DictComp(self, node):
+        self.visited(node)
         node.key.walkabout(self)
         node.value.walkabout(self)
         self.visit_sequence(node.generators)
 
     def visit_GeneratorExp(self, node):
+        self.visited(node)
         node.elt.walkabout(self)
         self.visit_sequence(node.generators)
 
     def visit_Await(self, node):
+        self.visited(node)
         node.value.walkabout(self)
 
     def visit_Yield(self, node):
+        self.visited(node)
         if node.value:
             node.value.walkabout(self)
 
     def visit_YieldFrom(self, node):
+        self.visited(node)
         node.value.walkabout(self)
 
     def visit_Compare(self, node):
+        self.visited(node)
         node.left.walkabout(self)
         self.visit_sequence(node.comparators)
 
     def visit_Call(self, node):
+        self.visited(node)
         node.func.walkabout(self)
         self.visit_sequence(node.args)
         self.visit_sequence(node.keywords)
 
     def visit_Num(self, node):
+        self.visited(node)
         pass
 
     def visit_Str(self, node):
+        self.visited(node)
         pass
 
     def visit_RevDBMetaVar(self, node):
+        self.visited(node)
         pass
 
     def visit_FormattedValue(self, node):
+        self.visited(node)
         node.value.walkabout(self)
         if node.format_spec:
             node.format_spec.walkabout(self)
 
     def visit_JoinedStr(self, node):
+        self.visited(node)
         self.visit_sequence(node.values)
 
     def visit_Bytes(self, node):
+        self.visited(node)
         pass
 
     def visit_NameConstant(self, node):
+        self.visited(node)
         pass
 
     def visit_Ellipsis(self, node):
+        self.visited(node)
         pass
 
     def visit_Constant(self, node):
+        self.visited(node)
         pass
 
     def visit_Attribute(self, node):
+        self.visited(node)
         node.value.walkabout(self)
 
     def visit_Subscript(self, node):
+        self.visited(node)
         node.value.walkabout(self)
         node.slice.walkabout(self)
 
     def visit_Starred(self, node):
+        self.visited(node)
         node.value.walkabout(self)
 
     def visit_Name(self, node):
+        self.visited(node)
         pass
 
     def visit_List(self, node):
+        self.visited(node)
         self.visit_sequence(node.elts)
 
     def visit_Tuple(self, node):
+        self.visited(node)
         self.visit_sequence(node.elts)
 
     def visit_Slice(self, node):
+        self.visited(node)
         if node.lower:
             node.lower.walkabout(self)
         if node.upper:
@@ -4534,22 +4598,27 @@
             node.step.walkabout(self)
 
     def visit_ExtSlice(self, node):
+        self.visited(node)
         self.visit_sequence(node.dims)
 
     def visit_Index(self, node):
+        self.visited(node)
         node.value.walkabout(self)
 
     def visit_comprehension(self, node):
+        self.visited(node)
         node.target.walkabout(self)
         node.iter.walkabout(self)
         self.visit_sequence(node.ifs)
 
     def visit_ExceptHandler(self, node):
+        self.visited(node)
         if node.type:
             node.type.walkabout(self)
         self.visit_sequence(node.body)
 
     def visit_arguments(self, node):
+        self.visited(node)
         self.visit_sequence(node.args)
         if node.vararg:
             node.vararg.walkabout(self)
@@ -4560,16 +4629,20 @@
         self.visit_sequence(node.defaults)
 
     def visit_arg(self, node):
+        self.visited(node)
         if node.annotation:
             node.annotation.walkabout(self)
 
     def visit_keyword(self, node):
+        self.visited(node)
         node.value.walkabout(self)
 
     def visit_alias(self, node):
+        self.visited(node)
         pass
 
     def visit_withitem(self, node):
+        self.visited(node)
         node.context_expr.walkabout(self)
         if node.optional_vars:
             node.optional_vars.walkabout(self)
diff --git a/pypy/interpreter/astcompiler/astbuilder.py 
b/pypy/interpreter/astcompiler/astbuilder.py
--- a/pypy/interpreter/astcompiler/astbuilder.py
+++ b/pypy/interpreter/astcompiler/astbuilder.py
@@ -939,7 +939,7 @@
             elif comp_type == tokens.NOTEQUAL:
                 flufl = self.compile_info.flags & 
consts.CO_FUTURE_BARRY_AS_BDFL
                 if flufl and comp_node.get_value() == '!=':
-                    self.error('invalid comparison', comp_node)
+                    self.error("with Barry as BDFL, use '<>' instead of '!='", 
comp_node)
                 elif not flufl and comp_node.get_value() == '<>':
                     self.error('invalid comparison', comp_node)
                 return ast.NotEq
diff --git a/pypy/interpreter/astcompiler/fstring.py 
b/pypy/interpreter/astcompiler/fstring.py
--- a/pypy/interpreter/astcompiler/fstring.py
+++ b/pypy/interpreter/astcompiler/fstring.py
@@ -25,7 +25,7 @@
 def f_constant_string(astbuilder, joined_pieces, w_u, atom_node):
     add_constant_string(astbuilder, joined_pieces, w_u, atom_node)
 
-def f_string_compile(astbuilder, source, atom_node):
+def f_string_compile(astbuilder, source, atom_node, fstr):
     # Note: a f-string is kept as a single literal up to here.
     # At this point only, we recursively call the AST compiler
     # on all the '{expr}' parts.  The 'expr' part is not parsed
@@ -44,16 +44,44 @@
         astbuilder.error("internal error: parser not available for parsing "
                    "the expressions inside the f-string", atom_node)
     assert isinstance(source, str)    # utf-8 encoded
-    source = '(%s)' % source
+
+    paren_source = '(%s)' % source  # to deal with whitespace at the start of 
source
+
+    lineno = 0
+    column_offset = 0
+    if fstr.stnode:
+        stnode = fstr.stnode
+        lineno = stnode.get_lineno() - 1 # one-based
+        # CPython has an equivalent hack :-(
+        value = stnode.get_value()
+        if value is not None:
+            column_offset = value.find(source) + stnode.get_column()
 
     info = pyparse.CompileInfo("<fstring>", "eval",
                                consts.PyCF_SOURCE_IS_UTF8 |
                                consts.PyCF_IGNORE_COOKIE,
                                optimize=astbuilder.compile_info.optimize)
     parser = astbuilder.recursive_parser
-    parse_tree = parser.parse_source(source, info)
-    return ast_from_node(astbuilder.space, parse_tree, info,
-                         recursive_parser=parser)
+    parse_tree = parser.parse_source(paren_source, info)
+
+    ast = ast_from_node(astbuilder.space, parse_tree, info,
+                        recursive_parser=parser)
+    fixup_fstring_positions(ast, lineno, column_offset)
+    return ast
+
+def fixup_fstring_positions(ast, line_offset, column_offset):
+    visitor = FixPosVisitor(line_offset, column_offset)
+    ast.walkabout(visitor)
+
+class FixPosVisitor(ast.GenericASTVisitor):
+    def __init__(self, line_offset, column_offset):
+        self.line_offset = line_offset
+        self.column_offset = column_offset
+
+    def visited(self, node):
+        if isinstance(node, ast.stmt) or isinstance(node, ast.expr):
+            node.lineno += self.line_offset
+            node.col_offset += self.column_offset
 
 
 def unexpected_end_of_string(astbuilder, atom_node):
@@ -177,7 +205,7 @@
     # Compile the expression as soon as possible, so we show errors
     # related to the expression before errors related to the
     # conversion or format_spec.
-    expr = f_string_compile(astbuilder, s[expr_start:i], atom_node)
+    expr = f_string_compile(astbuilder, s[expr_start:i], atom_node, fstr)
     assert isinstance(expr, ast.Expression)
 
     # Check for a conversion char, if present.
@@ -345,7 +373,7 @@
         child = atom_node.get_child(i)
         try:
             w_next = parsestring.parsestr(
-                    space, encoding, child.get_value())
+                    space, encoding, child.get_value(), child)
             if not isinstance(w_next, parsestring.W_FString):
                 add_constant_string(astbuilder, joined_pieces, w_next,
                                     atom_node)
diff --git a/pypy/interpreter/astcompiler/optimize.py 
b/pypy/interpreter/astcompiler/optimize.py
--- a/pypy/interpreter/astcompiler/optimize.py
+++ b/pypy/interpreter/astcompiler/optimize.py
@@ -142,6 +142,16 @@
     """)
     return space.pow(w_left, w_right, space.w_None)
 
+def _fold_lshift(space, w_left, w_right):
+    # don't constant-fold if "w_left" and "w_right" are integers and
+    # the estimated bit length of the result is unreasonably large
+    space.appexec([w_left, w_right], """(left, right):
+        if isinstance(left, int) and isinstance(right, int):
+            if left.bit_length() + right > 1000:
+                raise OverflowError
+    """)
+    return space.lshift(w_left, w_right)
+
 def _fold_not(space, operand):
     return space.newbool(not space.is_true(operand))
 
@@ -154,7 +164,7 @@
     ast.FloorDiv : _binary_fold("floordiv"),
     ast.Mod : _binary_fold("mod"),
     ast.Pow : _fold_pow,
-    ast.LShift : _binary_fold("lshift"),
+    ast.LShift : _fold_lshift,
     ast.RShift : _binary_fold("rshift"),
     ast.BitOr : _binary_fold("or_"),
     ast.BitXor : _binary_fold("xor"),
diff --git a/pypy/interpreter/astcompiler/test/test_astbuilder.py 
b/pypy/interpreter/astcompiler/test/test_astbuilder.py
--- a/pypy/interpreter/astcompiler/test/test_astbuilder.py
+++ b/pypy/interpreter/astcompiler/test/test_astbuilder.py
@@ -22,7 +22,7 @@
             flags = consts.CO_FUTURE_WITH_STATEMENT
         info = pyparse.CompileInfo("<test>", p_mode, flags)
         tree = self.parser.parse_source(source, info)
-        ast_node = ast_from_node(self.space, tree, info)
+        ast_node = ast_from_node(self.space, tree, info, self.parser)
         return ast_node
 
     def get_first_expr(self, source, p_mode=None, flags=None):
@@ -1476,3 +1476,8 @@
                            " bytes in position 0-1: truncated \\xXX escape")
         assert exc.lineno == 2
         assert exc.offset == 6
+
+    def test_fstring_lineno(self):
+        mod = self.get_ast('x=1\nf"{    x + 1}"')
+        assert mod.body[1].value.values[0].value.lineno == 2
+        assert mod.body[1].value.values[0].value.col_offset == 8
diff --git a/pypy/interpreter/astcompiler/test/test_compiler.py 
b/pypy/interpreter/astcompiler/test/test_compiler.py
--- a/pypy/interpreter/astcompiler/test/test_compiler.py
+++ b/pypy/interpreter/astcompiler/test/test_compiler.py
@@ -1474,13 +1474,14 @@
             assert ops.LOAD_CONST in counts
 
     def test_dont_fold_huge_powers(self):
-        for source in (
-            "2 ** 3000",         # not constant-folded: too big
-            "(-2) ** 3000",
+        for source, op in (
+                ("2 ** 3000", ops.BINARY_POWER),  # not constant-folded: too 
big
+                ("(-2) ** 3000", ops.BINARY_POWER),
+                ("5 << 1000", ops.BINARY_LSHIFT),
             ):
             source = 'def f(): %s' % source
             counts = self.count_instructions(source)
-            assert ops.BINARY_POWER in counts
+            assert op in counts
 
         for source in (
             "2 ** 2000",         # constant-folded
diff --git a/pypy/interpreter/astcompiler/tools/asdl_py.py 
b/pypy/interpreter/astcompiler/tools/asdl_py.py
--- a/pypy/interpreter/astcompiler/tools/asdl_py.py
+++ b/pypy/interpreter/astcompiler/tools/asdl_py.py
@@ -341,6 +341,9 @@
     def visitModule(self, mod):
         self.emit("class GenericASTVisitor(ASTVisitor):")
         self.emit("")
+        self.emit("def visited(self, node):", 1)
+        self.emit("pass  # base implementation", 2)
+        self.emit("")
         super(GenericASTVisitorVisitor, self).visitModule(mod)
         self.emit("")
 
@@ -357,6 +360,7 @@
 
     def make_visitor(self, name, fields):
         self.emit("def visit_%s(self, node):" % (name,), 1)
+        self.emit("self.visited(node)", 2)
         have_body = False
         for field in fields:
             if self.visitField(field):
diff --git a/pypy/interpreter/generator.py b/pypy/interpreter/generator.py
--- a/pypy/interpreter/generator.py
+++ b/pypy/interpreter/generator.py
@@ -785,4 +785,8 @@
                 # StopIteration, signalling that this 'aclose()' await
                 # is done.
                 raise OperationError(space.w_StopIteration, space.w_None)
+        if e.match(space, space.w_GeneratorExit):
+            if self.w_exc_type is None:
+                # Ignore this error.
+                raise OperationError(space.w_StopIteration, space.w_None)
         raise e
diff --git a/pypy/interpreter/pyparser/parsestring.py 
b/pypy/interpreter/pyparser/parsestring.py
--- a/pypy/interpreter/pyparser/parsestring.py
+++ b/pypy/interpreter/pyparser/parsestring.py
@@ -7,14 +7,15 @@
 
 
 class W_FString(W_Root):
-    def __init__(self, unparsed, raw_mode):
+    def __init__(self, unparsed, raw_mode, stnode):
         assert isinstance(unparsed, str)    # utf-8 encoded string
         self.unparsed = unparsed     # but the quotes are removed
         self.raw_mode = raw_mode
         self.current_index = 0       # for astcompiler.fstring
+        self.stnode = stnode
 
 
-def parsestr(space, encoding, s):
+def parsestr(space, encoding, s, stnode=None):
     """Parses a string or unicode literal, and return usually
     a wrapped value.  If we get an f-string, then instead return
     an unparsed but unquoted W_FString instance.
@@ -88,7 +89,7 @@
     if unicode_literal and not rawmode: # XXX Py_UnicodeFlag is ignored for now
         assert 0 <= ps <= q
         if saw_f:
-            return W_FString(s[ps:q], rawmode)
+            return W_FString(s[ps:q], rawmode, stnode)
         if encoding is None:
             substr = s[ps:q]
         else:
@@ -112,7 +113,7 @@
         if not unicode_literal:
             return space.newbytes(substr)
         elif saw_f:
-            return W_FString(substr, rawmode)
+            return W_FString(substr, rawmode, stnode)
         else:
             v = unicodehelper.str_decode_utf8(substr, 'strict', True, None)
             return space.newtext(*v)
diff --git a/pypy/interpreter/test/apptest_coroutine.py 
b/pypy/interpreter/test/apptest_coroutine.py
--- a/pypy/interpreter/test/apptest_coroutine.py
+++ b/pypy/interpreter/test/apptest_coroutine.py
@@ -202,6 +202,7 @@
     import gc, warnings  # XXX: importing warnings is expensive untranslated
     async def foobaz():
         pass
+    gc.collect()   # emit warnings from unrelated older tests
     with warnings.catch_warnings(record=True) as l:
         foobaz()
         gc.collect()
diff --git a/pypy/interpreter/test/apptest_pyframe.py 
b/pypy/interpreter/test/apptest_pyframe.py
--- a/pypy/interpreter/test/apptest_pyframe.py
+++ b/pypy/interpreter/test/apptest_pyframe.py
@@ -13,7 +13,8 @@
     import sys
     f = sys._getframe()
     assert f.f_globals is globals()
-    pytest.raises(AttributeError, "f.f_globals = globals()")
+    with pytest.raises(AttributeError):
+        f.f_globals = globals()
 
 def test_f_builtins():
     import sys, builtins
diff --git a/pypy/interpreter/test/test_compiler.py 
b/pypy/interpreter/test/test_compiler.py
--- a/pypy/interpreter/test/test_compiler.py
+++ b/pypy/interpreter/test/test_compiler.py
@@ -706,31 +706,26 @@
 
     def test_dont_inherit_flag(self):
         # this test checks that compile() don't inherit the __future__ flags
-        # of the hosting code. However, in Python3 we don't have any
-        # meaningful __future__ flag to check that (they are all enabled). The
-        # only candidate could be barry_as_FLUFL, but it's not implemented yet
-        # (and not sure it'll ever be)
-        py.test.skip("we cannot actually check the result of this test (see 
comment)")
+        # of the hosting code.
         space = self.space
         s1 = str(py.code.Source("""
-            from __future__ import division
-            exec(compile('x = 1/2', '?', 'exec', 0, 1))
+            from __future__ import barry_as_FLUFL
+            # not a syntax error inside the exec!
+            exec(compile('x = 1 != 2', '?', 'exec', 0, 1))
         """))
         w_result = space.appexec([space.wrap(s1)], """(s1):
             ns = {}
             exec(s1, ns)
             return ns['x']
         """)
-        assert space.float_w(w_result) == 0
+        assert space.is_true(w_result)
 
     def test_dont_inherit_across_import(self):
-        # see the comment for test_dont_inherit_flag
-        py.test.skip("we cannot actually check the result of this test (see 
comment)")
         from rpython.tool.udir import udir
-        udir.join('test_dont_inherit_across_import.py').write('x = 1/2\n')
+        udir.join('test_dont_inherit_across_import.py').write('x = 1 != 2\n')
         space = self.space
         s1 = str(py.code.Source("""
-            from __future__ import division
+            from __future__ import barry_as_FLUFL
             from test_dont_inherit_across_import import x
         """))
         w_result = space.appexec([space.wrap(str(udir)), space.wrap(s1)],
@@ -738,13 +733,14 @@
             import sys
             copy = sys.path[:]
             sys.path.insert(0, udir)
+            ns = {}
             try:
-                exec s1
+                exec(s1, ns)
             finally:
                 sys.path[:] = copy
-            return x
+            return ns['x']
         """)
-        assert space.float_w(w_result) == 0
+        assert space.is_true(w_result)
 
     def test_filename_in_syntaxerror(self):
         e = py.test.raises(OperationError, self.compiler.compile, """if 1:
@@ -917,9 +913,11 @@
         code = "from __future__ import barry_as_FLUFL; 2 {0} 3"
         compile(code.format('<>'), '<BDFL test>', 'exec',
                 __future__.CO_FUTURE_BARRY_AS_BDFL)
-        raises(SyntaxError, compile, code.format('!='),
+        with raises(SyntaxError) as excinfo:
+            compile(code.format('!='),
                '<FLUFL test>', 'exec',
                __future__.CO_FUTURE_BARRY_AS_BDFL)
+        assert excinfo.value.msg == "with Barry as BDFL, use '<>' instead of 
'!='"
 
     def test_guido_as_bdfl(self):
         # from test_flufl.py :-)
diff --git a/pypy/interpreter/test/test_function.py 
b/pypy/interpreter/test/test_function.py
--- a/pypy/interpreter/test/test_function.py
+++ b/pypy/interpreter/test/test_function.py
@@ -160,7 +160,8 @@
             return 41
         assert f() == 42
         assert g() == 41
-        raises(TypeError, "f.__code__ = 1")
+        with raises(TypeError):
+            f.__code__ = 1
         f.__code__ = g.__code__
         assert f() == 41
         def get_h(f=f):
@@ -168,14 +169,17 @@
                 return f() # a closure
             return h
         h = get_h()
-        raises(ValueError, "f.__code__ = h.__code__")
+        with raises(ValueError):
+            f.__code__ = h.__code__
 
     @pytest.mark.skipif("config.option.runappdirect")
     def test_write_code_builtin_forbidden(self):
         def f(*args):
             return 42
-        raises(TypeError, "dir.__code__ = f.__code__")
-        raises(TypeError, "list.append.__code__ = f.__code__")
+        with raises(TypeError):
+            dir.__code__ = f.__code__
+        with raises(TypeError):
+            list.append.__code__ = f.__code__
 
     def test_set_module_to_name_eagerly(self):
         skip("fails on PyPy but works on CPython.  Unsure we want to care")
@@ -313,19 +317,10 @@
             def func(self, **kw):
                 return self, kw
         func = A().func
-
-        # don't want the extra argument passing of raises
-        try:
+        with raises(TypeError):
             func(self=23)
-            assert False
-        except TypeError:
-            pass
-
-        try:
+        with raises(TypeError):
             func(**{'self': 23})
-            assert False
-        except TypeError:
-            pass
 
     def test_kwargs_confusing_name(self):
         def func(self):    # 'self' conflicts with the interp-level
diff --git a/pypy/interpreter/test/test_nestedscope.py 
b/pypy/interpreter/test/test_nestedscope.py
--- a/pypy/interpreter/test/test_nestedscope.py
+++ b/pypy/interpreter/test/test_nestedscope.py
@@ -99,7 +99,8 @@
             x = 1
 
         g = f()
-        raises(ValueError, "g.__closure__[0].cell_contents")
+        with raises(ValueError):
+            g.__closure__[0].cell_contents
 
     def test_compare_cells(self):
         def f(n):
diff --git a/pypy/interpreter/test/test_pyframe.py 
b/pypy/interpreter/test/test_pyframe.py
--- a/pypy/interpreter/test/test_pyframe.py
+++ b/pypy/interpreter/test/test_pyframe.py
@@ -62,7 +62,7 @@
 
         jump_out_of_block_forwards.jump = (3, 5)
         jump_out_of_block_forwards.output = [2, 5]
-        #run_test(jump_out_of_block_forwards)
+        run_test(jump_out_of_block_forwards)
 
         def jump_out_of_block_backwards(output):
             output.append(1)
diff --git a/pypy/interpreter/test/test_raise.py 
b/pypy/interpreter/test/test_raise.py
--- a/pypy/interpreter/test/test_raise.py
+++ b/pypy/interpreter/test/test_raise.py
@@ -2,9 +2,8 @@
 
 class AppTestRaise:
     def test_arg_as_string(self):
-        def f():
+        with raises(TypeError):
             raise "test"
-        raises(TypeError, f)
 
     def test_control_flow(self):
         try:
@@ -36,9 +35,8 @@
             assert isinstance(e, IndexError)
 
     def test_raise_cls(self):
-        def f():
+        with raises(IndexError):
             raise IndexError
-        raises(IndexError, f)
 
     def test_raise_cls_catch(self):
         def f(r):
@@ -46,7 +44,8 @@
                 raise r
             except LookupError:
                 return 1
-        raises(Exception, f, Exception)
+        with raises(Exception):
+            f(Exception)
         assert f(IndexError) == 1
 
     def test_raise_wrong(self):
@@ -99,7 +98,7 @@
         assert sys.exc_info() == (None, None, None)
 
     def test_reraise_1(self):
-        raises(IndexError, """
+        with raises(IndexError):
             import sys
             try:
                 raise ValueError
@@ -109,10 +108,10 @@
                 finally:
                     assert sys.exc_info()[0] is IndexError
                     raise
-        """)
+ 
 
     def test_reraise_2(self):
-        raises(IndexError, """
+        with raises(IndexError):
             def foo():
                 import sys
                 assert sys.exc_info()[0] is IndexError
@@ -124,10 +123,10 @@
                     raise IndexError
                 finally:
                     foo()
-        """)
+ 
 
     def test_reraise_3(self):
-        raises(IndexError, """
+        with raises(IndexError):
             def spam():
                 import sys
                 try:
@@ -142,7 +141,6 @@
                     raise IndexError
                 finally:
                     spam()
-        """)
 
     def test_reraise_4(self):
         import sys
@@ -156,7 +154,7 @@
         assert ok
 
     def test_reraise_5(self):
-        raises(IndexError, """
+        with raises(IndexError):
             import sys
             try:
                 raise ValueError
@@ -170,17 +168,16 @@
                 finally:
                     assert sys.exc_info()[0] is IndexError
                     assert sys.exc_info()[2].tb_next is some_traceback
-        """)
 
     def test_nested_reraise(self):
-        raises(TypeError, """
+        with raises(TypeError):
             def nested_reraise():
                 raise
             try:
                 raise TypeError("foo")
             except:
                 nested_reraise()
-        """)
+ 
 
     def test_with_reraise_1(self):
         class Context:
@@ -196,7 +193,8 @@
                 with Context():
                     pass
                 raise
-        raises(ValueError, "fn()")
+        with raises(ValueError):
+            fn()
 
 
     def test_with_reraise_2(self):
@@ -213,23 +211,20 @@
                 with Context():
                     raise KeyError("caught")
                 raise
-        raises(ValueError, "fn()")
+        with raises(ValueError):
+            fn()
 
     def test_userclass(self):
         # new-style classes can't be raised unless they inherit from
         # BaseException
-
         class A(object):
             def __init__(self, x=None):
                 self.x = x
-        
-        def f():
+
+        with raises(TypeError):
             raise A
-        raises(TypeError, f)
-
-        def f():
+        with raises(TypeError):
             raise A(42)
-        raises(TypeError, f)
 
     def test_userclass_catch(self):
         # classes can't be caught unless they inherit from BaseException
@@ -259,7 +254,7 @@
     def test_catch_tuple(self):
         class A(Exception):
             pass
-        
+
         try:
             raise ValueError
         except (ValueError, A):
@@ -307,7 +302,9 @@
         class MyException(Exception):
             def __new__(cls, *args):
                 return object()
-        raises(TypeError, "raise MyException")
+
+        with raises(TypeError):
+            raise MyException
 
     def test_with_exit_True(self):
         class X:
diff --git a/pypy/interpreter/test/test_syntax.py 
b/pypy/interpreter/test/test_syntax.py
--- a/pypy/interpreter/test/test_syntax.py
+++ b/pypy/interpreter/test/test_syntax.py
@@ -344,9 +344,6 @@
 
 class AppTestWith:
     def test_with_simple(self):
-
-        s = """
-if 1:
         class Context:
             def __init__(self):
                 self.calls = list()
@@ -360,78 +357,28 @@
         acontext = Context()
         with acontext:
             pass
-        """
-        ns = {}
-        exec(s, ns)
-        acontext = ns['acontext']
         assert acontext.calls == '__enter__ __exit__'.split()
 
     def test_compound_with(self):
-        s = """class Context:
-    def __init__(self, var):
-        self.record = []
-        self.var = var
-    def __enter__(self):
-        self.record.append(("__enter__", self.var))
-        return self.var
-    def __exit__(self, tp, value, tb):
-        self.record.append(("__exit__", self.var))
-c1 = Context("blah")
-c2 = Context("bling")
-with c1 as v1, c2 as v2:
-    pass
-    """
-        ns = {}
-        exec(s, ns)
-        assert ns["v1"] == "blah"
-        assert ns["v2"] == "bling"
-        assert ns["c1"].record == [("__enter__", "blah"), ("__exit__", "blah")]
-        assert ns["c2"].record == [("__enter__", "bling"),
-                                   ("__exit__", "bling")]
-
-
-    def test_start_with_blank_line(self):
-        s = """
-if 1:
         class Context:
-            def __init__(self):
-                self.calls = list()
-
+            def __init__(self, var):
+                self.record = []
+                self.var = var
             def __enter__(self):
-                self.calls.append('__enter__')
-
-            def __exit__(self, exc_type, exc_value, exc_tb):
-                self.calls.append('__exit__')
-
-        acontext = Context()
-        with acontext:
+                self.record.append(("__enter__", self.var))
+                return self.var
+            def __exit__(self, tp, value, tb):
+                self.record.append(("__exit__", self.var))
+        c1 = Context("blah")
+        c2 = Context("bling")
+        with c1 as v1, c2 as v2:
             pass
-"""
-        ns = {}
-        exec(s, ns)
-        acontext = ns['acontext']
-        assert acontext.calls == '__enter__ __exit__'.split()
-
-    def test_raw_doc_string(self):
-        s = """r'doc'
-class Context(object):
-    def __enter__(self):
-        global enter
-        enter = True
-    def __exit__(self, *exc):
-        global exit
-        exit = True
-with Context() as w:
-    pass"""
-        ns = {}
-        exec(s, ns)
-        assert ns['enter']
-        assert ns['exit']
+        assert v1 == "blah"
+        assert v2 == "bling"
+        assert c1.record == [("__enter__", "blah"), ("__exit__", "blah")]
+        assert c2.record == [("__enter__", "bling"), ("__exit__", "bling")]
 
     def test_with_as_var(self):
-
-        s = """
-if 1:
         class Context:
             def __init__(self):
                 self.calls = list()
@@ -448,17 +395,10 @@
         with acontextfact as avar:
             avar.append('__body__')
             pass
-        """
-        ns = {}
-        exec(s, ns)
-        acontextfact = ns['acontextfact']
         assert acontextfact.exit_params == (None, None, None)
         assert acontextfact.calls == '__enter__ __body__ __exit__'.split()
 
     def test_with_raise_exception(self):
-
-        s = """
-if 1:
         class Context:
             def __init__(self):
                 self.calls = list()
@@ -482,20 +422,12 @@
             pass
         else:
             raise AssertionError('With did not raise RuntimeError')
-        """
-        ns = {}
-        exec(s, ns)
-        acontextfact = ns['acontextfact']
-        error = ns['error']
         assert acontextfact.calls == '__enter__ __body__ __exit__'.split()
         assert acontextfact.exit_params[0:2] == (RuntimeError, error)
         import types
         assert isinstance(acontextfact.exit_params[2], types.TracebackType)
 
     def test_with_swallow_exception(self):
-
-        s = """
-if 1:
         class Context:
             def __init__(self):
                 self.calls = list()
@@ -515,11 +447,6 @@
             avar.append('__body__')
             raise error
             avar.append('__after_raise__')
-        """
-        ns = {}
-        exec(s, ns)
-        acontextfact = ns['acontextfact']
-        error = ns['error']
         assert acontextfact.calls == '__enter__ __body__ __exit__'.split()
         assert acontextfact.exit_params[0:2] == (RuntimeError, error)
         import types
@@ -544,9 +471,6 @@
         assert c.calls == ['exit']
 
     def test_with_break(self):
-
-        s = """
-if 1:
         class Context:
             def __init__(self):
                 self.calls = list()
@@ -568,17 +492,10 @@
                 avar.append('__after_break__')
         else:
             raise AssertionError('Break failed with With, reached else clause')
-        """
-        ns = {}
-        exec(s, ns)
-        acontextfact = ns['acontextfact']
         assert acontextfact.calls == '__enter__ __body__ __exit__'.split()
         assert acontextfact.exit_params == (None, None, None)
 
     def test_with_continue(self):
-
-        s = """
-if 1:
         class Context:
             def __init__(self):
                 self.calls = list()
@@ -600,16 +517,10 @@
                 avar.append('__after_continue__')
         else:
             avar.append('__continue__')
-        """
-        ns = {}
-        exec(s, ns)
-        acontextfact = ns['acontextfact']
         assert acontextfact.calls == '__enter__ __body__ __exit__ 
__continue__'.split()
         assert acontextfact.exit_params == (None, None, None)
 
     def test_with_return(self):
-        s = """
-if 1:
         class Context:
             def __init__(self):
                 self.calls = list()
@@ -630,28 +541,16 @@
                 return '__return__'
                 avar.append('__after_return__')
         acontextfact.calls.append(g(acontextfact))
-        """
-        ns = {}
-        exec(s, ns)
-        acontextfact = ns['acontextfact']
         assert acontextfact.calls == '__enter__ __body__ __exit__ 
__return__'.split()
         assert acontextfact.exit_params == (None, None, None)
 
     def test_with_as_keyword(self):
-        try:
+        with raises(SyntaxError):
             exec("with = 9")
-        except SyntaxError:
-            pass
-        else:
-            assert False, 'Assignment to with did not raise SyntaxError'
 
     def test_with_as_keyword_compound(self):
-        try:
+        with raises(SyntaxError):
             exec("from __future__ import generators, with_statement\nwith = 9")
-        except SyntaxError:
-            pass
-        else:
-            assert False, 'Assignment to with did not raise SyntaxError'
 
     def test_missing_as_SyntaxError(self):
         snippets = [
@@ -662,21 +561,10 @@
     pass
 """]
         for snippet in snippets:
-            try:
+            with raises(SyntaxError):
                 exec(snippet)
-            except SyntaxError:
-                pass
-            else:
-                assert False, "%s: did not raise SyntaxError" % snippet
 
 
-    def test_with_propagate_compileflag(self):
-        s = """
-if 1:
-        compile('''with x:
-        pass''', '', 'exec')
-        """
-        exec(s)
 
 class AppTestFunctionAnnotations:
 
@@ -707,7 +595,6 @@
                 pass
         f1()
         """
-
 class AppTestSyntaxError:
 
     def test_tokenizer_error_location(self):
@@ -752,7 +639,8 @@
 # -*- coding: uft-8 -*-
 pass
 """
-        raises(SyntaxError, exec, program)
+        with raises(SyntaxError):
+            exec(program)
         '''
 
     def test_exception_target_in_nested_scope(self):
@@ -798,24 +686,3 @@
             raise AssertionError("should have raised")
         """
 
-
-if __name__ == '__main__':
-    # only to check on top of CPython (you need 2.4)
-    from py.test import raises
-    for s in VALID:
-        try:
-            compile(s, '?', 'exec')
-        except Exception as e:
-            print '-'*20, 'FAILED TO COMPILE:', '-'*20
-            print s
-            print '%s: %s' % (e.__class__, e)
-            print '-'*60
-    for s in INVALID:
-        try:
-            raises(SyntaxError, compile, s, '?', 'exec')
-        except Exception as e:
-            print '-'*20, 'UNEXPECTEDLY COMPILED:', '-'*20
-            print s
-            print '%s: %s' % (e.__class__, e)
-            print '-'*60
-
diff --git a/pypy/interpreter/test/test_unicodehelper.py 
b/pypy/interpreter/test/test_unicodehelper.py
--- a/pypy/interpreter/test/test_unicodehelper.py
+++ b/pypy/interpreter/test/test_unicodehelper.py
@@ -1,7 +1,7 @@
 import pytest
 
 from pypy.interpreter.unicodehelper import (
-    utf8_encode_utf_8, decode_utf8sp,
+    utf8_encode_utf_8, decode_utf8sp, ErrorHandlerError
 )
 
 
@@ -21,7 +21,11 @@
     called with a start and stop position of the full surrogate
     pair (new behavior in python3.6)
     """
-    u = u"\udc80\ud800\udfff"
+    #               /--surrogate pair--\
+    #    \udc80      \ud800      \udfff
+    b = "\xed\xb2\x80\xed\xa0\x80\xed\xbf\xbf"
+
+    calls = []
 
     def errorhandler(errors, encoding, msg, s, start, end):
         """
@@ -32,31 +36,23 @@
         2. the second time, the characters will be 0xD800 and 0xDFFF, since
            that is a valid surrogate pair.
         """
-        assert s[start:end] in [u'\udc80', u'\uD800\uDFFF']
-        return '', end, 'b'
+        calls.append(s.decode("utf-8")[start:end])
+        return 'abc', end, 'b'
 
-    utf8_encode_utf_8(
-        u, 'strict',
+    res = utf8_encode_utf_8(
+        b, 'strict',
         errorhandler=errorhandler,
         allow_surrogates=False
     )
+    assert res == "abcabc"
+    assert calls == [u'\udc80', u'\uD800\uDFFF']
 
 def test_bad_error_handler():
-    u = u"\udc80\ud800\udfff"
+    b = u"\udc80\ud800\udfff".encode("utf-8")
+    def errorhandler(errors, encoding, msg, s, start, end):
+        return '', start, 'b' # returned index is too small
 
-    def errorhandler(errors, encoding, msg, s, start, end):
-        """
-        This handler will be called twice, so asserting both times:
-
-        1. the first time, 0xDC80 will be handled as a single surrogate,
-           since it is a standalone character and an invalid surrogate.
-        2. the second time, the characters will be 0xD800 and 0xDFFF, since
-           that is a valid surrogate pair.
-        """
-        assert s[start:end] in [u'\udc80', u'\uD800\uDFFF']
-        return '', start, 'b'
-
-    assert pytest.raises(Exception, utf8_encode_utf_8, u, 'strict',
+    pytest.raises(ErrorHandlerError, utf8_encode_utf_8, b, 'strict',
                   errorhandler=errorhandler, allow_surrogates=False)
 
 def test_decode_utf8sp():
diff --git a/pypy/interpreter/unicodehelper.py 
b/pypy/interpreter/unicodehelper.py
--- a/pypy/interpreter/unicodehelper.py
+++ b/pypy/interpreter/unicodehelper.py
@@ -31,7 +31,7 @@
     # Fast version of the "strict" errors handler.
     def raise_unicode_exception_encode(errors, encoding, msg, utf8,
                                        startingpos, endingpos):
-        u_len = rutf8.get_utf8_length(utf8)
+        u_len = rutf8.codepoints_in_utf8(utf8)
         raise OperationError(space.w_UnicodeEncodeError,
                              space.newtuple([space.newtext(encoding),
                                              space.newutf8(utf8, u_len),
@@ -120,12 +120,6 @@
     return encode_object(space, w_data, encoding, errors)
 
 
-def _has_surrogate(u):
-    for c in u:
-        if 0xD800 <= ord(c) <= 0xDFFF:
-            return True
-    return False
-
 # These functions take and return unwrapped rpython strings
 def decode_unicode_escape(space, string):
     from pypy.module._codecs import interp_codecs
@@ -221,23 +215,35 @@
     size = len(s)
     if size == 0:
         return ''
+
+    # two fast paths
+    if allow_surrogates:
+        # already valid utf-8 with surrogates, surrogates are allowed, so just
+        # return
+        return s
+    if not rutf8.has_surrogates(s):
+        # already valid utf-8 and doesn't contain surrogates, so we don't need
+        # to do anything
+        return s
+    # annoying slow path
+    return _utf8_encode_utf_8_deal_with_surrogates(s, errors, errorhandler)
+
+def _utf8_encode_utf_8_deal_with_surrogates(s, errors, errorhandler):
     pos = 0
     upos = 0
+    size = len(s)
     result = StringBuilder(size)
     while pos < size:
         try:
-            lgt = rutf8.check_utf8(s, allow_surrogates=allow_surrogates, 
start=pos)
-            if pos == 0:
-                # fast path
-                return s
-            for ch in s[pos:]:
-                result.append(ch)
+            rutf8.check_utf8(s, allow_surrogates=False, start=pos)
+            # otherwise the fast path above would have triggered
+            assert pos != 0
+            result.append_slice(s, pos, len(s))
             break
         except rutf8.CheckError as e:
             end = e.pos
             assert end >= 0
-            for ch in s[pos:end]:
-                result.append(ch)
+            result.append_slice(s, pos, end)
             upos += rutf8.codepoints_in_utf8(s, start=pos, end=end)
             pos = end
             # Try to get collect surrogates in one pass
@@ -254,11 +260,13 @@
             res, newindex, rettype = errorhandler(errors, 'utf-8',
                         'surrogates not allowed', s, upos, upos + delta)
             if rettype == 'u':
-                for cp in rutf8.Utf8StringIterator(res):
-                    result.append(chr(cp))
-            else:
-                for ch in res:
-                    result.append(ch)
+                try:
+                    rutf8.check_ascii(res)
+                except rutf8.CheckError:
+                    # this is a weird behaviour of CPython, but it's what 
happens
+                    errorhandler("strict", 'utf-8', 'surrogates not allowed', 
s, upos, upos + delta)
+                    assert 0, "unreachable"
+            result.append(res)
             if newindex <= upos:
                 raise ErrorHandlerError(newindex, upos)
             upos = newindex
diff --git a/pypy/module/__builtin__/compiling.py 
b/pypy/module/__builtin__/compiling.py
--- a/pypy/module/__builtin__/compiling.py
+++ b/pypy/module/__builtin__/compiling.py
@@ -133,11 +133,11 @@
     if not space.ismapping_w(w_namespace):
         if isclass:
             raise oefmt(space.w_TypeError,
-                "%N.__prepare__ must return a mapping, not %T",
+                "%N.__prepare__() must return a mapping, not %T",
                 w_meta, w_namespace)
         else:
             raise oefmt(space.w_TypeError,
-                "<metaclass>.__prepare__ must return a mapping, not %T",
+                "<metaclass>.__prepare__() must return a mapping, not %T",
                 w_namespace)
 
     code = w_func.getcode()
diff --git a/pypy/module/__builtin__/test/apptest_compile.py 
b/pypy/module/__builtin__/test/apptest_compile.py
--- a/pypy/module/__builtin__/test/apptest_compile.py
+++ b/pypy/module/__builtin__/test/apptest_compile.py
@@ -179,3 +179,20 @@
         assert 'module_doc' not in marshalled
         assert 'func_doc' not in marshalled
         assert 'class_doc' not in marshalled
+
+def test_build_class():
+    """Test error message bad __prepare__"""
+
+    class BadMeta(type):
+        @classmethod
+        def __prepare__(*args):
+            return None
+
+    def func():
+        class Foo(metaclass=BadMeta):
+            pass
+
+    excinfo = raises(TypeError, func)
+    assert str(excinfo.value) == (
+        r"BadMeta.__prepare__() must return a mapping, not NoneType"
+    )
diff --git a/pypy/module/_cffi_backend/test/test_recompiler.py 
b/pypy/module/_cffi_backend/test/test_recompiler.py
--- a/pypy/module/_cffi_backend/test/test_recompiler.py
+++ b/pypy/module/_cffi_backend/test/test_recompiler.py
@@ -75,8 +75,12 @@
 
     args_w = [space.wrap(module_name), space.wrap(so_file)]
     w_res = space.appexec(args_w, """(modulename, filename):
-        import imp
-        mod = imp.load_dynamic(modulename, filename)
+        import _imp
+        class Spec: pass
+        spec = Spec()
+        spec.name = modulename
+        spec.origin = filename
+        mod = _imp.create_dynamic(spec)
         assert mod.__name__ == modulename
         return (mod.ffi, mod.lib)
     """)
diff --git a/pypy/module/_codecs/interp_codecs.py 
b/pypy/module/_codecs/interp_codecs.py
--- a/pypy/module/_codecs/interp_codecs.py
+++ b/pypy/module/_codecs/interp_codecs.py
@@ -715,6 +715,8 @@
 @unwrap_spec(errors='text_or_none')
 def utf_8_encode(space, w_obj, errors="strict"):
     utf8, lgt = space.utf8_len_w(w_obj)
+    if lgt == len(utf8): # ascii
+        return space.newtuple([space.newbytes(utf8), space.newint(lgt)])
     if errors is None:
         errors = 'strict'
     state = space.fromcache(CodecState)
diff --git a/pypy/module/_codecs/test/test_codecs.py 
b/pypy/module/_codecs/test/test_codecs.py
--- a/pypy/module/_codecs/test/test_codecs.py
+++ b/pypy/module/_codecs/test/test_codecs.py
@@ -1041,6 +1041,14 @@
         # CPython raises OverflowError here
         raises((IndexError, OverflowError), b'apple\x92ham\x93spam'.decode, 
'utf-8', errors)
 
+    def test_badhandler_returns_unicode(self):
+        import codecs
+        import sys
+        errors = 'test.badhandler_unicode'
+        codecs.register_error(errors, lambda x: (chr(100000), x.end))
+        # CPython raises OverflowError here
+        raises(UnicodeEncodeError, u'\udc80\ud800\udfff'.encode, 'utf-8', 
errors)
+
     def test_unicode_internal(self):
         import codecs
         import sys
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
@@ -56,7 +56,7 @@
         # `__IOBase_closed` and call flush() by itself, but it is redundant
         # with whatever behaviour a non-trivial derived class will implement.
         self.space = space
-        self.w_dict = space.newdict()
+        self.w_dict = space.newdict(instance=True)
         self.__IOBase_closed = False
         if add_to_autoflusher:
             get_autoflusher(space).add(self)
diff --git a/pypy/module/_io/interp_stringio.py 
b/pypy/module/_io/interp_stringio.py
--- a/pypy/module/_io/interp_stringio.py
+++ b/pypy/module/_io/interp_stringio.py
@@ -1,4 +1,4 @@
-from rpython.rlib.rutf8 import get_utf8_length, next_codepoint_pos
+from rpython.rlib.rutf8 import codepoints_in_utf8, next_codepoint_pos
 
 from pypy.interpreter.error import OperationError, oefmt
 from pypy.interpreter.typedef import (
@@ -98,7 +98,7 @@
         return result
 
     def write(self, string):
-        length = get_utf8_length(string)
+        length = codepoints_in_utf8(string)
         if self.pos + length > len(self.data):
             self.resize(self.pos + length)
         pos = 0
@@ -173,7 +173,7 @@
         if readnl is None:
             w_readnl = space.w_None
         else:
-            w_readnl = space.str(space.newutf8(readnl, 
get_utf8_length(readnl)))  # YYY
+            w_readnl = space.str(space.newutf8(readnl, 
codepoints_in_utf8(readnl)))  # YYY
         return space.newtuple([
             w_initialval, w_readnl, space.newint(self.buf.pos), w_dict
         ])
@@ -239,7 +239,7 @@
             w_decoded = space.call_method(
                 w_decoded, "replace",
                 space.newtext("\n"),
-                space.newutf8(writenl, get_utf8_length(writenl)),
+                space.newutf8(writenl, codepoints_in_utf8(writenl)),
             )
         string = space.utf8_w(w_decoded)
         if string:
@@ -251,7 +251,7 @@
         self._check_closed(space)
         size = convert_size(space, w_size)
         v = self.buf.read(size)
-        lgt = get_utf8_length(v)
+        lgt = codepoints_in_utf8(v)
         return space.newutf8(v, lgt)
 
     def readline_w(self, space, w_limit=None):
@@ -266,7 +266,7 @@
             else:
                 newline = self.readnl
             result = self.buf.readline(newline, limit)
-        resultlen = get_utf8_length(result)
+        resultlen = codepoints_in_utf8(result)
         return space.newutf8(result, resultlen)
 
 
@@ -305,7 +305,7 @@
     def getvalue_w(self, space):
         self._check_closed(space)
         v = self.buf.getvalue()
-        lgt = get_utf8_length(v)
+        lgt = codepoints_in_utf8(v)
         return space.newutf8(v, lgt)
 
     def readable_w(self, space):
diff --git a/pypy/module/_io/interp_textio.py b/pypy/module/_io/interp_textio.py
--- a/pypy/module/_io/interp_textio.py
+++ b/pypy/module/_io/interp_textio.py
@@ -12,7 +12,7 @@
 from rpython.rlib.rbigint import rbigint
 from rpython.rlib.rstring import StringBuilder
 from rpython.rlib.rutf8 import (check_utf8, next_codepoint_pos,
-                                codepoints_in_utf8, get_utf8_length,
+                                codepoints_in_utf8, codepoints_in_utf8,
                                 Utf8StringBuilder)
 
 
@@ -308,13 +308,18 @@
 
 
 class DecodeBuffer(object):
-    def __init__(self, text=None):
+    def __init__(self, text=None, ulen=-1):
+        # self.text is a valid utf-8 string
+        if text is not None:
+            assert ulen >= 0
         self.text = text
         self.pos = 0
         self.upos = 0
+        self.ulen = ulen
 
     def set(self, space, w_decoded):
         check_decoded(space, w_decoded)
+        self.ulen = space.len_w(w_decoded)
         self.text = space.utf8_w(w_decoded)
         self.pos = 0
         self.upos = 0
@@ -323,12 +328,14 @@
         self.text = None
         self.pos = 0
         self.upos = 0
+        self.ulen = -1
 
     def get_chars(self, size):
+        """ returns a tuple (utf8, lgt) """
         if self.text is None or size == 0:
-            return ""
+            return "", 0
 
-        lgt = codepoints_in_utf8(self.text)
+        lgt = self.ulen
         available = lgt - self.upos
         if size < 0 or size > available:
             size = available
@@ -337,7 +344,7 @@
         if self.pos > 0 or size < available:
             start = self.pos
             pos = start
-            for  i in range(size):
+            for i in range(size):
                 pos = next_codepoint_pos(self.text, pos)
                 self.upos += 1
             assert start >= 0
@@ -348,8 +355,9 @@
             chars = self.text
             self.pos = len(self.text)
             self.upos = lgt
+            size = lgt
 
-        return chars
+        return chars, size
 
     def has_data(self):
         return (self.text is not None and not self.exhausted())
@@ -386,22 +394,22 @@
             limit = sys.maxint
         scanned = 0
         while scanned < limit:
-            try:
-                ch = self.next_char()
-                scanned += 1
-            except StopIteration:
+            if self.exhausted():
                 return False
+            ch = self.text[self.pos]
+            self._advance_codepoint()
+            scanned += 1
             if ch == '\n':
                 return True
             if ch == '\r':
                 if scanned >= limit:
                     return False
-                try:
-                    ch = self.peek_char()
-                except StopIteration:
+                if self.exhausted():
+                    # don't split potential \r\n
                     return False
+                ch = self.text[self.pos]
                 if ch == '\n':
-                    self.next_char()
+                    self._advance_codepoint()
                     return True
                 else:
                     return True
@@ -412,39 +420,66 @@
             limit = sys.maxint
         scanned = 0
         while scanned < limit:
-            try:
-                ch = self.next_char()
-            except StopIteration:
+            if self.exhausted():
                 return False
+            ch = self.text[self.pos]
+            self._advance_codepoint()
             scanned += 1
             if ch == '\r':
                 if scanned >= limit:
                     return False
-                try:
-                    if self.peek_char() == '\n':
-                        self.next_char()
-                        return True
-                except StopIteration:
-                    # This is the tricky case: we found a \r right at the end
+                if self.exhausted():
+                    # This is the tricky case: we found a \r right at the end,
+                    # un-consume it
                     self.pos -= 1
                     self.upos -= 1
                     return False
+                if self.text[self.pos] == '\n':
+                    self._advance_codepoint()
+                    return True
         return False
 
     def find_char(self, marker, limit):
+        # only works for ascii markers!
+        assert 0 <= ord(marker) < 128
+        # ascii fast path
+        if self.ulen == len(self.text):
+            end = len(self.text)
+            if limit >= 0:
+                end = min(end, self.pos + limit)
+            pos = self.pos
+            assert pos >= 0
+            assert end >= 0
+            pos = self.text.find(marker, pos, end)
+            if pos >= 0:
+                self.pos = self.upos = pos + 1
+                return True
+            else:
+                self.pos = self.upos = end
+                return False
+
         if limit < 0:
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to