diff --git a/Doc/library/__future__.rst b/Doc/library/__future__.rst index e3d749e6017847..c10c022aa24787 100644 --- a/Doc/library/__future__.rst +++ b/Doc/library/__future__.rst @@ -93,6 +93,10 @@ language using this mechanism: | annotations | 3.7.0b1 | 4.0 | :pep:`563`: | | | | | *Postponed evaluation of annotations* | +------------------+-------------+--------------+---------------------------------------------+ ++------------------+-------------+--------------+---------------------------------------------+ +| absolute_codepath| 3.8.0b1 | 4.0 | :pep:`9999`: | +| | | | *Absolute codepaths* | ++------------------+-------------+--------------+---------------------------------------------+ .. XXX Adding a new entry? Remember to update simple_stmts.rst, too. diff --git a/Include/code.h b/Include/code.h index 933de97d078282..d916cb0e3bb696 100644 --- a/Include/code.h +++ b/Include/code.h @@ -84,6 +84,7 @@ typedef struct { #define CO_FUTURE_BARRY_AS_BDFL 0x40000 #define CO_FUTURE_GENERATOR_STOP 0x80000 #define CO_FUTURE_ANNOTATIONS 0x100000 +#define CO_FUTURE_ABSOLUTE_CODEPATH 0x200000 /* This value is found in the co_cell2arg array when the associated cell variable does not correspond to an argument. */ diff --git a/Include/compile.h b/Include/compile.h index a833caa06b9dad..7baefdfe1d4cc6 100644 --- a/Include/compile.h +++ b/Include/compile.h @@ -16,7 +16,9 @@ PyAPI_FUNC(PyCodeObject *) PyNode_Compile(struct _node *, const char *); #define PyCF_MASK (CO_FUTURE_DIVISION | CO_FUTURE_ABSOLUTE_IMPORT | \ CO_FUTURE_WITH_STATEMENT | CO_FUTURE_PRINT_FUNCTION | \ CO_FUTURE_UNICODE_LITERALS | CO_FUTURE_BARRY_AS_BDFL | \ - CO_FUTURE_GENERATOR_STOP | CO_FUTURE_ANNOTATIONS) + CO_FUTURE_GENERATOR_STOP | CO_FUTURE_ANNOTATIONS | \ + CO_FUTURE_ABSOLUTE_CODEPATH) + #define PyCF_MASK_OBSOLETE (CO_NESTED) #define PyCF_SOURCE_IS_UTF8 0x0100 #define PyCF_DONT_IMPLY_DEDENT 0x0200 @@ -49,6 +51,7 @@ typedef struct { #define FUTURE_BARRY_AS_BDFL "barry_as_FLUFL" #define FUTURE_GENERATOR_STOP "generator_stop" #define FUTURE_ANNOTATIONS "annotations" +#define FUTURE_ABSOLUTE_CODEPATH "absolute_codepath" struct _mod; /* Declare the existence of this type */ #define PyAST_Compile(mod, s, f, ar) PyAST_CompileEx(mod, s, f, -1, ar) diff --git a/Lib/__future__.py b/Lib/__future__.py index e1135685d846ce..d09072e8bd7f75 100644 --- a/Lib/__future__.py +++ b/Lib/__future__.py @@ -58,6 +58,7 @@ "barry_as_FLUFL", "generator_stop", "annotations", + "absolute_codepath", ] __all__ = ["all_feature_names"] + all_feature_names @@ -76,6 +77,7 @@ CO_FUTURE_BARRY_AS_BDFL = 0x40000 CO_FUTURE_GENERATOR_STOP = 0x80000 # StopIteration becomes RuntimeError in generators CO_FUTURE_ANNOTATIONS = 0x100000 # annotations become strings at runtime +CO_FUTURE_ABSOLUTE_CODEPATH = 0x200000 class _Feature: def __init__(self, optionalRelease, mandatoryRelease, compiler_flag): @@ -144,3 +146,7 @@ def __repr__(self): annotations = _Feature((3, 7, 0, "beta", 1), (4, 0, 0, "alpha", 0), CO_FUTURE_ANNOTATIONS) + +absolute_codepath = _Feature((3, 8, 0, "beta", 1), + (4, 0, 0, "alpha", 0), + CO_FUTURE_ABSOLUTE_CODEPATH) diff --git a/Lib/test/test_future.py b/Lib/test/test_future.py index dd148b62956298..a16e1fe0cc320b 100644 --- a/Lib/test/test_future.py +++ b/Lib/test/test_future.py @@ -103,6 +103,10 @@ def test_unicode_literals_exec(self): exec("from __future__ import unicode_literals; x = ''", {}, scope) self.assertIsInstance(scope["x"], str) + def test_future5(self): + with support.CleanImport('test_future6'): + from test import test_future6 + class AnnotationsFutureTestCase(unittest.TestCase): template = dedent( """ diff --git a/Lib/test/test_future6.py b/Lib/test/test_future6.py new file mode 100644 index 00000000000000..2e19f1f261bfb6 --- /dev/null +++ b/Lib/test/test_future6.py @@ -0,0 +1,14 @@ +from __future__ import absolute_codepath +import os +import unittest + +class Tests(unittest.TestCase): + def test_absolute_codepath(self): + def fn(): + pass + filename = fn.__code__.co_filename + self.assertEqual(filename, os.path.abspath(filename)) + + +if __name__ == "__main__": + unittest.main() diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-05-23-22-22-02.bpo-20443.wXFKFh.rst b/Misc/NEWS.d/next/Core and Builtins/2019-05-23-22-22-02.bpo-20443.wXFKFh.rst new file mode 100644 index 00000000000000..3a458750964102 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-05-23-22-22-02.bpo-20443.wXFKFh.rst @@ -0,0 +1,2 @@ +Now code objects ``co_filename`` attribute is always an absolute path if a ``absolute_codepath`` future flag specified -- by +Batuhan Taskaya diff --git a/Python/compile.c b/Python/compile.c index 734e8401ff0247..1853c1e2e95c9e 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -22,7 +22,7 @@ */ #include "Python.h" - +#include "osdefs.h" #include "Python-ast.h" #include "pycore_pystate.h" /* _PyInterpreterState_GET_UNSAFE() */ #include "ast.h" @@ -30,6 +30,7 @@ #include "symtable.h" #include "opcode.h" #include "wordcode_helpers.h" +#include #define DEFAULT_BLOCK_SIZE 16 #define DEFAULT_BLOCKS 8 @@ -325,8 +326,7 @@ PyAST_CompileObject(mod_ty mod, PyObject *filename, PyCompilerFlags *flags, } if (!compiler_init(&c)) return NULL; - Py_INCREF(filename); - c.c_filename = filename; + c.c_arena = arena; c.c_future = PyFuture_FromASTObject(mod, filename); if (c.c_future == NULL) @@ -354,6 +354,23 @@ PyAST_CompileObject(mod_ty mod, PyObject *filename, PyCompilerFlags *flags, goto finally; } + if (c.c_future->ff_features & CO_FUTURE_ABSOLUTE_CODEPATH) { + wchar_t *path = PyUnicode_AsWideCharString(filename, NULL); + #if defined(HAVE_REALPATH) + wchar_t fullpath[MAXPATHLEN]; + path = _Py_wrealpath(path, fullpath, Py_ARRAY_LENGTH(fullpath)); + #elif defined(MS_WINDOWS) + wchar_t fullpath[MAX_PATH]; + wchar_t *ptemp; + if (GetFullPathNameW(path, Py_ARRAY_LENGTH(fullpath), fullpath, &ptemp)) + path = fullpath; + #endif + if (path != NULL) + filename = PyUnicode_FromWideChar(path, -1); + } + Py_INCREF(filename); + c.c_filename = filename; + co = compiler_mod(&c, mod); finally: diff --git a/Python/future.c b/Python/future.c index 1663a38a6fdb3a..3dcaa38ab66ef2 100644 --- a/Python/future.c +++ b/Python/future.c @@ -45,6 +45,8 @@ future_check_features(PyFutureFeatures *ff, stmt_ty s, PyObject *filename) continue; } else if (strcmp(feature, FUTURE_ANNOTATIONS) == 0) { ff->ff_features |= CO_FUTURE_ANNOTATIONS; + } else if (strcmp(feature, FUTURE_ABSOLUTE_CODEPATH) == 0) { + ff->ff_features |= CO_FUTURE_ABSOLUTE_CODEPATH; } else if (strcmp(feature, "braces") == 0) { PyErr_SetString(PyExc_SyntaxError, "not a chance");