Skip to content

Keep add_imports below a prefixed module docstring - #2626

Merged
DanielNoord merged 3 commits into
PyCQA:mainfrom
Eljees:fix/1893-add-imports-below-prefixed-docstring
Aug 26, 2026
Merged

Keep add_imports below a prefixed module docstring#2626
DanielNoord merged 3 commits into
PyCQA:mainfrom
Eljees:fix/1893-add-imports-below-prefixed-docstring

Conversation

@Eljees

@Eljees Eljees commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Closes #1893.

add_imports inserts the import above the module docstring when that docstring carries a string prefix:

>>> import isort
>>> src = 'r\"\"\"module docstring\n\"\"\"\nfrom __future__ import annotations\n'
>>> print(isort.code(src, add_imports=["from __future__ import annotations"]))
from __future__ import annotations

r"""module docstring
"""
from __future__ import annotations

The import is both moved above the docstring and duplicated, because the file already contained it. Reported by @Skylion007 in 2022 and hit again by @sodul in 2024.

Cause

The guard in isort/core.py that stops the insertion tests the raw line:

and not line.lstrip().startswith(COMMENT_INDICATORS)

It only recognises a docstring that begins with a quote. r"""... begins with a letter, so the guard misses it and the import goes in above the docstring.

A single-line prefixed docstring escapes this by accident: the neighbouring endswith(DOCSTRING_INDICATORS) guard catches it. Only multi-line prefixed docstrings are affected. Every legal prefix and both quote flavours break; an unprefixed docstring never does.

(The report points at isort/parse.py:218; the actual place is the guard above.)

Fix

A small helper that strips a legal string prefix, but only when a quote follows it immediately -- so ordinary identifiers like rating = 1 are left alone.

Tests

One regression test in tests/unit/test_regressions.py, three blocks: the reporter's exact input; a control that the import is still added, below the docstring; and a sweep over 12 prefixes x 2 quote flavours. It fails on main with the duplicated import shown above.

pytest tests/unit gives 615 passed with this change against 614 on a clean tree -- the same 3 failures in both runs (test_importable and two test_ticketed_features cases needing the example plugin packages), so no regressions. flake8, ruff check, ruff format --check, isort --profile hug --check and mypy are clean on both changed files.

@DanielNoord
DanielNoord force-pushed the fix/1893-add-imports-below-prefixed-docstring branch from 7faf53b to e533ef0 Compare August 17, 2026 20:57
@codecov

codecov Bot commented Aug 17, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.37%. Comparing base (0cba6f6) to head (6436e6a).

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #2626   +/-   ##
=======================================
  Coverage   99.36%   99.37%           
=======================================
  Files          41       41           
  Lines        3172     3180    +8     
  Branches      684      686    +2     
=======================================
+ Hits         3152     3160    +8     
  Misses         12       12           
  Partials        8        8           
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Comment thread tests/unit/test_regressions.py Outdated
)

# Every legal prefix, in both quote flavours and both cases.
for prefix in ("r", "R", "b", "B", "f", "F", "u", "U", "rb", "bR", "Fr", "rf"):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we reuse STRING_PREFIXES here?

Comment thread isort/core.py Outdated
and not was_in_quote
and not import_section
and not line.lstrip().startswith(COMMENT_INDICATORS)
and not _strip_string_prefix(line.lstrip()).startswith(COMMENT_INDICATORS)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably better to create one shared "Is start of a comment" utility instead to make clear what we are testing for here.

Eljees added 3 commits August 22, 2026 09:18
The guard that stops isort inserting add_imports above a module docstring tests the raw line against COMMENT_INDICATORS, so it only recognises a docstring that starts with a quote. A docstring carrying a legal string prefix (r, b, f, u or a combination) starts with a letter, the guard misses it, and the import is inserted above the docstring - and, because the file already contained that import, duplicated. Single-line prefixed docstrings escape this by accident, via the neighbouring endswith(DOCSTRING_INDICATORS) guard; multi-line ones do not. Strip a legal string prefix before the quote-based check. Closes PyCQA#1893.
Signed-off-by: Eljees <3.14hell@gmail.com>
Addresses the two review comments.

The quote-based test in `process` is now `_is_comment_or_string_start`,
so the call site says what it is asking rather than composing a strip and
a startswith inline.

The regression test iterates `isort.core.STRING_PREFIXES` instead of
repeating the prefixes, so the two cannot drift apart.
@Eljees
Eljees force-pushed the fix/1893-add-imports-below-prefixed-docstring branch from e533ef0 to 6436e6a Compare August 22, 2026 09:20
@Eljees

Eljees commented Aug 22, 2026

Copy link
Copy Markdown
Contributor Author

Both done, thanks — and the branch is rebased onto current main.

The predicate has a name. _is_comment_or_string_start(line) replaces the inline _strip_string_prefix(line.lstrip()).startswith(COMMENT_INDICATORS) at the call site in process, so the condition reads as the question it is asking. I did not fold the other startswith("#") sites into it: those ask "is this a comment", while this one asks "is this a comment or a string of any kind", and the second is what the docstring case needs.

The test reuses STRING_PREFIXES. It now iterates sorted(STRING_PREFIXES) and derives the case variants from each prefix rather than repeating a hand-written list, so the two cannot drift:

for prefix in sorted(STRING_PREFIXES):
    for cased in sorted({prefix, prefix.upper(), prefix.capitalize()}):
        for quote in ('"""', "'''"):

