[Python-checkins] cpython: Close #11619: The parser and the import machinery do not encode Unicode

victor.stinner python-checkins at python.org
Mon Aug 26 22:33:52 CEST 2013


http://hg.python.org/cpython/rev/df2fdd42b375
changeset:   85417:df2fdd42b375
user:        Victor Stinner <victor.stinner at gmail.com>
date:        Mon Aug 26 22:28:21 2013 +0200
summary:
  Close #11619: The parser and the import machinery do not encode Unicode
filenames anymore on Windows.

files:
  Doc/c-api/exceptions.rst |   36 ++++++--
  Doc/c-api/veryhigh.rst   |   16 ++-
  Include/ast.h            |    5 +
  Include/compile.h        |   15 +++-
  Include/parsetok.h       |   42 ++++++++--
  Include/pyerrors.h       |    7 +
  Include/pythonrun.h      |   25 ++++++
  Include/symtable.h       |    6 +-
  Include/warnings.h       |    7 +
  Lib/test/test_import.py  |   10 ++-
  Misc/NEWS                |    3 +
  Modules/parsermodule.c   |   49 ++++++++----
  Modules/symtablemodule.c |   10 +-
  Parser/parsetok.c        |   79 ++++++++++++++++---
  Python/_warnings.c       |   31 +++++--
  Python/ast.c             |   39 +++++----
  Python/bltinmodule.c     |   14 +--
  Python/compile.c         |   57 +++++++++-----
  Python/errors.c          |   56 ++++++++++---
  Python/future.c          |   27 +++++-
  Python/pythonrun.c       |  104 +++++++++++++++++++++-----
  Python/symtable.c        |   55 ++++++++++---
  22 files changed, 516 insertions(+), 177 deletions(-)


diff --git a/Doc/c-api/exceptions.rst b/Doc/c-api/exceptions.rst
--- a/Doc/c-api/exceptions.rst
+++ b/Doc/c-api/exceptions.rst
@@ -235,7 +235,7 @@
 
    Similar to :c:func:`PyErr_SetFromErrnoWithFilenameObject`, but the filename
    is given as a C string.  *filename* is decoded from the filesystem encoding
-   (:func:`sys.getfilesystemencoding`).
+   (:func:`os.fsdecode`).
 
 
 .. c:function:: PyObject* PyErr_SetFromWindowsErr(int ierr)
@@ -267,7 +267,7 @@
 
    Similar to :c:func:`PyErr_SetFromWindowsErrWithFilenameObject`, but the
    filename is given as a C string.  *filename* is decoded from the filesystem
-   encoding (:func:`sys.getfilesystemencoding`).  Availability: Windows.
+   encoding (:func:`os.fsdecode`).  Availability: Windows.
 
 
 .. c:function:: PyObject* PyErr_SetExcFromWindowsErrWithFilenameObject(PyObject *type, int ierr, PyObject *filename)
@@ -293,20 +293,27 @@
    .. versionadded:: 3.3
 
 
-.. c:function:: void PyErr_SyntaxLocationEx(char *filename, int lineno, int col_offset)
+.. c:function:: void PyErr_SyntaxLocationObject(PyObject *filename, int lineno, int col_offset)
 
    Set file, line, and offset information for the current exception.  If the
    current exception is not a :exc:`SyntaxError`, then it sets additional
    attributes, which make the exception printing subsystem think the exception
-   is a :exc:`SyntaxError`. *filename* is decoded from the filesystem encoding
-   (:func:`sys.getfilesystemencoding`).
+   is a :exc:`SyntaxError`.
 
-   .. versionadded:: 3.2
+.. versionadded:: 3.4
+
+
+.. c:function:: void PyErr_SyntaxLocationEx(char *filename, int lineno, int col_offset)
+
+   Like :c:func:`PyErr_SyntaxLocationObject`, but *filename* is a byte string
+   decoded from the filesystem encoding (:func:`os.fsdecode`).
+
+.. versionadded:: 3.2
 
 
 .. c:function:: void PyErr_SyntaxLocation(char *filename, int lineno)
 
-   Like :c:func:`PyErr_SyntaxLocationExc`, but the col_offset parameter is
+   Like :c:func:`PyErr_SyntaxLocationEx`, but the col_offset parameter is
    omitted.
 
 
@@ -355,15 +362,22 @@
    documentation.  There is no C API for warning control.
 
 
-.. c:function:: int PyErr_WarnExplicit(PyObject *category, const char *message, const char *filename, int lineno, const char *module, PyObject *registry)
+.. c:function:: int PyErr_WarnExplicitObject(PyObject *category, PyObject *message, PyObject *filename, int lineno, PyObject *module, PyObject *registry)
 
    Issue a warning message with explicit control over all warning attributes.  This
    is a straightforward wrapper around the Python function
    :func:`warnings.warn_explicit`, see there for more information.  The *module*
    and *registry* arguments may be set to *NULL* to get the default effect
-   described there. *message* and *module* are UTF-8 encoded strings,
-   *filename* is decoded from the filesystem encoding
-   (:func:`sys.getfilesystemencoding`).
+   described there.
+
+   .. versionadded:: 3.4
+
+
+.. c:function:: int PyErr_WarnExplicit(PyObject *category, const char *message, const char *filename, int lineno, const char *module, PyObject *registry)
+
+   Similar to :c:func:`PyErr_WarnExplicitObject` except that *message* and
+   *module* are UTF-8 encoded strings, and *filename* is decoded from the
+   filesystem encoding (:func:`os.fsdecode`).
 
 
 .. c:function:: int PyErr_WarnFormat(PyObject *category, Py_ssize_t stack_level, const char *format, ...)
diff --git a/Doc/c-api/veryhigh.rst b/Doc/c-api/veryhigh.rst
--- a/Doc/c-api/veryhigh.rst
+++ b/Doc/c-api/veryhigh.rst
@@ -258,16 +258,15 @@
    *optimize* set to ``-1``.
 
 
-.. c:function:: PyObject* Py_CompileStringExFlags(const char *str, const char *filename, int start, PyCompilerFlags *flags, int optimize)
+.. c:function:: PyObject* Py_CompileStringObject(const char *str, PyObject *filename, int start, PyCompilerFlags *flags, int optimize)
 
    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 be :const:`Py_eval_input`,
    :const:`Py_file_input`, or :const:`Py_single_input`.  The filename specified by
    *filename* is used to construct the code object and may appear in tracebacks or
-   :exc:`SyntaxError` exception messages, it is decoded from the filesystem
-   encoding (:func:`sys.getfilesystemencoding`).  This returns *NULL* if the
-   code cannot be parsed or compiled.
+   :exc:`SyntaxError` exception messages.  This returns *NULL* if the code
+   cannot be parsed or compiled.
 
    The integer *optimize* specifies the optimization level of the compiler; a
    value of ``-1`` selects the optimization level of the interpreter as given by
@@ -275,9 +274,16 @@
    ``__debug__`` is true), ``1`` (asserts are removed, ``__debug__`` is false)
    or ``2`` (docstrings are removed too).
 
+   .. versionadded:: 3.4
+
+
+.. c:function:: PyObject* Py_CompileStringExFlags(const char *str, const char *filename, int start, PyCompilerFlags *flags, int optimize)
+
+   Like :c:func:`Py_CompileStringExFlags`, but *filename* is a byte string
+   decoded from the filesystem encoding (:func:`os.fsdecode`).
+
    .. versionadded:: 3.2
 
-
 .. c:function:: PyObject* PyEval_EvalCode(PyObject *co, PyObject *globals, PyObject *locals)
 
    This is a simplified interface to :c:func:`PyEval_EvalCodeEx`, with just
diff --git a/Include/ast.h b/Include/ast.h
--- a/Include/ast.h
+++ b/Include/ast.h
@@ -10,6 +10,11 @@
     PyCompilerFlags *flags,
     const char *filename,       /* decoded from the filesystem encoding */
     PyArena *arena);
+PyAPI_FUNC(mod_ty) PyAST_FromNodeObject(
+    const node *n,
+    PyCompilerFlags *flags,
+    PyObject *filename,
+    PyArena *arena);
 
 #ifdef __cplusplus
 }
diff --git a/Include/compile.h b/Include/compile.h
--- a/Include/compile.h
+++ b/Include/compile.h
@@ -36,7 +36,20 @@
     PyCompilerFlags *flags,
     int optimize,
     PyArena *arena);
-PyAPI_FUNC(PyFutureFeatures *) PyFuture_FromAST(struct _mod *, const char *);
+PyAPI_FUNC(PyCodeObject *) PyAST_CompileObject(
+    struct _mod *mod,
+    PyObject *filename,
+    PyCompilerFlags *flags,
+    int optimize,
+    PyArena *arena);
+PyAPI_FUNC(PyFutureFeatures *) PyFuture_FromAST(
+    struct _mod * mod,
+    const char *filename        /* decoded from the filesystem encoding */
+    );
+PyAPI_FUNC(PyFutureFeatures *) PyFuture_FromASTObject(
+    struct _mod * mod,
+    PyObject *filename
+    );
 
 /* _Py_Mangle is defined in compile.c */
 PyAPI_FUNC(PyObject*) _Py_Mangle(PyObject *p, PyObject *name);
diff --git a/Include/parsetok.h b/Include/parsetok.h
--- a/Include/parsetok.h
+++ b/Include/parsetok.h
@@ -42,10 +42,16 @@
 
 PyAPI_FUNC(node *) PyParser_ParseStringFlags(const char *, grammar *, int,
                                               perrdetail *, int);
-PyAPI_FUNC(node *) PyParser_ParseFileFlags(FILE *, const char *,
-					   const char*, grammar *,
-						 int, char *, char *,
-						 perrdetail *, int);
+PyAPI_FUNC(node *) PyParser_ParseFileFlags(
+    FILE *fp,
+    const char *filename,       /* decoded from the filesystem encoding */
+    const char *enc,
+    grammar *g,
+    int start,
+    char *ps1,
+    char *ps2,
+    perrdetail *err_ret,
+    int flags);
 PyAPI_FUNC(node *) PyParser_ParseFileFlagsEx(
     FILE *fp,
     const char *filename,       /* decoded from the filesystem encoding */
@@ -56,11 +62,24 @@
     char *ps2,
     perrdetail *err_ret,
     int *flags);
+PyAPI_FUNC(node *) PyParser_ParseFileObject(
+    FILE *fp,
+    PyObject *filename,
+    const char *enc,
+    grammar *g,
+    int start,
+    char *ps1,
+    char *ps2,
+    perrdetail *err_ret,
+    int *flags);
 
-PyAPI_FUNC(node *) PyParser_ParseStringFlagsFilename(const char *,
-					      const char *,
-					      grammar *, int,
-                                              perrdetail *, int);
+PyAPI_FUNC(node *) PyParser_ParseStringFlagsFilename(
+    const char *s,
+    const char *filename,       /* decoded from the filesystem encoding */
+    grammar *g,
+    int start,
+    perrdetail *err_ret,
+    int flags);
 PyAPI_FUNC(node *) PyParser_ParseStringFlagsFilenameEx(
     const char *s,
     const char *filename,       /* decoded from the filesystem encoding */
@@ -68,6 +87,13 @@
     int start,
     perrdetail *err_ret,
     int *flags);
+PyAPI_FUNC(node *) PyParser_ParseStringObject(
+    const char *s,
+    PyObject *filename,
+    grammar *g,
+    int start,
+    perrdetail *err_ret,
+    int *flags);
 
 /* Note that the following functions are defined in pythonrun.c,
    not in parsetok.c */
diff --git a/Include/pyerrors.h b/Include/pyerrors.h
--- a/Include/pyerrors.h
+++ b/Include/pyerrors.h
@@ -301,9 +301,16 @@
     const char *filename,       /* decoded from the filesystem encoding */
     int lineno,
     int col_offset);
+PyAPI_FUNC(void) PyErr_SyntaxLocationObject(
+    PyObject *filename,
+    int lineno,
+    int col_offset);
 PyAPI_FUNC(PyObject *) PyErr_ProgramText(
     const char *filename,       /* decoded from the filesystem encoding */
     int lineno);
+PyAPI_FUNC(PyObject *) PyErr_ProgramTextObject(
+    PyObject *filename,
+    int lineno);
 
 /* The following functions are used to create and modify unicode
    exceptions from C */
diff --git a/Include/pythonrun.h b/Include/pythonrun.h
--- a/Include/pythonrun.h
+++ b/Include/pythonrun.h
@@ -66,6 +66,12 @@
     int start,
     PyCompilerFlags *flags,
     PyArena *arena);
+PyAPI_FUNC(struct _mod *) PyParser_ASTFromStringObject(
+    const char *s,
+    PyObject *filename,
+    int start,
+    PyCompilerFlags *flags,
+    PyArena *arena);
 PyAPI_FUNC(struct _mod *) PyParser_ASTFromFile(
     FILE *fp,
     const char *filename,       /* decoded from the filesystem encoding */
@@ -76,6 +82,16 @@
     PyCompilerFlags *flags,
     int *errcode,
     PyArena *arena);
+PyAPI_FUNC(struct _mod *) PyParser_ASTFromFileObject(
+    FILE *fp,
+    PyObject *filename,
+    const char* enc,
+    int start,
+    char *ps1,
+    char *ps2,
+    PyCompilerFlags *flags,
+    int *errcode,
+    PyArena *arena);
 #endif
 
 #ifndef PyParser_SimpleParseString
@@ -117,11 +133,20 @@
     int start,
     PyCompilerFlags *flags,
     int optimize);
+PyAPI_FUNC(PyObject *) Py_CompileStringObject(
+    const char *str,
+    PyObject *filename, int start,
+    PyCompilerFlags *flags,
+    int optimize);
 #endif
 PyAPI_FUNC(struct symtable *) Py_SymtableString(
     const char *str,
     const char *filename,       /* decoded from the filesystem encoding */
     int start);
