class scopes are not inlined into their parent scope. (Contributed by
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
===========
out = kill_python(p)
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):
template = dedent(
"""
--- /dev/null
+Don't consider :mod:`__future__` imports with dots before the module name.
}
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__"))
{
Py_DECREF(names);
* 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;
if (modname &&
_PyUnicode_EqualToASCIIString(modname, "__future__")) {