Measured

The reported input, run against the two revisions of core.py:

isort/core.py isort.code(r-prefixed docstring + import, add_imports=[same import])
current main the import is emitted a second time above the docstring
this branch unchanged, as it should be

pytest tests/unit: 621 passed, 1 skipped, 2 failed — and those two, test_isort_supports_shared_profiles_issue_970 and test_sort_configurable_sort_issue_1732, fail identically on a clean checkout of main in this environment (they want an example profile and a natural_plus sort order that come from plugins that are not installed). main alone gives 620 passed, so the delta is exactly the one test this PR adds.

One thing the rebase fixed rather than the review: before it, tests/unit/test_importable.py::test_importable failed on the branch and passed on main — the branch simply predated the pytest.raises(SystemExit) change to that file. Worth knowing it was staleness and not this change.

ruff check and ruff format --check are clean on both files.

@DanielNoord
DanielNoord added this pull request to the merge queue Aug 26, 2026
Merged via the queue into PyCQA:main with commit 727d119 Aug 26, 2026
43 checks passed
mergify Bot added a commit to ArcadeData/arcadedb that referenced this pull request Aug 30, 2026
…[skip ci]

Bumps [https://github.com/pycqa/isort](https://github.com/pycqa/isort) from 8.0.1 to 9.0.0.
Release notes

*Sourced from [https://github.com/pycqa/isort's releases](https://github.com/pycqa/isort/releases).*

> 9.0.0
> -----
>
> `isort` `9.0.0` is the result of several alpha and beta releases, as well as a small number of fixes added after the last beta. For release notes for the individual alphas and betas we would like to refer to:
>
> * [9.0.0a2](https://github.com/PyCQA/isort/releases/tag/9.0.0a2)
> * [9.0.0a3](https://github.com/PyCQA/isort/releases/tag/9.0.0a3)
> * [9.0.0b1](https://github.com/PyCQA/isort/releases/tag/9.0.0b1)
> * [9.0.0b2](https://github.com/PyCQA/isort/releases/tag/9.0.0b2)
> * [9.0.0b5](https://github.com/PyCQA/isort/releases/tag/9.0.0b5)
>
> *Skipped version numbers are the result of changes to our release infrastructure that broke while creating the actual releases.*
>
> Please find below the full release notes for version `9.0.0`, the newest release of `isort` after version `8.0.1`.
>
> ---
>
> `isort` `9.0.0` contains some significant changes and improvements. Most notably there is now support for Python 3.15 and its `lazy` imports and we have included several performance improvements as well as providing `mypyc` compiled wheels for all major platforms and supported versions of Python. In our own tests we saw speeds ups of more than 2x and 3x times, but this is highly dependent on the codebase `isort` needs to inspect.
>
> The full list of changes is as follows:
>
> 💥 Breaking Changes
> -----------------------
>
> * Remove logic for deprecated options ([#2498](https://redirect.github.com/pycqa/isort/issues/2498)) [`@​DanielNoord`](https://github.com/DanielNoord)
>
> 🚀 Features
> -----------------
>
> * Sort lazy import statements ([#2503](https://redirect.github.com/pycqa/isort/issues/2503)) [`@​DanielNoord`](https://github.com/DanielNoord)
> * Add initial support for Python 3.15 ([#2466](https://redirect.github.com/pycqa/isort/issues/2466)) [`@​DanielNoord`](https://github.com/DanielNoord)
> * Compile with `mypyc` by [`@​DanielNoord`](https://github.com/DanielNoord) in [PyCQA/isort#2586](https://redirect.github.com/PyCQA/isort/pull/2586)
> * Cache calls to `posixpath.abspath` by [`@​DanielNoord`](https://github.com/DanielNoord) in [PyCQA/isort#2606](https://redirect.github.com/PyCQA/isort/pull/2606)
> * Consider private `stdlib` modules to be `stdlib` ([#2295](https://redirect.github.com/pycqa/isort/issues/2295)) [`@​devdanzin`](https://github.com/devdanzin)
> * Add CLI Flag for --forced-separate ([PyCQA/isort#2367](https://redirect.github.com/PyCQA/isort/pull/2367)) [`@​hirak99`](https://github.com/hirak99)
> * Add separate\_packages option ([#2313](https://redirect.github.com/pycqa/isort/issues/2313)) [`@​alex-liang3`](https://github.com/alex-liang3)
>
> 🪲 Fixes
> --------------
>
> * Fix inline comment duplication across merged `from X import` lines ([#2499](https://redirect.github.com/pycqa/isort/issues/2499)) [`@​copilot-swe-agent`](https://github.com/copilot-swe-agent)
> * Fix src glob patterns passed via CLI ([#2497](https://redirect.github.com/pycqa/isort/issues/2497)) [`@​ReinerBRO`](https://github.com/ReinerBRO)
> * Fix opening-line comment moving to alias attribute line on wrapped imports ([#2491](https://redirect.github.com/pycqa/isort/issues/2491)) [`@​copilot-swe-agent`](https://github.com/copilot-swe-agent)
> * Fix multi\_line\_output=3/5 ignored when wrapping single imports with inline comments ([#2474](https://redirect.github.com/pycqa/isort/issues/2474)) [`@​copilot-swe-agent`](https://github.com/copilot-swe-agent)
> * Fix false positive in `check_code` when using `float_to_top` + `add_imports` ([#2492](https://redirect.github.com/pycqa/isort/issues/2492)) [`@​copilot-swe-agent`](https://github.com/copilot-swe-agent)
> * Fix: preserve bare `#` inline comments on imports ([#2488](https://redirect.github.com/pycqa/isort/issues/2488)) [`@​copilot-swe-agent`](https://github.com/copilot-swe-agent)
> * Fix grouping of non-aliased imports when mixed with aliased imports from the same module ([#2470](https://redirect.github.com/pycqa/isort/issues/2470)) [`@​copilot-swe-agent`](https://github.com/copilot-swe-agent)
> * Fix [PyCQA/isort#2500](https://redirect.github.com/PyCQA/isort/issues/2500): trusted publishing by [`@​staticdev`](https://github.com/staticdev) in [PyCQA/isort#2521](https://redirect.github.com/PyCQA/isort/pull/2521)
> * Fix git\_hook lazy=True option by [`@​sparrowt`](https://github.com/sparrowt) in [PyCQA/isort#2542](https://redirect.github.com/PyCQA/isort/pull/2542)
> * Honor `# isort: off/on/split` during `float_to_top` preprocessing with CRLF input by [`@​DanielNoord`](https://github.com/DanielNoord) with [`@​Copilot`](https://github.com/Copilot) in [PyCQA/isort#2553](https://redirect.github.com/PyCQA/isort/pull/2553)
> * Fix --sort-reexports crash with non-seekable streams (e.g. stdin) by [`@​Abdu-Ahmed`](https://github.com/Abdu-Ahmed) in [PyCQA/isort#2547](https://redirect.github.com/PyCQA/isort/pull/2547)
> * Fix non-idempotent output with split\_on\_trailing\_comma and a non-default wrap mode by [`@​sarathfrancis90`](https://github.com/sarathfrancis90) in [PyCQA/isort#2554](https://redirect.github.com/PyCQA/isort/pull/2554)
> * Fix non-idempotent NOQA wrap mode with imports that carry their own comment by [`@​sarathfrancis90`](https://github.com/sarathfrancis90) in [PyCQA/isort#2556](https://redirect.github.com/PyCQA/isort/pull/2556)
> * Fix NOQA wrap mode accumulating spaces before the comment on each run by [`@​sarathfrancis90`](https://github.com/sarathfrancis90) in [PyCQA/isort#2558](https://redirect.github.com/PyCQA/isort/pull/2558)
> * Fix NOQA not added to long imports in several output paths by [`@​urayoru113`](https://github.com/urayoru113) in [PyCQA/isort#2568](https://redirect.github.com/PyCQA/isort/pull/2568)
> * Honor `# isort: skip` when a `__future__` import is present ([#2092](https://redirect.github.com/pycqa/isort/issues/2092)) by [`@​apoorvdarshan`](https://github.com/apoorvdarshan) in [PyCQA/isort#2574](https://redirect.github.com/PyCQA/isort/pull/2574)

... (truncated)


Changelog

*Sourced from [https://github.com/pycqa/isort's changelog](https://github.com/PyCQA/isort/blob/main/CHANGELOG.md).*

> ### 9.0.0 August 26 2026
>
> * Remove logic for deprecated options ([#2498](https://redirect.github.com/pycqa/isort/issues/2498)) [`@​DanielNoord`](https://github.com/DanielNoord)
> * Sort lazy import statements ([#2503](https://redirect.github.com/pycqa/isort/issues/2503)) [`@​DanielNoord`](https://github.com/DanielNoord)
> * Add initial support for Python 3.15 ([#2466](https://redirect.github.com/pycqa/isort/issues/2466)) [`@​DanielNoord`](https://github.com/DanielNoord)
> * Compile with `mypyc` by [`@​DanielNoord`](https://github.com/DanielNoord) in [PyCQA/isort#2586](https://redirect.github.com/PyCQA/isort/pull/2586)
> * Cache calls to `posixpath.abspath` by [`@​DanielNoord`](https://github.com/DanielNoord) in [PyCQA/isort#2606](https://redirect.github.com/PyCQA/isort/pull/2606)
> * Consider private `stdlib` modules to be `stdlib` ([#2295](https://redirect.github.com/pycqa/isort/issues/2295)) [`@​devdanzin`](https://github.com/devdanzin)
> * Add CLI Flag for --forced-separate ([PyCQA/isort#2367](https://redirect.github.com/PyCQA/isort/pull/2367)) [`@​hirak99`](https://github.com/hirak99)
> * Add separate\_packages option ([#2313](https://redirect.github.com/pycqa/isort/issues/2313)) [`@​alex-liang3`](https://github.com/alex-liang3)
> * Fix inline comment duplication across merged `from X import` lines ([#2499](https://redirect.github.com/pycqa/isort/issues/2499)) [`@​copilot-swe-agent`](https://github.com/copilot-swe-agent)
> * Fix src glob patterns passed via CLI ([#2497](https://redirect.github.com/pycqa/isort/issues/2497)) [`@​ReinerBRO`](https://github.com/ReinerBRO)
> * Fix opening-line comment moving to alias attribute line on wrapped imports ([#2491](https://redirect.github.com/pycqa/isort/issues/2491)) [`@​copilot-swe-agent`](https://github.com/copilot-swe-agent)
> * Fix multi\_line\_output=3/5 ignored when wrapping single imports with inline comments ([#2474](https://redirect.github.com/pycqa/isort/issues/2474)) [`@​copilot-swe-agent`](https://github.com/copilot-swe-agent)
> * Fix false positive in `check_code` when using `float_to_top` + `add_imports` ([#2492](https://redirect.github.com/pycqa/isort/issues/2492)) [`@​copilot-swe-agent`](https://github.com/copilot-swe-agent)
> * Fix: preserve bare `#` inline comments on imports ([#2488](https://redirect.github.com/pycqa/isort/issues/2488)) [`@​copilot-swe-agent`](https://github.com/copilot-swe-agent)
> * Fix grouping of non-aliased imports when mixed with aliased imports from the same module ([#2470](https://redirect.github.com/pycqa/isort/issues/2470)) [`@​copilot-swe-agent`](https://github.com/copilot-swe-agent)
> * Fix [PyCQA/isort#2500](https://redirect.github.com/PyCQA/isort/issues/2500): trusted publishing by [`@​staticdev`](https://github.com/staticdev) in [PyCQA/isort#2521](https://redirect.github.com/PyCQA/isort/pull/2521)
> * Fix git\_hook lazy=True option by [`@​sparrowt`](https://github.com/sparrowt) in [PyCQA/isort#2542](https://redirect.github.com/PyCQA/isort/pull/2542)
> * Honor `# isort: off/on/split` during `float_to_top` preprocessing with CRLF input by [`@​DanielNoord`](https://github.com/DanielNoord) with [`@​Copilot`](https://github.com/Copilot) in [PyCQA/isort#2553](https://redirect.github.com/PyCQA/isort/pull/2553)
> * Fix --sort-reexports crash with non-seekable streams (e.g. stdin) by [`@​Abdu-Ahmed`](https://github.com/Abdu-Ahmed) in [PyCQA/isort#2547](https://redirect.github.com/PyCQA/isort/pull/2547)
> * Fix non-idempotent output with split\_on\_trailing\_comma and a non-default wrap mode by [`@​sarathfrancis90`](https://github.com/sarathfrancis90) in [PyCQA/isort#2554](https://redirect.github.com/PyCQA/isort/pull/2554)
> * Fix non-idempotent NOQA wrap mode with imports that carry their own comment by [`@​sarathfrancis90`](https://github.com/sarathfrancis90) in [PyCQA/isort#2556](https://redirect.github.com/PyCQA/isort/pull/2556)
> * Fix NOQA wrap mode accumulating spaces before the comment on each run by [`@​sarathfrancis90`](https://github.com/sarathfrancis90) in [PyCQA/isort#2558](https://redirect.github.com/PyCQA/isort/pull/2558)
> * Fix NOQA not added to long imports in several output paths by [`@​urayoru113`](https://github.com/urayoru113) in [PyCQA/isort#2568](https://redirect.github.com/PyCQA/isort/pull/2568)
> * Honor `# isort: skip` when a `__future__` import is present ([#2092](https://redirect.github.com/pycqa/isort/issues/2092)) by [`@​apoorvdarshan`](https://github.com/apoorvdarshan) in [PyCQA/isort#2574](https://redirect.github.com/PyCQA/isort/pull/2574)
> * fix: make sorted `__all__` and literals black-compatible ([#2280](https://redirect.github.com/pycqa/isort/issues/2280)) by [`@​lord-haffi`](https://github.com/lord-haffi) in [PyCQA/isort#2576](https://redirect.github.com/PyCQA/isort/pull/2576)
> * Honor skip comments when sorting reexports by [`@​sakshichitnis27`](https://github.com/sakshichitnis27) in [PyCQA/isort#2581](https://redirect.github.com/PyCQA/isort/pull/2581)
> * Keep aliased import when the plain name carries a comment by [`@​sarathfrancis90`](https://github.com/sarathfrancis90) in [PyCQA/isort#2567](https://redirect.github.com/PyCQA/isort/pull/2567)
> * fix: don't crash on --config-root without --resolve-all-configs by [`@​Gooh456`](https://github.com/Gooh456) in [PyCQA/isort#2597](https://redirect.github.com/PyCQA/isort/pull/2597)
> * fix: check\_code misses lines\_before\_imports-only changes ([#2242](https://redirect.github.com/pycqa/isort/issues/2242)) by [`@​gaoflow`](https://github.com/gaoflow) in [PyCQA/isort#2563](https://redirect.github.com/PyCQA/isort/pull/2563)
> * Fix preservation of form-feed blank lines by [`@​utkarshalpha`](https://github.com/utkarshalpha) in [PyCQA/isort#2599](https://redirect.github.com/PyCQA/isort/pull/2599)
> * Small clean up and fix inconsistency in handling of `*` imports by [`@​DanielNoord`](https://github.com/DanielNoord) in [PyCQA/isort#2619](https://redirect.github.com/PyCQA/isort/pull/2619)
> * Fix word-wrapping of 'from ... import \*' into invalid Python ([#2267](https://redirect.github.com/pycqa/isort/issues/2267)) by [`@​sudorm-rf0`](https://github.com/sudorm-rf0) in [PyCQA/isort#2624](https://redirect.github.com/PyCQA/isort/pull/2624)
> * Fix pylint disable-next comments at the start of imports by [`@​Neallin-917`](https://github.com/Neallin-917) in [PyCQA/isort#2628](https://redirect.github.com/PyCQA/isort/pull/2628)
> * Keep add\_imports below a prefixed module docstring by [`@​Eljees`](https://github.com/Eljees) in [PyCQA/isort#2626](https://redirect.github.com/PyCQA/isort/pull/2626)
> * Add read the docs configuration ([#2504](https://redirect.github.com/pycqa/isort/issues/2504)) [`@​DanielNoord`](https://github.com/DanielNoord)
> * Remove unused and broken dependencies ([#2517](https://redirect.github.com/pycqa/isort/issues/2517)) [`@​DanielNoord`](https://github.com/DanielNoord)
> * Remove `Any` from `parse.py` ([#2516](https://redirect.github.com/pycqa/isort/issues/2516)) [`@​DanielNoord`](https://github.com/DanielNoord)
> * Bring documentation in line with old documentation ([#2507](https://redirect.github.com/pycqa/isort/issues/2507)) [`@​DanielNoord`](https://github.com/DanielNoord)
> * Sync profile docs with implementation ([#2495](https://redirect.github.com/pycqa/isort/issues/2495)) [`@​copilot-swe-agent`](https://github.com/copilot-swe-agent)
> * Fix the playground ([#2494](https://redirect.github.com/pycqa/isort/issues/2494)) [`@​DanielNoord7`](https://github.com/DanielNoord7)) [`@​hirak99`](https://github.com/hirak99)
> * Remove unused \_ENCODING\_PATTERN regex and re import by [`@​duriantaco`](https://github.com/duriantaco) in [PyCQA/isort#2525](https://redirect.github.com/PyCQA/isort/pull/2525)
> * Remove references to defunct `git_ignore` config by [`@​sparrowt`](https://github.com/sparrowt) in [PyCQA/isort#2531](https://redirect.github.com/PyCQA/isort/pull/2531)
> * Fix broken relative links in README and CHANGELOG for both GitHub and Sphinx by [`@​rohitshinde08`](https://github.com/rohitshinde08) in [PyCQA/isort#2530](https://redirect.github.com/PyCQA/isort/pull/2530)
> * Bump vendored `tomli` by [`@​DanielNoord`](https://github.com/DanielNoord) in [PyCQA/isort#2579](https://redirect.github.com/PyCQA/isort/pull/2579)
> * Document temporary .isorted files by [`@​sapunyangkut`](https://github.com/sapunyangkut) in [PyCQA/isort#2580](https://redirect.github.com/PyCQA/isort/pull/2580)
> * Remove `cruft` by [`@​DanielNoord`](https://github.com/DanielNoord) in [PyCQA/isort#2610](https://redirect.github.com/PyCQA/isort/pull/2610)
> * Small fixes in preparation for `mypyc` compiled wheels by [`@​DanielNoord`](https://github.com/DanielNoord) in [PyCQA/isort#2623](https://redirect.github.com/PyCQA/isort/pull/2623)
> * Small fixes in preparation for compiling with `mypyc` by [`@​DanielNoord`](https://github.com/DanielNoord) in [PyCQA/isort#2625](https://redirect.github.com/PyCQA/isort/pull/2625)

... (truncated)


Commits

* [`727d119`](PyCQA/isort@727d119) Name the predicate and drive the prefix test off STRING\_PREFIXES
* [`dec76bc`](PyCQA/isort@dec76bc) Fix multiline docstring style
* [`cb179db`](PyCQA/isort@cb179db) Keep add\_imports below a prefixed module docstring
* [`7542f76`](PyCQA/isort@7542f76) test: distinguish pylint disable-next comments
* [`9f56767`](PyCQA/isort@9f56767) Fix pylint disable-next comments at top of imports
* [`0cba6f6`](PyCQA/isort@0cba6f6) Delete .cruft.json
* [`dcdda58`](PyCQA/isort@dcdda58) Remove `if` completely
* [`03d3878`](PyCQA/isort@03d3878) Fix check in CI
* [`926a147`](PyCQA/isort@926a147) Run less Builds
* [`c4ab2e9`](PyCQA/isort@c4ab2e9) Fix `test_importable` for local dev
* Additional commits viewable in [compare view](PyCQA/isort@8.0.1...9.0.0)
  
[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility\_score?dependency-name=https://github.com/pycqa/isort&package-manager=pre\_commit&previous-version=8.0.1&new-version=9.0.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
Dependabot commands and options
  
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot show  ignore conditions` will show all of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
netbsd-srcmastr pushed a commit to NetBSD/pkgsrc that referenced this pull request Aug 30, 2026
### 9.0.0 August 26 2026

   - Remove logic for deprecated options (#2498) @DanielNoord
   - Sort lazy import statements (#2503) @DanielNoord
   - Add initial support for Python 3.15 (#2466) @DanielNoord
   - Compile with `mypyc` by @DanielNoord in PyCQA/isort#2586
   - Cache calls to `posixpath.abspath` by @DanielNoord in PyCQA/isort#2606
   - Consider private `stdlib` modules to be `stdlib` (#2295) @devdanzin
   - Add CLI Flag for --forced-separate (PyCQA/isort#2367) @hirak99
   - Add separate_packages option (#2313) @alex-liang3
   - Fix inline comment duplication across merged `from X import` lines (#2499) @copilot-swe-agent
   - Fix src glob patterns passed via CLI (#2497) @ReinerBRO
   - Fix opening-line comment moving to alias attribute line on wrapped imports (#2491) @copilot-swe-agent
   - Fix multi_line_output=3/5 ignored when wrapping single imports with inline comments (#2474) @copilot-swe-agent
   - Fix false positive in `check_code` when using `float_to_top` + `add_imports` (#2492) @copilot-swe-agent
   - Fix: preserve bare `#` inline comments on imports (#2488) @copilot-swe-agent
   - Fix grouping of non-aliased imports when mixed with aliased imports from the same module (#2470) @copilot-swe-agent
   - Fix PyCQA/isort#2500: trusted publishing by @staticdev in PyCQA/isort#2521
   - Fix git_hook lazy=True option by @sparrowt in PyCQA/isort#2542
   - Honor `# isort: off/on/split` during `float_to_top` preprocessing with CRLF input by @DanielNoord with @Copilot in PyCQA/isort#2553
   - Fix --sort-reexports crash with non-seekable streams (e.g. stdin) by @Abdu-Ahmed in PyCQA/isort#2547
   - Fix non-idempotent output with split_on_trailing_comma and a non-default wrap mode by @sarathfrancis90 in PyCQA/isort#2554
   - Fix non-idempotent NOQA wrap mode with imports that carry their own comment by @sarathfrancis90 in PyCQA/isort#2556
   - Fix NOQA wrap mode accumulating spaces before the comment on each run by @sarathfrancis90 in PyCQA/isort#2558
   - Fix NOQA not added to long imports in several output paths by @urayoru113 in PyCQA/isort#2568
   - Honor `# isort: skip` when a `__future__` import is present (#2092) by @apoorvdarshan in PyCQA/isort#2574
   - fix: make sorted `__all__` and literals black-compatible (#2280) by @lord-haffi in PyCQA/isort#2576
   - Honor skip comments when sorting reexports by @sakshichitnis27 in PyCQA/isort#2581
   - Keep aliased import when the plain name carries a comment by @sarathfrancis90 in PyCQA/isort#2567
   - fix: don't crash on --config-root without --resolve-all-configs by @Gooh456 in PyCQA/isort#2597
   - fix: check_code misses lines_before_imports-only changes (#2242) by @gaoflow in PyCQA/isort#2563
   - Fix preservation of form-feed blank lines by @utkarshalpha in PyCQA/isort#2599
   - Small clean up and fix inconsistency in handling of `*` imports by @DanielNoord in PyCQA/isort#2619
   - Fix word-wrapping of 'from ... import *' into invalid Python (#2267) by @sudorm-rf0 in PyCQA/isort#2624
   - Fix pylint disable-next comments at the start of imports by @Neallin-917 in PyCQA/isort#2628
   - Keep add_imports below a prefixed module docstring by @Eljees in PyCQA/isort#2626
   - Add read the docs configuration (#2504) @DanielNoord
   - Remove unused and broken dependencies (#2517) @DanielNoord
   - Remove `Any` from `parse.py` (#2516) @DanielNoord
   - Bring documentation in line with old documentation (#2507) @DanielNoord
   - Sync profile docs with implementation (#2495) @copilot-swe-agent
   - Fix the playground (#2494) @DanielNoord7) @hirak99
   - Remove unused _ENCODING_PATTERN regex and re import by @duriantaco in PyCQA/isort#2525
   - Remove references to defunct `git_ignore` config by @sparrowt in PyCQA/isort#2531
   - Fix broken relative links in README and CHANGELOG for both GitHub and Sphinx by @rohitshinde08 in PyCQA/isort#2530
   - Bump vendored `tomli` by @DanielNoord in PyCQA/isort#2579
   - Document temporary .isorted files by @sapunyangkut in PyCQA/isort#2580
   - Remove `cruft` by @DanielNoord in PyCQA/isort#2610
   - Small fixes in preparation for `mypyc` compiled wheels by @DanielNoord in PyCQA/isort#2623
   - Small fixes in preparation for compiling with `mypyc` by @DanielNoord in PyCQA/isort#2625
   - Fix `test_importable` for local dev by @DanielNoord in PyCQA/isort#2635
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

add_import adds imports above module docstring when docstring is raw string

2 participants