mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
gh-118216: Don't consider dotted __future__
imports (#118267)
This commit is contained in:
parent
67bba9dd0f
commit
7c97dc8c95
5 changed files with 26 additions and 2 deletions
|
@ -288,6 +288,10 @@ Other Language Changes
|
||||||
class scopes are not inlined into their parent scope. (Contributed by
|
class scopes are not inlined into their parent scope. (Contributed by
|
||||||
Jelle Zijlstra in :gh:`109118` and :gh:`118160`.)
|
Jelle Zijlstra in :gh:`109118` and :gh:`118160`.)
|
||||||
|
|
||||||
|
* ``from __future__ import ...`` statements are now just normal
|
||||||
|
relative imports if dots are present before the module name.
|
||||||
|
(Contributed by Jeremiah Gabriel Pascual in :gh:`118216`.)
|
||||||
|
|
||||||
|
|
||||||
New Modules
|
New Modules
|
||||||
===========
|
===========
|
||||||
|
|
|
@ -203,6 +203,25 @@ class FutureTest(unittest.TestCase):
|
||||||
out = kill_python(p)
|
out = kill_python(p)
|
||||||
self.assertNotIn(b'SyntaxError: invalid syntax', out)
|
self.assertNotIn(b'SyntaxError: invalid syntax', out)
|
||||||
|
|
||||||
|
def test_future_dotted_import(self):
|
||||||
|
with self.assertRaises(ImportError):
|
||||||
|
exec("from .__future__ import spam")
|
||||||
|
|
||||||
|
code = dedent(
|
||||||
|
"""
|
||||||
|
from __future__ import print_function
|
||||||
|
from ...__future__ import ham
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
with self.assertRaises(ImportError):
|
||||||
|
exec(code)
|
||||||
|
|
||||||
|
code = """
|
||||||
|
from .__future__ import nested_scopes
|
||||||
|
from __future__ import barry_as_FLUFL
|
||||||
|
"""
|
||||||
|
self.assertSyntaxError(code, lineno=2)
|
||||||
|
|
||||||
class AnnotationsFutureTestCase(unittest.TestCase):
|
class AnnotationsFutureTestCase(unittest.TestCase):
|
||||||
template = dedent(
|
template = dedent(
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Don't consider :mod:`__future__` imports with dots before the module name.
|
|
@ -3849,7 +3849,7 @@ compiler_from_import(struct compiler *c, stmt_ty s)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (location_is_after(LOC(s), c->c_future.ff_location) &&
|
if (location_is_after(LOC(s), c->c_future.ff_location) &&
|
||||||
s->v.ImportFrom.module &&
|
s->v.ImportFrom.module && s->v.ImportFrom.level == 0 &&
|
||||||
_PyUnicode_EqualToASCIIString(s->v.ImportFrom.module, "__future__"))
|
_PyUnicode_EqualToASCIIString(s->v.ImportFrom.module, "__future__"))
|
||||||
{
|
{
|
||||||
Py_DECREF(names);
|
Py_DECREF(names);
|
||||||
|
|
|
@ -77,7 +77,7 @@ future_parse(_PyFutureFeatures *ff, mod_ty mod, PyObject *filename)
|
||||||
* are another future statement and a doc string.
|
* are another future statement and a doc string.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (s->kind == ImportFrom_kind) {
|
if (s->kind == ImportFrom_kind && s->v.ImportFrom.level == 0) {
|
||||||
identifier modname = s->v.ImportFrom.module;
|
identifier modname = s->v.ImportFrom.module;
|
||||||
if (modname &&
|
if (modname &&
|
||||||
_PyUnicode_EqualToASCIIString(modname, "__future__")) {
|
_PyUnicode_EqualToASCIIString(modname, "__future__")) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue