@@ -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
@@ -3662,6 +3739,22 @@ def inner():
36623739 lazy from collections import deque
36633740""" , "lazy from ... import not allowed inside functions" )
36643741
3742+ self ._check_error ("""\
3743+ from os lazy import path
3744+ """ , "use 'lazy from ... ' instead of 'from ... lazy import'" )
3745+ self ._check_error ("""\
3746+ from os.path lazy import join
3747+ """ , "use 'lazy from ... ' instead of 'from ... lazy import'" )
3748+ self ._check_error ("""\
3749+ from .mod lazy import join
3750+ """ , "use 'lazy from ... ' instead of 'from ... lazy import'" )
3751+ self ._check_error ("""\
3752+ from ..mod lazy import join
3753+ """ , "use 'lazy from ... ' instead of 'from ... lazy import'" )
3754+ self ._check_error ("""\
3755+ from ...mod lazy import join
3756+ """ , "use 'lazy from ... ' instead of 'from ... lazy import'" )
3757+
36653758 def test_lazy_import_valid_cases (self ):
36663759 """Test that lazy imports work at module level."""
36673760 # These should compile without errors
0 commit comments