]> granicus.if.org Git - python/commitdiff
Close #11619: The parser and the import machinery do not encode Unicode
authorVictor Stinner <victor.stinner@gmail.com>
Mon, 26 Aug 2013 20:28:21 +0000 (22:28 +0200)
committerVictor Stinner <victor.stinner@gmail.com>
Mon, 26 Aug 2013 20:28:21 +0000 (22:28 +0200)
filenames anymore on Windows.

22 files changed:
Doc/c-api/exceptions.rst
Doc/c-api/veryhigh.rst
Include/ast.h
Include/compile.h
Include/parsetok.h
Include/pyerrors.h
Include/pythonrun.h
Include/symtable.h
Include/warnings.h
Lib/test/test_import.py
Misc/NEWS
Modules/parsermodule.c
Modules/symtablemodule.c
Parser/parsetok.c
Python/_warnings.c
Python/ast.c
Python/bltinmodule.c
Python/compile.c
Python/errors.c
Python/future.c
Python/pythonrun.c
Python/symtable.c

index c3d978f393f9a08d71c3c4c9503d89879fc06d10..8658a585410463a36a03c02d5432ab03c87a02a6 100644 (file)
@@ -235,7 +235,7 @@ in various ways.  There is a separate error indicator for each thread.
 
    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 @@ in various ways.  There is a separate error indicator for each thread.
 
    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 @@ in various ways.  There is a separate error indicator for each thread.
    .. 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 @@ in various ways.  There is a separate error indicator for each thread.
    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, ...)
index 284eee8d660dc409de8b6eaf9a5a7b7f5b6d7038..eef79516425804ed6b9cb1ca197db30843548976 100644 (file)
@@ -258,16 +258,15 @@ the same library that the Python runtime is using.
    *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 @@ the same library that the Python runtime is using.
    ``__debug__`` is true), ``1`` (asserts are removed, ``__debug__`` is false)
    or ``2`` (docstrings are removed too).
 
-   .. versionadded:: 3.2
+   .. 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
index 055e8dc916e1bfd6005bd22188bac5a5620aa8c7..6a8c8165c0550f80c4acb606b10a6d0d9c322e34 100644 (file)
@@ -10,6 +10,11 @@ PyAPI_FUNC(mod_ty) PyAST_FromNode(
     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
 }
index ac2636dfc93db6e1cde928b2fd9e5610c3a7258c..12d75d3337eef5364b974e0f5c709a74b53ac47f 100644 (file)
@@ -36,7 +36,20 @@ PyAPI_FUNC(PyCodeObject *) PyAST_CompileEx(
     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);
index 911dfc10e400eee4f82fe33d3a1ce6fb2b07b564..68b59bcc5184b981160e8beb56c6f68b838b1bb3 100644 (file)
@@ -42,10 +42,16 @@ PyAPI_FUNC(node *) PyParser_ParseFile (FILE *, const char *, grammar *, int,
 
 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 @@ PyAPI_FUNC(node *) PyParser_ParseFileFlagsEx(
     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 @@ PyAPI_FUNC(node *) PyParser_ParseStringFlagsFilenameEx(
     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 */
index af37410e2338cc541624c7a78ab4e800eeea4a48..a279d81541c59694f05206f0cb56e19be5ce5c6b 100644 (file)
@@ -301,9 +301,16 @@ PyAPI_FUNC(void) PyErr_SyntaxLocationEx(
     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 */
index 1a40b0655be631e17b3720e27cbfeae0af6c1ac5..aca591507e316e82672fb50979b8472eb07c4795 100644 (file)
@@ -66,6 +66,12 @@ PyAPI_FUNC(struct _mod *) PyParser_ASTFromString(
     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 @@ PyAPI_FUNC(struct _mod *) PyParser_ASTFromFile(
     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 @@ PyAPI_FUNC(PyObject *) Py_CompileStringExFlags(
     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);
index 44535d0d953ccfa532a5e1dfb9366f86788776a0..1cfd8844e5afb8927f069ed831286b7fc9c3142b 100644 (file)
@@ -16,7 +16,7 @@ typedef enum _block_type { FunctionBlock, ClassBlock, ModuleBlock }
 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 @@ PyAPI_FUNC(struct symtable *) PySymtable_Build(
     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 *);
index 5a7dfb1bb24b320dea3d5357c06924f80e687da1..217c06a665671130c93b69af7b73c3fc121e7478 100644 (file)
@@ -17,6 +17,13 @@ PyAPI_FUNC(int) PyErr_WarnFormat(
     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 */
index 11a75a07644c169ed21ab248edfec5b995cc4f21..2485e22ccfcf187e6890635deab92fae31711690 100644 (file)
@@ -22,7 +22,7 @@ import test.support
 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 @@ class ImportTracebackTests(unittest.TestCase):
         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.
index 90f15be68a7cd836ae4bacbb0dd85a1f93cec265..f7efbeb0c93c612df8876f143465e2dd982ec61e 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,9 @@ Projected Release date: 2013-09-08
 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).
 
index 7a6e4552079670d32a5797119a746d8172b4e795..537a2e9e6d2c730eb160e6cad09a35f79fcf6439 100644 (file)
@@ -477,33 +477,46 @@ parser_st2list(PyST_Object *self, PyObject *args, PyObject *kw)
 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;
 }
 
 
index fbc1ff6922012862be5bf1957b1b53d7135c8d01..036fdb926b2a20eb4c03931f56e39a1b8432456d 100644 (file)
@@ -11,12 +11,12 @@ symtable_symtable(PyObject *self, PyObject *args)
     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 @@ symtable_symtable(PyObject *self, PyObject *args)
     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;
index d61ba924b565163275a67782ca6648c2e851f761..2df91599268ef6175740f1bbaef902165ba65a14 100644 (file)
@@ -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 @@ PyParser_ParseStringFlagsFilename(const char *s, const char *filename,
 }
 
 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 @@ PyParser_ParseStringFlagsFilenameEx(const char *s, const char *filename,
     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 @@ PyParser_ParseFileFlags(FILE *fp, const char *filename, const char *enc,
 }
 
 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 @@ PyParser_ParseFileFlagsEx(FILE *fp, const char *filename,
     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 @@ done:
 }
 
 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 @@ initerr(perrdetail *err_ret, const char *filename)
     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;
index f93ede2e2f5546a52133ad8cde0c4f3daf42ce2d..b8d4bb61def4dc0db2463ef568ead0e29ab259a4 100644 (file)
@@ -707,14 +707,14 @@ warnings_warn_explicit(PyObject *self, PyObject *args, PyObject *kwds)
 
         /* 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);
 }
 
 
@@ -785,12 +785,27 @@ PyErr_Warn(PyObject *category, char *text)
 }
 
 /* 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 @@ PyErr_WarnExplicit(PyObject *category, const char *text,
             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);
index a72ba2035c020a5f2f4f1ce22eb7f13051f36ca4..073d59f02622dceb4c1e8347887d68f56fdecb61 100644 (file)
@@ -491,7 +491,7 @@ PyAST_Validate(mod_ty mod)
 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 @@ static int
 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 @@ num_stmts(const node *n)
 */
 
 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 @@ PyAST_FromNode(const node *n, PyCompilerFlags *flags, const char *filename,
     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 @@ PyAST_FromNode(const node *n, PyCompilerFlags *flags, const char *filename,
     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.)
 */
 
index fb3abae9627d09e0de044814a667e9f48a3adff9..11d9ee425fa4c00cd59d2377018a24411e5a9fb6 100644 (file)
@@ -579,8 +579,7 @@ static PyObject *
 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 @@ builtin_compile(PyObject *self, PyObject *args, PyObject *kwds)
 
     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 @@ builtin_compile(PyObject *self, PyObject *args, PyObject *kwds)
                 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 @@ builtin_compile(PyObject *self, PyObject *args, PyObject *kwds)
     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;
 }
 
index d11e3abeaa4ca2fc9f1b743039ea03bdc2a72926..71a0930a8e1fcacda6c2b663fd60c10d4f9e09bf 100644 (file)
@@ -149,8 +149,7 @@ handled by the symbol analysis pass.
 */
 
 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 @@ compiler_init(struct compiler *c)
 }
 
 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 @@ PyAST_CompileEx(mod_ty mod, const char *filename, PyCompilerFlags *flags,
 
     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 @@ PyAST_CompileEx(mod_ty mod, const char *filename, PyCompilerFlags *flags,
     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");
@@ -338,6 +335,21 @@ PyAST_CompileEx(mod_ty mod, const char *filename, PyCompilerFlags *flags,
     return co;
 }
 
+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)
 {
@@ -360,8 +372,7 @@ compiler_free(struct compiler *c)
         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 @@ get_ref_type(struct compiler *c, PyObject *name)
     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 @@ compiler_assert(struct compiler *c, stmt_ty s)
 {
     static PyObject *assertion_error = NULL;
     basicblock *end;
+    PyObject* msg;
 
     if (c->c_optimize)
         return 1;
@@ -2421,11 +2432,17 @@ compiler_assert(struct compiler *c, stmt_ty s)
     }
     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 @@ compiler_error(struct compiler *c, const char *errstr)
     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 @@ makecode(struct compiler *c, struct assembler *a)
                     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:
index 2d5eb6c21ec91e206aa7c0401651cda7ad277762..7985eab536f875e84e50e115616f1c1b88baba27 100644 (file)
@@ -901,7 +901,8 @@ extern PyObject *PyModule_GetWarningsModule(void);
 
 
 void
-PyErr_SyntaxLocation(const char *filename, int lineno) {
+PyErr_SyntaxLocation(const char *filename, int lineno)
+{
     PyErr_SyntaxLocationEx(filename, lineno, -1);
 }
 
@@ -911,7 +912,7 @@ PyErr_SyntaxLocation(const char *filename, int lineno) {
    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 @@ PyErr_SyntaxLocationEx(const char *filename, int lineno, int col_offset)
         }
     }
     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_SyntaxLocationEx(const char *filename, int lineno, int col_offset)
     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 @@ PyErr_SyntaxLocationEx(const char *filename, int lineno, int col_offset)
    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 @@ PyErr_ProgramText(const char *filename, int lineno)
     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
index 80978147f57e03b0da29b95ee952fbc98752f9c8..81eab54dd62fa33ce4ffafa20515e3e96c59014d 100644 (file)
@@ -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 @@ future_check_features(PyFutureFeatures *ff, stmt_ty s, const char *filename)
         } 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 @@ future_check_features(PyFutureFeatures *ff, stmt_ty s, const char *filename)
 }
 
 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 @@ future_parse(PyFutureFeatures *ff, mod_ty mod, const char *filename)
                 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 @@ future_parse(PyFutureFeatures *ff, mod_ty mod, const char *filename)
 
 
 PyFutureFeatures *
-PyFuture_FromAST(mod_ty mod, const char *filename)
+PyFuture_FromASTObject(mod_ty mod, PyObject *filename)
 {
     PyFutureFeatures *ff;
 
@@ -139,3 +139,18 @@ PyFuture_FromAST(mod_ty mod, const char *filename)
     }
     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;
+}
index 37dc3b8dc88bbedbb90aae44a207df1feb8904a0..dc8f412cb4190ca18b9f492e4c0cd197782d9b96 100644 (file)
@@ -2051,8 +2051,8 @@ run_pyc_file(FILE *fp, const char *filename, PyObject *globals,
 }
 
 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 @@ Py_CompileStringExFlags(const char *str, const char *filename, int start,
     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 @@ Py_CompileStringExFlags(const char *str, const char *filename, int start,
         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 @@ PyCompileString(const char *str, const char *filename, int start)
 }
 
 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 @@ PyParser_ASTFromString(const char *s, const char *filename, int start,
 }
 
 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 @@ PyParser_ASTFromFile(FILE *fp, const char *filename, const char* enc,
     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 *
index 183bf691335f1d0671a6adf32b5e6faf2d5f5939..618a81442bcac91c0842b9b135707ad10e8e77c9 100644 (file)
@@ -233,7 +233,7 @@ symtable_new(void)
 #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 @@ PySymtable_Build(mod_ty mod, const char *filename, PyFutureFeatures *future)
     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 @@ PySymtable_Build(mod_ty mod, const char *filename, PyFutureFeatures *future)
     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 @@ error_at_directive(PySTEntryObject *ste, PyObject *name)
         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 @@ check_unoptimized(const PySTEntryObject* ste) {
         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 @@ symtable_analyze(struct symtable *st)
 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 @@ symtable_add_def(struct symtable *st, PyObject *name, int flag)
         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 @@ symtable_visit_alias(struct symtable *st, alias_ty a)
             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;
         }