Skip to content

reflow-imports

reflow-imports splits a from-import that overflows import-line-length into a run of from ... import ... statements. Each statement repeats the module prefix and packs as many alphabetized names as fit before the next line opens, so the imported names start at the same column after import on every line and a deep module path never pushes them rightward.

Two further facets change what one import line carries. split-multi-module breaks a comma-joined import a, b, the form pycodestyle flags as E401, into one import statement per module, since those commas separate distinct modules and nothing ties them to one line. merge-members runs the other way on from-imports, merging every from pkg import ... statement of one module within an import run onto a single line that names each member once, so the module appears once with its members after it. A from pkg import a, b line is never broken at its commas, because those commas separate members of one module rather than modules.

The rule runs after group-imports and before alphabetize-siblings, so each module it splits onto its own line is placed in its import group in the same pass, and the merged member list is written in the order alphabetize-siblings would leave it. Setting alphabetize-siblings = false keeps the authored member order across both moves.

The rule acts on single-line imports that open their own line. A from ... import *, a from-import already within budget, a ;-joined statement, and a parenthesized multi-line import stay as written, and a lone name whose own line still overflows keeps its place rather than splitting further. A backslash-continued import arrives here already rejoined, since shed-backslash-continuations removes the escape well ahead of it, so every move the rule makes reads the single line that rejoin produced. A comment anywhere on the lines a merge would fold together blocks the merge, since folding those statements together would leave the comment describing nothing, and a notebook's cell boundary blocks a merge the same way.

Pair with align-imports to align the import keyword across the resulting run. The rule forecasts the block as the rules that run between it and align-imports will lay it out, with each merged member list folded into its lead statement and each run sorted and placed as alphabetize-siblings and band-constants leave it. Every row it writes therefore sits at the column align-imports settles that run to, and a second pass changes nothing.

Configuration

KeyTypeDefaultMeaning
enabledbooltrueTurns the rule on or off.
merge-membersbooltrueMerges repeated from <module> import … statements into one statement naming each member once, in the order alphabetize-siblings gives them. false keeps each statement as written.
split-multi-modulebooltrueBreaks a comma-joined import a, b into one import statement per module. false keeps the comma-joined form.

Each move sits behind its own facet, so a project can switch one off without touching the others. split-multi-module gates the comma-joined break and merge-members the same-module merge, both on by default, and the width split runs whatever either is set to.

The wrap budget comes from the top-level import-line-length key (default 120), which governs the import wrap independently of code-line-length. An import is a list of names alphabetize-siblings already sorts, so it stays scannable at a width where dense expression code would not, which is why it gets more horizontal room before a wrap pays off. Setting import-line-length to false drops the dedicated budget, so the import wrap falls back to code-line-length.

The Canonical Case

from pkg.sub import alpha, beta, delta, epsilon, gamma runs past the import-line-length budget of 40. The statement splits into a run of repeated-prefix lines, each packing the names in order up to the budget before the next opens, so alpha, beta, delta sits on the first and epsilon, gamma on the second.

from pkg.sub import alpha, beta, delta
from pkg.sub import epsilon, gamma
python

More Examples

With import-line-length set to 40, from pkg import alpha, beta, gamma, delta # noqa: F401 runs past the budget and splits across two statements.

The trailing # noqa: F401 marker repeats on every line the split writes, so each name it covered still carries it, and a linter reading the marker suppresses the same set of names after the split as before it.

import os, sys names two modules on one line. split-multi-module splits it into one import statement per module, the form group-imports and alphabetize-siblings then order, because the comma joins two distinct modules that share nothing beyond the line.

from ..pkg import alpha, beta, delta, gamma runs past the import-line-length budget of 35, so the names split across two statements. Each line repeats the two leading dots in its prefix, so both open with from ..pkg import.

With import-line-length set to 40, from pkg import alpha as a, beta as b, gamma as g runs past the budget and splits. Each name keeps its as alias on the line it moves to, so both statements repeat the from pkg import prefix and gamma as g moves whole to the second line.

from pkg.sub import alpha, beta, delta, epsilon, gamma sits inside load and runs past the import-line-length budget of 44. It splits into repeated-prefix statements that each carry the block indent, and the budget counts the indent columns, so each packed line fits within the measure.