+PyAPI_FUNC(struct symtable *) Py_SymtableStringObject(
+    const char *str,
+    PyObject *filename,
+    int start);
 
 PyAPI_FUNC(void) PyErr_Print(void);
 PyAPI_FUNC(void) PyErr_PrintEx(int);
diff --git a/Include/symtable.h b/Include/symtable.h
--- a/Include/symtable.h
+++ b/Include/symtable.h
@@ -16,7 +16,7 @@
 struct _symtable_entry;
 
 struct symtable {
-    const char *st_filename;        /* name of file being compiled,
+    PyObject *st_filename;          /* name of file being compiled,
                                        decoded from the filesystem encoding */
     struct _symtable_entry *st_cur; /* current symbol table entry */
     struct _symtable_entry *st_top; /* symbol table entry for module */
@@ -74,6 +74,10 @@
     mod_ty mod,
     const char *filename,       /* decoded from the filesystem encoding */
     PyFutureFeatures *future);
+PyAPI_FUNC(struct symtable *) PySymtable_BuildObject(
+    mod_ty mod,
+    PyObject *filename,
+    PyFutureFeatures *future);
 PyAPI_FUNC(PySTEntryObject *) PySymtable_Lookup(struct symtable *, void *);
 
 PyAPI_FUNC(void) PySymtable_Free(struct symtable *);
diff --git a/Include/warnings.h b/Include/warnings.h
--- a/Include/warnings.h
+++ b/Include/warnings.h
@@ -17,6 +17,13 @@
     Py_ssize_t stack_level,
     const char *format,         /* ASCII-encoded string  */
     ...);
+PyAPI_FUNC(int) PyErr_WarnExplicitObject(
+    PyObject *category,
+    PyObject *message,
+    PyObject *filename,
+    int lineno,
+    PyObject *module,
+    PyObject *registry);
 PyAPI_FUNC(int) PyErr_WarnExplicit(
     PyObject *category,
     const char *message,        /* UTF-8 encoded string */
diff --git a/Lib/test/test_import.py b/Lib/test/test_import.py
--- a/Lib/test/test_import.py
+++ b/Lib/test/test_import.py
@@ -22,7 +22,7 @@
 from test.support import (
     EnvironmentVarGuard, TESTFN, check_warnings, forget, is_jython,
     make_legacy_pyc, rmtree, run_unittest, swap_attr, swap_item, temp_umask,
-    unlink, unload, create_empty_file, cpython_only)
+    unlink, unload, create_empty_file, cpython_only, TESTFN_UNENCODABLE)
 from test import script_helper
 
 
@@ -1055,6 +1055,14 @@
         finally:
             importlib.SourceLoader.load_module = old_load_module
 
+    @unittest.skipUnless(TESTFN_UNENCODABLE, 'need TESTFN_UNENCODABLE')
+    def test_unencodable_filename(self):
+        # Issue #11619: The Python parser and the import machinery must not
+        # encode filenames, especially on Windows
+        pyname = script_helper.make_script('', TESTFN_UNENCODABLE, 'pass')
+        name = pyname[:-3]
+        script_helper.assert_python_ok("-c", "mod = __import__(%a)" % name)
+
 
 if __name__ == '__main__':
     # Test needs to be a package, so we can do relative imports.
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,9 @@
 Core and Builtins
 -----------------
 
+- Issue #11619: The parser and the import machinery do not encode Unicode
+  filenames anymore on Windows.
+
 - Issue #18808: Non-daemon threads are now automatically joined when
   a sub-interpreter is shutdown (it would previously dump a fatal error).
 
diff --git a/Modules/parsermodule.c b/Modules/parsermodule.c
--- a/Modules/parsermodule.c
+++ b/Modules/parsermodule.c
@@ -477,33 +477,46 @@
 static PyObject*
 parser_compilest(PyST_Object *self, PyObject *args, PyObject *kw)
 {
-    PyObject*     res = 0;
-    PyArena*      arena;
+    PyObject*     res = NULL;
+    PyArena*      arena = NULL;
     mod_ty        mod;
-    char*         str = "<syntax-tree>";
+    PyObject*     filename = NULL;
     int ok;
 
     static char *keywords[] = {"st", "filename", NULL};
 
     if (self == NULL || PyModule_Check(self))
-        ok = PyArg_ParseTupleAndKeywords(args, kw, "O!|s:compilest", keywords,
-                                         &PyST_Type, &self, &str);
+        ok = PyArg_ParseTupleAndKeywords(args, kw, "O!|O&:compilest", keywords,
+                                         &PyST_Type, &self,
+                                         PyUnicode_FSDecoder, &filename);
     else
-        ok = PyArg_ParseTupleAndKeywords(args, kw, "|s:compile", &keywords[1],
-                                         &str);
-
-    if (ok) {
-        arena = PyArena_New();
-        if (arena) {
-           mod = PyAST_FromNode(self->st_node, &(self->st_flags), str, arena);
-           if (mod) {
-               res = (PyObject *)PyAST_Compile(mod, str, &(self->st_flags), arena);
-           }
-           PyArena_Free(arena);
-        }
+        ok = PyArg_ParseTupleAndKeywords(args, kw, "|O&:compile", &keywords[1],
+                                         PyUnicode_FSDecoder, &filename);
+    if (!ok)
+        goto error;
+
+    if (filename == NULL) {
+        filename = PyUnicode_FromString("<syntax-tree>");
+        if (filename == NULL)
+            goto error;
     }
 
-    return (res);
+    arena = PyArena_New();
+    if (!arena)
+        goto error;
+
+    mod = PyAST_FromNodeObject(self->st_node, &self->st_flags,
+                               filename, arena);
+    if (!mod)
+        goto error;
+
+    res = (PyObject *)PyAST_CompileObject(mod, filename,
+                                          &self->st_flags, -1, arena);
+error:
+    Py_XDECREF(filename);
+    if (arena != NULL)
+        PyArena_Free(arena);
+    return res;
 }
 
 
diff --git a/Modules/symtablemodule.c b/Modules/symtablemodule.c
--- a/Modules/symtablemodule.c
+++ b/Modules/symtablemodule.c
@@ -11,12 +11,12 @@
     PyObject *t;
 
     char *str;
-    char *filename;
+    PyObject *filename;
     char *startstr;
     int start;
 
-    if (!PyArg_ParseTuple(args, "sss:symtable", &str, &filename,
-                          &startstr))
+    if (!PyArg_ParseTuple(args, "sO&s:symtable",
+                          &str, PyUnicode_FSDecoder, &filename, &startstr))
         return NULL;
     if (strcmp(startstr, "exec") == 0)
         start = Py_file_input;
@@ -27,9 +27,11 @@
     else {
         PyErr_SetString(PyExc_ValueError,
            "symtable() arg 3 must be 'exec' or 'eval' or 'single'");
+        Py_DECREF(filename);
         return NULL;
     }
-    st = Py_SymtableString(str, filename, start);
+    st = Py_SymtableStringObject(str, filename, start);
+    Py_DECREF(filename);
     if (st == NULL)
         return NULL;
     t = st->st_blocks;
diff --git a/Parser/parsetok.c b/Parser/parsetok.c
--- a/Parser/parsetok.c
+++ b/Parser/parsetok.c
@@ -13,7 +13,7 @@
 
 /* Forward */
 static node *parsetok(struct tok_state *, grammar *, int, perrdetail *, int *);
-static int initerr(perrdetail *err_ret, const char* filename);
+static int initerr(perrdetail *err_ret, PyObject * filename);
 
 /* Parse input coming from a string.  Return error code, print some errors. */
 node *
@@ -41,9 +41,9 @@
 }
 
 node *
