@@ -2872,6 +2872,14 @@ def check_warning(self, code, errtext, filename="<testcase>", mode="exec"):
28722872 with self .assertWarnsRegex (SyntaxWarning , errtext ):
28732873 compile (code , filename , mode )
28742874
2875+ def check_no_warning (self , code , filename = "<testcase>" , mode = "exec" ):
2876+ """Check that compiling code does not raise any warnings."""
2877+ import warnings
2878+ with warnings .catch_warnings (record = True ) as caught :
2879+ warnings .simplefilter ("always" )
2880+ compile (code , filename , mode )
2881+ self .assertEqual (caught , [])
2882+
28752883 def test_return_in_finally (self ):
28762884 source = textwrap .dedent ("""
28772885 def f():
@@ -2942,6 +2950,75 @@ def test_break_and_continue_in_finally(self):
29422950 """ )
29432951 self .check_warning (source , f"'{ kw } ' in a 'finally' block" )
29442952
2953+ def test_from_lazy_imports (self ):
2954+ # gh-150459
2955+ self .check_warning (
2956+ "from . lazy import x" ,
2957+ "did you mean 'lazy from . import'?" ,
2958+ )
2959+ self .check_warning (
2960+ "from . lazy import x as y" ,
2961+ "did you mean 'lazy from . import'?" ,
2962+ )
2963+ self .check_warning (
2964+ "from . lazy import *" ,
2965+ "did you mean 'lazy from . import'?" ,
2966+ )
2967+ self .check_warning (
2968+ "from .. lazy import x" ,
2969+ "did you mean 'lazy from .. import'?" ,
2970+ )
2971+ self .check_warning (
2972+ "from ... lazy import x" ,
2973+ "did you mean 'lazy from ... import'?" ,
2974+ )
2975+ self .check_warning (
2976+ "from .... lazy import x" ,
2977+ "did you mean 'lazy from .... import'?" ,
2978+ )
2979+ self .check_warning (
2980+ "from . \\ \n lazy import x" ,
2981+ "did you mean 'lazy from . import'?" ,
2982+ )
2983+ self .check_warning (
2984+ "from .\\ \n lazy import x" ,
2985+ "did you mean 'lazy from . import'?" ,
2986+ )
2987+ self .check_warning (
2988+ "from .\t lazy import x" ,
2989+ "did you mean 'lazy from . import'?" ,
2990+ )
2991+
2992+ def test_not_from_lazy_imports (self ):
2993+ self .check_no_warning ("from .lazy import x" )
2994+ self .check_no_warning ("from .lazy import *" )
2995+ self .check_no_warning ("from ..lazy import x" )
2996+ self .check_no_warning ("from ...lazy import x" )
2997+ self .check_no_warning ("from .lazy.sub import x" )
2998+ self .check_no_warning ("from ..lazy.sub import x" )
2999+ self .check_no_warning ("from ...lazy.sub import x" )
3000+ self .check_no_warning ("from . lazier import x" )
3001+ self .check_no_warning ("from . lazy_module import x" )
3002+ self .check_no_warning ("from . lazy.sub import x" )
3003+ self .check_no_warning ("from . sub.lazy import x" )
3004+ self .check_no_warning ("from lazy import x" )
3005+ self .check_no_warning ("from lazy.sub import x" )
3006+ self .check_no_warning ("lazy from . lazy import x" )
3007+ self .check_no_warning ("from . import lazy" )
3008+
3009+ def test_from_lazy_imports_as_error (self ):
3010+ import warnings
3011+ with warnings .catch_warnings ():
3012+ warnings .simplefilter ("error" , SyntaxWarning )
3013+ with self .assertRaisesRegex (
3014+ SyntaxError ,
3015+ re .escape ("did you mean 'lazy from . import'?" ),
3016+ ) as cm :
3017+ compile ("from . lazy import x" , "<test>" , "exec" )
3018+ self .assertEqual (cm .exception .lineno , 1 )
3019+ self .assertEqual (cm .exception .offset , 8 )
3020+ self .assertEqual (cm .exception .end_offset , 12 )
3021+
29453022
29463023class SyntaxErrorTestCase (unittest .TestCase ):
29473024
@@ -3618,6 +3695,22 @@ def inner():
36183695 lazy from collections import deque
36193696""" , "lazy from ... import not allowed inside functions" )
36203697
3698+ self ._check_error ("""\
3699+ from os lazy import path
3700+ """ , "use 'lazy from ... ' instead of 'from ... lazy import'" )
3701+ self ._check_error ("""\
3702+ from os.path lazy import join
3703+ """ , "use 'lazy from ... ' instead of 'from ... lazy import'" )
3704+ self ._check_error ("""\
3705+ from .mod lazy import join
3706+ """ , "use 'lazy from ... ' instead of 'from ... lazy import'" )
3707+ self ._check_error ("""\
3708+ from ..mod lazy import join
3709+ """ , "use 'lazy from ... ' instead of 'from ... lazy import'" )
3710+ self ._check_error ("""\
3711+ from ...mod lazy import join
3712+ """ , "use 'lazy from ... ' instead of 'from ... lazy import'" )
3713+
36213714 def test_lazy_import_valid_cases (self ):
36223715 """Test that lazy imports work at module level."""
36233716 # These should compile without errors
0 commit comments