@@ -35,7 +35,7 @@ def sorted_imports(
3535 sections : Iterable [str ] = itertools .chain (parsed .sections , config .forced_separate )
3636
3737 if config .no_sections :
38- parsed .imports ["no_sections" ] = {"straight" : {}, "from" : {}}
38+ parsed .imports ["no_sections" ] = {"straight" : {}, "from" : {}, "lazy_straight" : {}, "lazy_from" : {} }
3939 base_sections : tuple [str , ...] = ()
4040 for section in sections :
4141 if section == "FUTURE" :
@@ -45,6 +45,12 @@ def sorted_imports(
4545 parsed .imports [section ].get ("straight" , {})
4646 )
4747 parsed .imports ["no_sections" ]["from" ].update (parsed .imports [section ].get ("from" , {}))
48+ parsed .imports ["no_sections" ]["lazy_straight" ].update (
49+ parsed .imports [section ].get ("lazy_straight" , {})
50+ )
51+ parsed .imports ["no_sections" ]["lazy_from" ].update (
52+ parsed .imports [section ].get ("lazy_from" , {})
53+ )
4854 sections = (* base_sections , "no_sections" )
4955
5056 output : list [str ] = []
@@ -126,6 +132,62 @@ def sorted_imports(
126132 section_output .extend (comments )
127133 section_output .append (str (line ))
128134
135+ # PEP 810 lazy imports always follow all eager imports within the section.
136+ lazy_straight_modules = parsed .imports [section ].get ("lazy_straight" , {})
137+ if not config .only_sections :
138+ lazy_straight_modules = sorting .sort (
139+ config ,
140+ lazy_straight_modules ,
141+ key = lambda key : sorting .module_key (
142+ key , config , section_name = section , straight_import = True
143+ ),
144+ reverse = config .reverse_sort ,
145+ )
146+
147+ lazy_from_modules = parsed .imports [section ].get ("lazy_from" , {})
148+ if not config .only_sections :
149+ lazy_from_modules = sorting .sort (
150+ config ,
151+ lazy_from_modules ,
152+ key = lambda key : sorting .module_key (key , config , section_name = section ),
153+ reverse = config .reverse_sort ,
154+ )
155+
156+ lazy_straight_imports = _with_straight_imports (
157+ parsed ,
158+ config ,
159+ lazy_straight_modules ,
160+ section ,
161+ remove_imports ,
162+ f"lazy { import_type } " ,
163+ import_key = "lazy_straight" ,
164+ )
165+ lazy_from_imports = _with_from_imports (
166+ parsed ,
167+ config ,
168+ lazy_from_modules ,
169+ section ,
170+ remove_imports ,
171+ f"lazy { import_type } " ,
172+ import_key = "lazy_from" ,
173+ )
174+
175+ lazy_lines_between = ["" ] * (
176+ config .lines_between_types
177+ if lazy_from_modules and lazy_straight_modules
178+ else 0
179+ )
180+ if config .from_first or section == "FUTURE" :
181+ lazy_section_output = lazy_from_imports + lazy_lines_between + lazy_straight_imports
182+ else :
183+ lazy_section_output = lazy_straight_imports + lazy_lines_between + lazy_from_imports
184+
185+ if lazy_section_output :
186+ if section_output :
187+ section_output += ["" ] * config .lines_between_types + lazy_section_output
188+ else :
189+ section_output = lazy_section_output
190+
129191 section_name = section
130192 no_lines_before = section_name in config .no_lines_before
131193
@@ -254,14 +316,21 @@ def _with_from_imports(
254316 section : str ,
255317 remove_imports : list [str ],
256318 import_type : str ,
319+ import_key : str = "from" ,
257320) -> list [str ]:
258321 output : list [str ] = []
259322 for module in from_modules :
260323 if module in remove_imports :
261324 continue
262325
263- import_start = f"from { module } { import_type } "
264- from_imports = list (parsed .imports [section ]["from" ][module ])
326+ # For lazy from imports the keyword order is ``lazy from X import ...``
327+ # rather than the naive ``from X lazy import ...`` that would result from
328+ # placing ``import_type`` between the module name and ``import``.
329+ if import_type .startswith ("lazy " ):
330+ import_start = f"lazy from { module } import "
331+ else :
332+ import_start = f"from { module } { import_type } "
333+ from_imports = list (parsed .imports [section ][import_key ][module ])
265334 if (
266335 not config .no_inline_sort
267336 or (config .force_single_line and module not in config .single_line_exclusions )
@@ -299,7 +368,7 @@ def _with_from_imports(
299368 for from_import in copy .copy (from_imports ):
300369 if from_import in as_imports :
301370 idx = from_imports .index (from_import )
302- if parsed .imports [section ]["from" ][module ][from_import ]:
371+ if parsed .imports [section ][import_key ][module ][from_import ]:
303372 from_imports [(idx + 1 ) : (idx + 1 )] = as_imports .pop (from_import )
304373 else :
305374 from_imports [idx : (idx + 1 )] = as_imports .pop (from_import )
@@ -347,7 +416,7 @@ def _with_from_imports(
347416 )
348417 if from_import in as_imports :
349418 if (
350- parsed .imports [section ]["from" ][module ][from_import ]
419+ parsed .imports [section ][import_key ][module ][from_import ]
351420 and not only_show_as_imports
352421 ):
353422 output .append (
@@ -403,7 +472,7 @@ def _with_from_imports(
403472 parsed .categorized_comments ["straight" ].get (f"{ module } .{ from_import } " ) or []
404473 )
405474 if (
406- parsed .imports [section ]["from" ][module ][from_import ]
475+ parsed .imports [section ][import_key ][module ][from_import ]
407476 and not only_show_as_imports
408477 ):
409478 specific_comment = (
@@ -540,7 +609,7 @@ def _with_from_imports(
540609 from_imports [0 ] not in as_imports
541610 or (
542611 config .combine_as_imports
543- and parsed .imports [section ]["from" ][module ][from_import ]
612+ and parsed .imports [section ][import_key ][module ][from_import ]
544613 )
545614 ):
546615 from_import_section .append (from_imports .pop (0 ))
@@ -633,6 +702,7 @@ def _with_straight_imports(
633702 section : str ,
634703 remove_imports : list [str ],
635704 import_type : str ,
705+ import_key : str = "straight" ,
636706) -> list [str ]:
637707 output : list [str ] = []
638708
@@ -675,7 +745,7 @@ def _with_straight_imports(
675745
676746 import_definition = []
677747 if module in parsed .as_map ["straight" ]:
678- if parsed .imports [section ]["straight" ][module ]:
748+ if parsed .imports [section ][import_key ][module ]:
679749 import_definition .append ((f"{ import_type } { module } " , module ))
680750 import_definition .extend (
681751 (f"{ import_type } { module } as { as_import } " , f"{ module } as { as_import } " )
0 commit comments