-PyParser_ParseStringFlagsFilenameEx(const char *s, const char *filename,
-                          grammar *g, int start,
-                          perrdetail *err_ret, int *flags)
+PyParser_ParseStringObject(const char *s, PyObject *filename,
+                           grammar *g, int start,
+                           perrdetail *err_ret, int *flags)
 {
     struct tok_state *tok;
     int exec_input = start == file_input;
@@ -67,6 +67,29 @@
     return parsetok(tok, g, start, err_ret, flags);
 }
 
+node *
+PyParser_ParseStringFlagsFilenameEx(const char *s, const char *filename_str,
+                          grammar *g, int start,
+                          perrdetail *err_ret, int *flags)
+{
+    node *n;
+    PyObject *filename = NULL;
+#ifndef PGEN
+    if (filename_str != NULL) {
+        filename = PyUnicode_DecodeFSDefault(filename_str);
+        if (filename == NULL) {
+            err_ret->error = E_ERROR;
+            return NULL;
+        }
+    }
+#endif
+    n = PyParser_ParseStringObject(s, filename, g, start, err_ret, flags);
+#ifndef PGEN
+    Py_XDECREF(filename);
+#endif
+    return n;
+}
+
 /* Parse input coming from a file.  Return error code, print some errors. */
 
 node *
@@ -88,9 +111,10 @@
 }
 
 node *
-PyParser_ParseFileFlagsEx(FILE *fp, const char *filename,
-                          const char *enc, grammar *g, int start,
-                          char *ps1, char *ps2, perrdetail *err_ret, int *flags)
+PyParser_ParseFileObject(FILE *fp, PyObject *filename,
+                         const char *enc, grammar *g, int start,
+                         char *ps1, char *ps2, perrdetail *err_ret,
+                         int *flags)
 {
     struct tok_state *tok;
 
@@ -108,6 +132,30 @@
     return parsetok(tok, g, start, err_ret, flags);
 }
 
+node *
+PyParser_ParseFileFlagsEx(FILE *fp, const char *filename,
+                          const char *enc, grammar *g, int start,
+                          char *ps1, char *ps2, perrdetail *err_ret, int *flags)
+{
+    node *n;
+    PyObject *fileobj = NULL;
+#ifndef PGEN
+    if (filename != NULL) {
+        fileobj = PyUnicode_DecodeFSDefault(filename);
+        if (fileobj == NULL) {
+            err_ret->error = E_ERROR;
+            return NULL;
+        }
+    }
+#endif
+    n = PyParser_ParseFileObject(fp, fileobj, enc, g,
+                                 start, ps1, ps2, err_ret, flags);
+#ifndef PGEN
+    Py_XDECREF(fileobj);
+#endif
+    return n;
+}
+
 #ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
 #if 0
 static char with_msg[] =
@@ -306,7 +354,7 @@
 }
 
 static int
-initerr(perrdetail *err_ret, const char *filename)
+initerr(perrdetail *err_ret, PyObject *filename)
 {
     err_ret->error = E_OK;
     err_ret->lineno = 0;
@@ -315,13 +363,16 @@
     err_ret->token = -1;
     err_ret->expected = -1;
 #ifndef PGEN
-    if (filename)
-        err_ret->filename = PyUnicode_DecodeFSDefault(filename);
-    else
+    if (filename) {
+        Py_INCREF(filename);
+        err_ret->filename = filename;
+    }
+    else {
         err_ret->filename = PyUnicode_FromString("<string>");
-    if (err_ret->filename == NULL) {
-        err_ret->error = E_ERROR;
-        return -1;
+        if (err_ret->filename == NULL) {
+            err_ret->error = E_ERROR;
+            return -1;
+        }
     }
 #endif
     return 0;
diff --git a/Python/_warnings.c b/Python/_warnings.c
--- a/Python/_warnings.c
+++ b/Python/_warnings.c
@@ -707,14 +707,14 @@
 
         /* Handle the warning. */
         returned = warn_explicit(category, message, filename, lineno, module,
-                            registry, source_line);
+                                 registry, source_line);
         Py_DECREF(source_list);
         return returned;
     }
 
  standard_call:
     return warn_explicit(category, message, filename, lineno, module,
-                                registry, NULL);
+                         registry, NULL);
 }
 
 
@@ -786,11 +786,26 @@
 
 /* Warning with explicit origin */
 int
+PyErr_WarnExplicitObject(PyObject *category, PyObject *message,
+                         PyObject *filename, int lineno,
+                         PyObject *module, PyObject *registry)
+{
+    PyObject *res;
+    if (category == NULL)
+        category = PyExc_RuntimeWarning;
+    res = warn_explicit(category, message, filename, lineno,
+                        module, registry, NULL);
+    if (res == NULL)
+        return -1;
+    Py_DECREF(res);
+    return 0;
+}
+
+int
 PyErr_WarnExplicit(PyObject *category, const char *text,
                    const char *filename_str, int lineno,
                    const char *module_str, PyObject *registry)
 {
-    PyObject *res;
     PyObject *message = PyUnicode_FromString(text);
     PyObject *filename = PyUnicode_DecodeFSDefault(filename_str);
     PyObject *module = NULL;
@@ -804,14 +819,8 @@
             goto exit;
     }
 
-    if (category == NULL)
-        category = PyExc_RuntimeWarning;
-    res = warn_explicit(category, message, filename, lineno, module, registry,
-                        NULL);
-    if (res == NULL)
-        goto exit;
-    Py_DECREF(res);
-    ret = 0;
+    ret = PyErr_WarnExplicitObject(category, message, filename, lineno,
+                                   module, registry);
 
  exit:
     Py_XDECREF(message);
diff --git a/Python/ast.c b/Python/ast.c
--- a/Python/ast.c
+++ b/Python/ast.c
@@ -491,7 +491,7 @@
 struct compiling {
     char *c_encoding; /* source encoding */
     PyArena *c_arena; /* arena for allocating memeory */
-    const char *c_filename; /* filename */
+    PyObject *c_filename; /* filename */
     PyObject *c_normalize; /* Normalization function from unicodedata. */
     PyObject *c_normalize_args; /* Normalization argument tuple. */
 };
@@ -573,24 +573,13 @@
 ast_error(struct compiling *c, const node *n, const char *errmsg)
 {
     PyObject *value, *errstr, *loc, *tmp;
-    PyObject *filename_obj;
-
-    loc = PyErr_ProgramText(c->c_filename, LINENO(n));
+
+    loc = PyErr_ProgramTextObject(c->c_filename, LINENO(n));
     if (!loc) {
         Py_INCREF(Py_None);
         loc = Py_None;
     }
-    if (c->c_filename) {
-        filename_obj = PyUnicode_DecodeFSDefault(c->c_filename);
-        if (!filename_obj) {
-            Py_DECREF(loc);
-            return 0;
-        }
-    } else {
-        Py_INCREF(Py_None);
-        filename_obj = Py_None;
-    }
-    tmp = Py_BuildValue("(NiiN)", filename_obj, LINENO(n), n->n_col_offset, loc);
+    tmp = Py_BuildValue("(OiiN)", c->c_filename, LINENO(n), n->n_col_offset, loc);
     if (!tmp)
         return 0;
     errstr = PyUnicode_FromString(errmsg);
@@ -673,8 +662,8 @@
 */
 
 mod_ty
-PyAST_FromNode(const node *n, PyCompilerFlags *flags, const char *filename,
-               PyArena *arena)
+PyAST_FromNodeObject(const node *n, PyCompilerFlags *flags,
+                     PyObject *filename, PyArena *arena)
 {
     int i, j, k, num;
     asdl_seq *stmts = NULL;
@@ -684,6 +673,7 @@
     mod_ty res = NULL;
 
     c.c_arena = arena;
+    /* borrowed reference */
     c.c_filename = filename;
     c.c_normalize = c.c_normalize_args = NULL;
     if (flags && flags->cf_flags & PyCF_SOURCE_IS_UTF8) {
@@ -797,6 +787,21 @@
     return res;
 }
 
+mod_ty
+PyAST_FromNode(const node *n, PyCompilerFlags *flags, const char *filename_str,
+               PyArena *arena)
+{
+    mod_ty mod;
+    PyObject *filename;
+    filename = PyUnicode_DecodeFSDefault(filename_str);
+    if (filename == NULL)
+        return NULL;
+    mod = PyAST_FromNodeObject(n, flags, filename, arena);
+    Py_DECREF(filename);
+    return mod;
+
+}
+
 /* Return the AST repr. of the operator represented as syntax (|, ^, etc.)
 */
 
diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c
--- a/Python/bltinmodule.c
+++ b/Python/bltinmodule.c
@@ -579,8 +579,7 @@
 builtin_compile(PyObject *self, PyObject *args, PyObject *kwds)
 {
     char *str;
-    PyObject *filename_obj;
-    char *filename;
+    PyObject *filename;
     char *startstr;
     int mode = -1;
     int dont_inherit = 0;
@@ -596,12 +595,11 @@
 
     if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO&s|iii:compile",  kwlist,
                                      &cmd,
-                                     PyUnicode_FSConverter, &filename_obj,
+                                     PyUnicode_FSDecoder, &filename,
                                      &startstr, &supplied_flags,
                                      &dont_inherit, &optimize))
         return NULL;
 
-    filename = PyBytes_AS_STRING(filename_obj);
     cf.cf_flags = supplied_flags | PyCF_SOURCE_IS_UTF8;
 
     if (supplied_flags &
@@ -659,8 +657,8 @@
                 PyArena_Free(arena);
                 goto error;
             }
-            result = (PyObject*)PyAST_CompileEx(mod, filename,
-                                                &cf, optimize, arena);
+            result = (PyObject*)PyAST_CompileObject(mod, filename,
+                                                    &cf, optimize, arena);
             PyArena_Free(arena);
         }
         goto finally;
@@ -670,13 +668,13 @@
     if (str == NULL)
         goto error;
 
-    result = Py_CompileStringExFlags(str, filename, start[mode], &cf, optimize);
+    result = Py_CompileStringObject(str, filename, start[mode], &cf, optimize);
     goto finally;
 
 error:
     result = NULL;
 finally:
-    Py_DECREF(filename_obj);
+    Py_DECREF(filename);
     return result;
 }
 
diff --git a/Python/compile.c b/Python/compile.c
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -149,8 +149,7 @@
 */
 
 struct compiler {
-    const char *c_filename;
-    PyObject *c_filename_obj;
+    PyObject *c_filename;
     struct symtable *c_st;
     PyFutureFeatures *c_future; /* pointer to module's __future__ */
     PyCompilerFlags *c_flags;
@@ -288,8 +287,8 @@
 }
 
 PyCodeObject *
