Skip to content

Commit 66f78c8

Browse files
authored
Merge pull request #818 from asottile/aliases-multi-from-imports
fix import rewriting with aliases in multi-from
2 parents f8932f0 + 524e94f commit 66f78c8

File tree

2 files changed

+14
-3
lines changed

2 files changed

+14
-3
lines changed

pyupgrade/_plugins/imports.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,7 @@ class FromImport(NamedTuple):
281281
mod_start: int
282282
mod_end: int
283283
names: tuple[int, ...]
284+
ends: tuple[int, ...]
284285
end: int
285286

286287
@classmethod
@@ -310,11 +311,14 @@ def parse(cls, i: int, tokens: list[Token]) -> FromImport:
310311
for j in range(import_token + 1, end)
311312
if tokens[j].name == 'NAME'
312313
]
314+
ends_by_offset = {}
313315
for i in reversed(range(len(names))):
314316
if tokens[names[i]].src == 'as':
317+
ends_by_offset[names[i - 1]] = names[i + 1]
315318
del names[i:i + 2]
319+
ends = tuple(ends_by_offset.get(pos, pos) for pos in names)
316320

317-
return cls(start, mod_start, mod_end + 1, tuple(names), end)
321+
return cls(start, mod_start, mod_end + 1, tuple(names), ends, end)
318322

319323
def remove_self(self, tokens: list[Token]) -> None:
320324
del tokens[self.start:self.end]
@@ -327,10 +331,10 @@ def remove_parts(self, tokens: list[Token], idxs: list[int]) -> None:
327331
if idx == 0: # look forward until next name and del
328332
del tokens[self.names[idx]:self.names[idx + 1]]
329333
else: # look backward for comma and del
330-
j = end = self.names[idx]
334+
j = self.names[idx]
331335
while tokens[j].src != ',':
332336
j -= 1
333-
del tokens[j:end + 1]
337+
del tokens[j:self.ends[idx] + 1]
334338

335339

336340
def _alias_to_s(alias: ast.alias) -> str:

tests/features/import_replaces_test.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,13 @@ def test_mock_noop_keep_mock():
305305
'from collections.abc import Callable\n',
306306
id='typing.Callable is rewritable in 3.10+ only',
307307
),
308+
pytest.param(
309+
'from typing import Optional, Sequence as S\n',
310+
(3, 10),
311+
'from typing import Optional\n'
312+
'from collections.abc import Sequence as S\n',
313+
id='aliasing in multi from import',
314+
),
308315
),
309316
)
310317
def test_import_replaces(s, min_version, expected):

0 commit comments

Comments
 (0)