import json as parser, re as regex names two modules on one line, each with an as alias. The line splits into one import statement per module, and each as clause stays with its own module, so json as parser and re as regex come out intact as two single-alias statements, the shape align-imports can later pad to one as column.

Three from pkg.sub import statements carry alpha, beta, delta, and epsilon, gamma. The names gather into one list and repack to the import-line-length budget of 40, coming out as alpha, beta, delta then epsilon, gamma, because the merge and the width split are written together rather than the merge producing one over-long line first.

from pkg import alpha and from pkg import beta sit either side of from other import thing. The two pkg statements still merge onto one line, written where alpha first appeared with other on the line below, because the merge reads the whole block of imports rather than adjacent statements alone.

With merge-members = false, from pkg import beta and from pkg import alpha sit on consecutive lines under import os, sys. The two pkg statements stay apart, whereas split-multi-module still splits import os, sys into one statement per module, because turning off one facet leaves the others running.

from pkg import alpha and from pkg import beta name the same module on consecutive lines. merge-members merges them into one line carrying both names, so pkg appears once with alpha and beta listed in the order the source wrote them.

With split-multi-module = false, import os, sys sits above from pkg import alpha and from pkg import beta. The comma-joined import os, sys stays exactly as written, whereas merge-members still gathers the two pkg statements onto one line, because turning off one facet leaves the rest of reflow-imports running.

No Change

from pkg import beta carries a trailing comment, and from pkg import alpha sits below it. Neither line merges, because the comment describes the beta statement alone and a merged line would put it beside both names, so the rule leaves every pkg statement in place whenever one of them carries a comment.

No Change

from pkg import beta sits above from pkg import alpha, and the alpha line carries a trailing comment. Both pkg statements stay in place with the comment where its author wrote it, because merging alpha into the beta line would delete the line the comment sits on and take the comment with it, so the merge skips the module.

No Change

from verylongpackagename import singleverylongmembername runs past the import-line-length budget of 30 on its own. The line stays as written and overflows the budget whole, because a statement carrying one name has no comma left to break at.

No Change

from collections import * runs past the import-line-length budget of 20. It passes through unchanged, because a star import carries no member list to split, leaving nothing to move onto a second line.

No Change

from pkg import alpha, beta measures 27 characters against the import-line-length budget of 40. It keeps its single line, because the split reads only imports that overflow and this one fits with room to spare.

  1. import sys, os and import myapp.core, abc each name two modules in one statement, with myapp in first-party. reflow-imports splits each into one module per line ahead of group-imports and alphabetize-siblings, so every split-off module reaches its own group and its sorted position, and myapp.core ends up in the local section rather than beside the stdlib abc it was joined to.

  2. from pkg import a is unread and sits directly under the # Local imports comment, with a blank line between it and from pkg import b. reflow-imports merges the two statements across that blank line, so when prune-inert-imports removes a, from pkg import b moves up onto the line a had, the blank line goes with b's old position, and the comment ends up heading the import that survives.

  3. from .pgen2 import token is the first line under the # Local imports comment, and nothing in the module reads it. reflow-imports merges that line into its .pgen2 sibling, so once it goes the comment heads from .pgen2 import driver. prune-inert-imports moves the sibling onto the vacated line rather than leaving the move to the merge on a later pass, which keeps a real import under the comment at every step.

  4. LIMIT = 3 sits between from pkg import alpha and from pkg import beta, which would ordinarily keep the two apart. band-constants moves the constant below the imports, and reflow-imports merges the two pkg statements onto one line in the same run, because it measures against the order the move leaves rather than the order as written, so no second pass is needed once the constant has moved.

  5. from pkg import a and from pkg import b are both unread, and a is the line the # Local imports comment heads. from pkg import b carries no comment and is removed, and with it gone there is no sibling left for reflow-imports to merge a into, so from pkg import a stays under its comment rather than being removed too, because removing it would leave the comment over nothing.

  6. from pkg import a is never read and is the line the # Local imports comment heads, with X = 1 between it and from pkg import b. band-constants moves X = 1 below the imports, which brings the two pkg statements together, and with them adjacent from pkg import b moves up onto the line a vacates as a is removed, leaving the comment heading a real import rather than a gap.