-PyAST_CompileEx(mod_ty mod, const char *filename, PyCompilerFlags *flags,
-                int optimize, PyArena *arena)
+PyAST_CompileObject(mod_ty mod, PyObject *filename, PyCompilerFlags *flags,
+                   int optimize, PyArena *arena)
 {
     struct compiler c;
     PyCodeObject *co = NULL;
@@ -304,12 +303,10 @@
 
     if (!compiler_init(&c))
         return NULL;
+    Py_INCREF(filename);
     c.c_filename = filename;
-    c.c_filename_obj = PyUnicode_DecodeFSDefault(filename);
-    if (!c.c_filename_obj)
-        goto finally;
     c.c_arena = arena;
-    c.c_future = PyFuture_FromAST(mod, filename);
+    c.c_future = PyFuture_FromASTObject(mod, filename);
     if (c.c_future == NULL)
         goto finally;
     if (!flags) {
@@ -323,7 +320,7 @@
     c.c_optimize = (optimize == -1) ? Py_OptimizeFlag : optimize;
     c.c_nestlevel = 0;
 
-    c.c_st = PySymtable_Build(mod, filename, c.c_future);
+    c.c_st = PySymtable_BuildObject(mod, filename, c.c_future);
     if (c.c_st == NULL) {
         if (!PyErr_Occurred())
             PyErr_SetString(PyExc_SystemError, "no symtable");
@@ -339,6 +336,21 @@
 }
 
 PyCodeObject *
+PyAST_CompileEx(mod_ty mod, const char *filename_str, PyCompilerFlags *flags,
+                int optimize, PyArena *arena)
+{
+    PyObject *filename;
+    PyCodeObject *co;
+    filename = PyUnicode_DecodeFSDefault(filename_str);
+    if (filename == NULL)
+        return NULL;
+    co = PyAST_CompileObject(mod, filename, flags, optimize, arena);
+    Py_DECREF(filename);
+    return co;
+
+}
+
+PyCodeObject *
 PyNode_Compile(struct _node *n, const char *filename)
 {
     PyCodeObject *co = NULL;
@@ -360,8 +372,7 @@
         PySymtable_Free(c->c_st);
     if (c->c_future)
         PyObject_Free(c->c_future);
-    if (c->c_filename_obj)
-        Py_DECREF(c->c_filename_obj);
+    Py_XDECREF(c->c_filename);
     Py_DECREF(c->c_stack);
 }
 
@@ -1368,12 +1379,11 @@
     if (scope == 0) {
         char buf[350];
         PyOS_snprintf(buf, sizeof(buf),
-                      "unknown scope for %.100s in %.100s(%s) in %s\n"
+                      "unknown scope for %.100s in %.100s(%s)\n"
                       "symbols: %s\nlocals: %s\nglobals: %s",
                       PyBytes_AS_STRING(name),
                       PyBytes_AS_STRING(c->u->u_name),
                       PyObject_REPR(c->u->u_ste->ste_id),
-                      c->c_filename,
                       PyObject_REPR(c->u->u_ste->ste_symbols),
                       PyObject_REPR(c->u->u_varnames),
                       PyObject_REPR(c->u->u_names)
@@ -2411,6 +2421,7 @@
 {
     static PyObject *assertion_error = NULL;
     basicblock *end;
+    PyObject* msg;
 
     if (c->c_optimize)
         return 1;
@@ -2421,11 +2432,17 @@
     }
     if (s->v.Assert.test->kind == Tuple_kind &&
         asdl_seq_LEN(s->v.Assert.test->v.Tuple.elts) > 0) {
-        const char* msg =
-            "assertion is always true, perhaps remove parentheses?";
-        if (PyErr_WarnExplicit(PyExc_SyntaxWarning, msg, c->c_filename,
-                               c->u->u_lineno, NULL, NULL) == -1)
+        msg = PyUnicode_FromString("assertion is always true, "
+                                   "perhaps remove parentheses?");
+        if (msg == NULL)
             return 0;
+        if (PyErr_WarnExplicitObject(PyExc_SyntaxWarning, msg,
+                                     c->c_filename, c->u->u_lineno,
+                                     NULL, NULL) == -1) {
+            Py_DECREF(msg);
+            return 0;
+        }
+        Py_DECREF(msg);
     }
     VISIT(c, expr, s->v.Assert.test);
     end = compiler_new_block(c);
@@ -3593,12 +3610,12 @@
     PyObject *loc;
     PyObject *u = NULL, *v = NULL;
 
-    loc = PyErr_ProgramText(c->c_filename, c->u->u_lineno);
+    loc = PyErr_ProgramTextObject(c->c_filename, c->u->u_lineno);
     if (!loc) {
         Py_INCREF(Py_None);
         loc = Py_None;
     }
-    u = Py_BuildValue("(OiiO)", c->c_filename_obj, c->u->u_lineno,
+    u = Py_BuildValue("(OiiO)", c->c_filename, c->u->u_lineno,
                       c->u->u_col_offset, loc);
     if (!u)
         goto exit;
@@ -4188,7 +4205,7 @@
                     nlocals, stackdepth(c), flags,
                     bytecode, consts, names, varnames,
                     freevars, cellvars,
-                    c->c_filename_obj, c->u->u_name,
+                    c->c_filename, c->u->u_name,
                     c->u->u_firstlineno,
                     a->a_lnotab);
  error:
diff --git a/Python/errors.c b/Python/errors.c
--- a/Python/errors.c
+++ b/Python/errors.c
@@ -901,7 +901,8 @@
 
 
 void
-PyErr_SyntaxLocation(const char *filename, int lineno) {
+PyErr_SyntaxLocation(const char *filename, int lineno)
+{
     PyErr_SyntaxLocationEx(filename, lineno, -1);
 }
 
@@ -911,7 +912,7 @@
    to make printing of exceptions believe it is a syntax error. */
 
 void
-PyErr_SyntaxLocationEx(const char *filename, int lineno, int col_offset)
+PyErr_SyntaxLocationObject(PyObject *filename, int lineno, int col_offset)
 {
     PyObject *exc, *v, *tb, *tmp;
     _Py_IDENTIFIER(filename);
@@ -945,16 +946,10 @@
         }
     }
     if (filename != NULL) {
-        tmp = PyUnicode_DecodeFSDefault(filename);
-        if (tmp == NULL)
+        if (_PyObject_SetAttrId(v, &PyId_filename, filename))
             PyErr_Clear();
-        else {
-            if (_PyObject_SetAttrId(v, &PyId_filename, tmp))
-                PyErr_Clear();
-            Py_DECREF(tmp);
-        }
 
-        tmp = PyErr_ProgramText(filename, lineno);
+        tmp = PyErr_ProgramTextObject(filename, lineno);
         if (tmp) {
             if (_PyObject_SetAttrId(v, &PyId_text, tmp))
                 PyErr_Clear();
@@ -984,6 +979,21 @@
     PyErr_Restore(exc, v, tb);
 }
 
+void
+PyErr_SyntaxLocationEx(const char *filename, int lineno, int col_offset)
+{
+    PyObject *fileobj;
+    if (filename != NULL) {
+        fileobj = PyUnicode_DecodeFSDefault(filename);
+        if (fileobj == NULL)
+            PyErr_Clear();
+    }
+    else
+        fileobj = NULL;
+    PyErr_SyntaxLocationObject(fileobj, lineno, col_offset);
+    Py_XDECREF(fileobj);
+}
+
 /* Attempt to load the line of text that the exception refers to.  If it
    fails, it will return NULL but will not set an exception.
 
@@ -991,15 +1001,11 @@
    functionality in tb_displayline() in traceback.c. */
 
 PyObject *
-PyErr_ProgramText(const char *filename, int lineno)
+err_programtext(FILE *fp, int lineno)
 {
-    FILE *fp;
     int i;
     char linebuf[1000];
 
-    if (filename == NULL || *filename == '\0' || lineno <= 0)
-        return NULL;
-    fp = fopen(filename, "r" PY_STDIOTEXTMODE);
     if (fp == NULL)
         return NULL;
     for (i = 0; i < lineno; i++) {
@@ -1030,6 +1036,26 @@
     return NULL;
 }
 
+PyObject *
+PyErr_ProgramText(const char *filename, int lineno)
+{
+    FILE *fp;
+    if (filename == NULL || *filename == '\0' || lineno <= 0)
+        return NULL;
+    fp = fopen(filename, "r" PY_STDIOTEXTMODE);
+    return err_programtext(fp, lineno);
+}
+
+PyObject *
+PyErr_ProgramTextObject(PyObject *filename, int lineno)
+{
+    FILE *fp;
+    if (filename == NULL || lineno <= 0)
+        return NULL;
+    fp = _Py_fopen(filename, "r" PY_STDIOTEXTMODE);
+    return err_programtext(fp, lineno);
+}
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/Python/future.c b/Python/future.c
--- a/Python/future.c
+++ b/Python/future.c
@@ -11,7 +11,7 @@
 "from __future__ imports must occur at the beginning of the file"
 
 static int
-future_check_features(PyFutureFeatures *ff, stmt_ty s, const char *filename)
+future_check_features(PyFutureFeatures *ff, stmt_ty s, PyObject *filename)
 {
     int i;
     asdl_seq *names;
@@ -43,12 +43,12 @@
         } else if (strcmp(feature, "braces") == 0) {
             PyErr_SetString(PyExc_SyntaxError,
                             "not a chance");
-            PyErr_SyntaxLocationEx(filename, s->lineno, s->col_offset);
+            PyErr_SyntaxLocationObject(filename, s->lineno, s->col_offset);
             return 0;
         } else {
             PyErr_Format(PyExc_SyntaxError,
                          UNDEFINED_FUTURE_FEATURE, feature);
-            PyErr_SyntaxLocationEx(filename, s->lineno, s->col_offset);
+            PyErr_SyntaxLocationObject(filename, s->lineno, s->col_offset);
             return 0;
         }
     }
@@ -56,7 +56,7 @@
 }
 
 static int
-future_parse(PyFutureFeatures *ff, mod_ty mod, const char *filename)
+future_parse(PyFutureFeatures *ff, mod_ty mod, PyObject *filename)
 {
     int i, done = 0, prev_line = 0;
     stmt_ty first;
@@ -101,7 +101,7 @@
                 if (done) {
                     PyErr_SetString(PyExc_SyntaxError,
                                     ERR_LATE_FUTURE);
-                    PyErr_SyntaxLocationEx(filename, s->lineno, s->col_offset);
+                    PyErr_SyntaxLocationObject(filename, s->lineno, s->col_offset);
                     return 0;
                 }
                 if (!future_check_features(ff, s, filename))
@@ -121,7 +121,7 @@
 
 
 PyFutureFeatures *
-PyFuture_FromAST(mod_ty mod, const char *filename)
+PyFuture_FromASTObject(mod_ty mod, PyObject *filename)
 {
     PyFutureFeatures *ff;
 
@@ -139,3 +139,18 @@
     }
     return ff;
 }
+
+
+PyFutureFeatures *
+PyFuture_FromAST(mod_ty mod, const char *filename_str)
+{
+    PyFutureFeatures *ff;
+    PyObject *filename;
+
+    filename = PyUnicode_DecodeFSDefault(filename_str);
+    if (filename == NULL)
+        return NULL;
+    ff = PyFuture_FromASTObject(mod, filename);
+    Py_DECREF(filename);
+    return ff;
+}
diff --git a/Python/pythonrun.c b/Python/pythonrun.c
--- a/Python/pythonrun.c
+++ b/Python/pythonrun.c
@@ -2051,8 +2051,8 @@
 }
 
 PyObject *
-Py_CompileStringExFlags(const char *str, const char *filename, int start,
-                        PyCompilerFlags *flags, int optimize)
+Py_CompileStringObject(const char *str, PyObject *filename, int start,
+                       PyCompilerFlags *flags, int optimize)
 {
     PyCodeObject *co;
     mod_ty mod;
@@ -2060,7 +2060,7 @@
     if (arena == NULL)
         return NULL;
 
-    mod = PyParser_ASTFromString(str, filename, start, flags, arena);
+    mod = PyParser_ASTFromStringObject(str, filename, start, flags, arena);
     if (mod == NULL) {
         PyArena_Free(arena);
         return NULL;
@@ -2070,11 +2070,24 @@
         PyArena_Free(arena);
         return result;
     }
-    co = PyAST_CompileEx(mod, filename, flags, optimize, arena);
+    co = PyAST_CompileObject(mod, filename, flags, optimize, arena);
     PyArena_Free(arena);
     return (PyObject *)co;
 }
 
+PyObject *
+Py_CompileStringExFlags(const char *str, const char *filename_str, int start,
+                        PyCompilerFlags *flags, int optimize)
+{
+    PyObject *filename, *co;
+    filename = PyUnicode_DecodeFSDefault(filename_str);
+    if (filename == NULL)
+        return NULL;
+    co = Py_CompileStringObject(str, filename, start, flags, optimize);
+    Py_DECREF(filename);
+    return co;
+}
+
 /* For use in Py_LIMITED_API */
 #undef Py_CompileString
 PyObject *
@@ -2084,46 +2097,62 @@
 }
 
 struct symtable *
-Py_SymtableString(const char *str, const char *filename, int start)
+Py_SymtableStringObject(const char *str, PyObject *filename, int start)
 {
     struct symtable *st;
     mod_ty mod;
     PyCompilerFlags flags;
-    PyArena *arena = PyArena_New();
+    PyArena *arena;
+
+    arena = PyArena_New();
     if (arena == NULL)
         return NULL;
 
     flags.cf_flags = 0;
-    mod = PyParser_ASTFromString(str, filename, start, &flags, arena);
+    mod = PyParser_ASTFromStringObject(str, filename, start, &flags, arena);
     if (mod == NULL) {
         PyArena_Free(arena);
         return NULL;
     }
-    st = PySymtable_Build(mod, filename, 0);
+    st = PySymtable_BuildObject(mod, filename, 0);
     PyArena_Free(arena);
     return st;
 }
 
+struct symtable *
+Py_SymtableString(const char *str, const char *filename_str, int start)
+{
+    PyObject *filename;
+    struct symtable *st;
+
+    filename = PyUnicode_DecodeFSDefault(filename_str);
+    if (filename == NULL)
+        return NULL;
+    st = Py_SymtableStringObject(str, filename, start);
+    Py_DECREF(filename);
+    return st;
+}
+
 /* Preferred access to parser is through AST. */
 mod_ty
-PyParser_ASTFromString(const char *s, const char *filename, int start,
-                       PyCompilerFlags *flags, PyArena *arena)
+PyParser_ASTFromStringObject(const char *s, PyObject *filename, int start,
+                             PyCompilerFlags *flags, PyArena *arena)
 {
     mod_ty mod;
     PyCompilerFlags localflags;
     perrdetail err;
     int iflags = PARSER_FLAGS(flags);
 
-    node *n = PyParser_ParseStringFlagsFilenameEx(s, filename,
-                                    &_PyParser_Grammar, start, &err,
-                                    &iflags);
+    node *n = PyParser_ParseStringObject(s, filename,
+                                         &_PyParser_Grammar, start, &err,
+                                         &iflags);
     if (flags == NULL) {
         localflags.cf_flags = 0;
         flags = &localflags;
     }
     if (n) {
         flags->cf_flags |= iflags & PyCF_MASK;
-        mod = PyAST_FromNode(n, flags, filename, arena);
+        mod = PyAST_FromNodeObject(n, flags, filename, arena);
         PyNode_Free(n);
     }
     else {
@@ -2135,26 +2164,40 @@
 }
 
 mod_ty
-PyParser_ASTFromFile(FILE *fp, const char *filename, const char* enc,
-                     int start, char *ps1,
-                     char *ps2, PyCompilerFlags *flags, int *errcode,
-                     PyArena *arena)
+PyParser_ASTFromString(const char *s, const char *filename_str, int start,
+                       PyCompilerFlags *flags, PyArena *arena)
+{
+    PyObject *filename;
+    mod_ty mod;
+    filename = PyUnicode_DecodeFSDefault(filename_str);
+    if (filename == NULL)
+        return NULL;
+    mod = PyParser_ASTFromStringObject(s, filename, start, flags, arena);
+    Py_DECREF(filename);
+    return mod;
+}
+
+mod_ty
+PyParser_ASTFromFileObject(FILE *fp, PyObject *filename, const char* enc,
+                           int start, char *ps1,
+                           char *ps2, PyCompilerFlags *flags, int *errcode,
+                           PyArena *arena)
 {
     mod_ty mod;
     PyCompilerFlags localflags;
     perrdetail err;
     int iflags = PARSER_FLAGS(flags);
 
-    node *n = PyParser_ParseFileFlagsEx(fp, filename, enc,
-                                      &_PyParser_Grammar,
-                            start, ps1, ps2, &err, &iflags);
+    node *n = PyParser_ParseFileObject(fp, filename, enc,
+                                       &_PyParser_Grammar,
+                                       start, ps1, ps2, &err, &iflags);
     if (flags == NULL) {
         localflags.cf_flags = 0;
         flags = &localflags;
     }
     if (n) {
         flags->cf_flags |= iflags & PyCF_MASK;
-        mod = PyAST_FromNode(n, flags, filename, arena);
+        mod = PyAST_FromNodeObject(n, flags, filename, arena);
         PyNode_Free(n);
     }
     else {
@@ -2167,6 +2210,23 @@
     return mod;
 }
 
+mod_ty
+PyParser_ASTFromFile(FILE *fp, const char *filename_str, const char* enc,
+                     int start, char *ps1,
+                     char *ps2, PyCompilerFlags *flags, int *errcode,
+                     PyArena *arena)
+{
+    mod_ty mod;
+    PyObject *filename;
+    filename = PyUnicode_DecodeFSDefault(filename_str);
+    if (filename == NULL)
+        return NULL;
+    mod = PyParser_ASTFromFileObject(fp, filename, enc, start, ps1, ps2,
+                                     flags, errcode, arena);
+    Py_DECREF(filename);
+    return mod;
+}
+
 /* Simplified interface to parsefile -- return node or set exception */
 
 node *
diff --git a/Python/symtable.c b/Python/symtable.c
--- a/Python/symtable.c
+++ b/Python/symtable.c
@@ -233,7 +233,7 @@
 #define COMPILER_STACK_FRAME_SCALE 3
 
 struct symtable *
-PySymtable_Build(mod_ty mod, const char *filename, PyFutureFeatures *future)
+PySymtable_BuildObject(mod_ty mod, PyObject *filename, PyFutureFeatures *future)
 {
     struct symtable *st = symtable_new();
     asdl_seq *seq;
@@ -241,7 +241,12 @@
     PyThreadState *tstate;
 
     if (st == NULL)
-        return st;
+        return NULL;
+    if (filename == NULL) {
+        PySymtable_Free(st);
+        return NULL;
+    }
+    Py_INCREF(filename);
     st->st_filename = filename;
     st->st_future = future;
 
@@ -302,9 +307,23 @@
     return NULL;
 }
 
+struct symtable *
+PySymtable_Build(mod_ty mod, const char *filename_str, PyFutureFeatures *future)
+{
+    PyObject *filename;
+    struct symtable *st;
+    filename = PyUnicode_DecodeFSDefault(filename_str);
+    if (filename == NULL)
+        return NULL;
+    st = PySymtable_BuildObject(mod, filename, future);
+    Py_DECREF(filename);
+    return st;
+}
+
 void
 PySymtable_Free(struct symtable *st)
 {
+    Py_XDECREF(st->st_filename);
     Py_XDECREF(st->st_blocks);
     Py_XDECREF(st->st_stack);
     PyMem_Free((void *)st);
@@ -354,9 +373,9 @@
         if (PyTuple_GET_ITEM(data, 0) == name)
             break;
     }
-    PyErr_SyntaxLocationEx(ste->ste_table->st_filename,
-                           PyLong_AsLong(PyTuple_GET_ITEM(data, 1)),
-                           PyLong_AsLong(PyTuple_GET_ITEM(data, 2)));
+    PyErr_SyntaxLocationObject(ste->ste_table->st_filename,
+                               PyLong_AsLong(PyTuple_GET_ITEM(data, 1)),
+                               PyLong_AsLong(PyTuple_GET_ITEM(data, 2)));
     return 0;
 }
 
@@ -583,8 +602,9 @@
         break;
     }
 
-    PyErr_SyntaxLocationEx(ste->ste_table->st_filename, ste->ste_opt_lineno,
-                           ste->ste_opt_col_offset);
+    PyErr_SyntaxLocationObject(ste->ste_table->st_filename,
+                               ste->ste_opt_lineno,
+                               ste->ste_opt_col_offset);
     return 0;
 }
 
@@ -915,15 +935,20 @@
 static int
 symtable_warn(struct symtable *st, char *msg, int lineno)
 {
-    if (PyErr_WarnExplicit(PyExc_SyntaxWarning, msg, st->st_filename,
-                           lineno, NULL, NULL) < 0)     {
+    PyObject *message = PyUnicode_FromString(msg);
+    if (message == NULL)
+        return 0;
+    if (PyErr_WarnExplicitObject(PyExc_SyntaxWarning, message, st->st_filename,
+                                 lineno, NULL, NULL) < 0)     {
+        Py_DECREF(message);
         if (PyErr_ExceptionMatches(PyExc_SyntaxWarning)) {
             PyErr_SetString(PyExc_SyntaxError, msg);
-            PyErr_SyntaxLocationEx(st->st_filename, st->st_cur->ste_lineno,
-                                   st->st_cur->ste_col_offset);
+            PyErr_SyntaxLocationObject(st->st_filename, st->st_cur->ste_lineno,
+                                       st->st_cur->ste_col_offset);
         }
         return 0;
     }
+    Py_DECREF(message);
     return 1;
 }
 
@@ -1006,9 +1031,9 @@
         if ((flag & DEF_PARAM) && (val & DEF_PARAM)) {
             /* Is it better to use 'mangled' or 'name' here? */
             PyErr_Format(PyExc_SyntaxError, DUPLICATE_ARGUMENT, name);
-            PyErr_SyntaxLocationEx(st->st_filename,
-                                   st->st_cur->ste_lineno,
-                                   st->st_cur->ste_col_offset);
+            PyErr_SyntaxLocationObject(st->st_filename,
+                                       st->st_cur->ste_lineno,
+                                       st->st_cur->ste_col_offset);
             goto error;
         }
         val |= flag;
@@ -1613,7 +1638,7 @@
             int lineno = st->st_cur->ste_lineno;
             int col_offset = st->st_cur->ste_col_offset;
             PyErr_SetString(PyExc_SyntaxError, IMPORT_STAR_WARNING);
-            PyErr_SyntaxLocationEx(st->st_filename, lineno, col_offset);
+            PyErr_SyntaxLocationObject(st->st_filename, lineno, col_offset);
             Py_DECREF(store_name);
             return 0;
         }

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list