Skip to content

Changelog

Changelog

All notable changes to this project will be documented in this file.

[1.5.0] - 2026-10-02

Added
  • -j/--jobs option (and jobs config key) to analyze files in parallel processes; 0 uses all CPUs. --permission always runs with a single process #293
  • --format json (and format config key) prints unused imports and errors as one JSON document for editors, CI and other tools #342
  • per-file-ignores configuration to keep matching imports in matching files (e.g. re-exports in __init__.py) while still checking the rest #343
Changed
  • Scopes are looked up by identity instead of by comparing fields, which removes a quadratic scan and makes analysis about a third faster on large code bases #341
Fixed
  • String type expressions in builtin generics (list["X"]), Annotated, TypeAlias values and TypeVar bounds/constraints are now resolved, so the imports they use are no longer removed #329
  • Names added with __all__ += [...] or listed in an annotated __all__: list[str] = [...] now count as re-exports, so their imports are no longer removed #330
  • Imports inside try / except* blocks are treated like try / except, so optional import fallbacks are no longer removed #331
  • A nested if no longer resets the if/else import dispatch of the enclosing if, so imports after it are no longer removed #332
  • Explicit re-exports (import X as X, from m import X as X, PEP 484) are no longer reported or removed #333
  • from . import * and from . import x no longer report the package as .None, and refactoring with --include-star-import no longer crashes on from . import *; relative star imports are neither reported nor changed since their names can’t be resolved #334
  • Unused imports are no longer missed when the name is reassigned before use in the same scope, or bound locally in the function that uses it (parameter, assignment, loop target, import, …). Assignment targets no longer count as uses #335
  • Imports inside a try block without an except handler (try / finally) are checked again, and a nested try no longer clears the protection of the enclosing one #336
  • # noqa comments for other codes (e.g. # noqa: E501) no longer skip the import; a bare # noqa and # noqa: F401 still do #337
  • On Python 3.12+ the output showed Emoji.STAR, Emoji.PARTYING_FACE and ColorSelect.AUTO instead of their values; --help also listed the --color choices in upper case #338
  • The --permission prompt honours --color; it received the file encoding instead of the color setting and was always colored #339
  • Files that can’t be read or decoded (bad encoding declaration, invalid bytes, permission errors) are reported and make the exit code 1, instead of being skipped silently or crashing the whole run #340
  • Files containing null bytes are reported as syntax errors instead of crashing the run on Python 3.9–3.11
  • A # noqa comment is found on the right line when a string literal earlier in the file contains a form feed or another character that str.splitlines() treats as a line break
  • String forward references in PEP 695/696 positions (type X = "Y", type parameter bounds and defaults) and in TypeVar/ParamSpec/TypeVarTuple default= are resolved; Literal[...] values and Annotated[...] metadata no longer count as uses

[1.4.0] - 2026-06-02

Added
  • Python 3.14 support added, including the new except clause syntax without parentheses around exception tuples (PEP 758) #326
Changed
  • Raised libcst upper pin from <=1.8.2 to <=1.8.6 so the refactor pipeline can parse and round-trip files using PEP 758 syntax

[1.3.1] - 2026-02-18

Fixed
  • Fix false positive when import and usage are on the same semicolon-separated line #292
  • Fix nested if statement dispatch not recognized (e.g. TYPE_CHECKING inside version check) #294
  • Fix incorrect removal of runtime import shadowed by TYPE_CHECKING import #313
  • Fix import after use in function incorrectly removed #178
  • Fix subpackage import incorrectly removed when sibling subpackage is used #180
  • Fix/deduplicate clashing star import suggestions
  • Preserve comments when removing unused imports

[1.3.0] - 2025-08-01

Added
  • Python 3.13 support added
Changed
  • Python 3.8 support dropped
  • Updated minimum Python version requirement from 3.8+ to 3.9+
  • Removed Python 3.8 from CI/CD pipeline and testing environments
  • Updated all configuration files to reflect Python 3.9+ support
  • Upgraded all package versions in use
Fixed
  • Replace deprecated lib2to3 imports with ast module in test cases
  • Fixed deprecation warning in Python 3.10+ compatibility
  • Updated test cases to use modern ast module instead of deprecated lib2to3 package
  • All tests now pass without deprecation warnings

[1.2.1] - 2023-12-24

Added
  • Python 3.12 support added

[1.2.0] - 2023-12-22

Changed
  • Python 3.6 support dropped
  • Python 3.7 support dropped
Fixed
  • Improved Type Comment Analysis

To ensure accurate type comment analysis, a crucial fix was implemented in the code. The update involves refining the process by adding a check within ast.AnnAssign and ast.arg types. Specifically, the code now includes a verification that visit_Constant occurs under an annotation, addressing unnecessary name discovery issues for better accuracy in type_comment assessment.

import sys
from typing import (
    List,
)


test_list: List[str] = ["spam", "eggs"]  # it thought spam and eggs were a ast.Name object.

[1.1.0] - 2023-11-17

Added
  • Support for Python version 3.11.

[1.0.1] - 2023-11-17

Changed
  • Implement strtobool function (and remove distutils dependency) #297

[1.0.0] - 2023-07-07

Added
  • Automatically pick up config options from setup.cfg if it is present in the project root else check and if it exists use pyproject.toml. #256

If you want you can disable this feature by passing --disable-auto-discovery-config

  • Add github-action #229
  • Add support like command line commands in configuration files. #287
Fixed
  • ignore-init setting is not working from command line call #263
  • Running without options or a config file #281
  • Attribute as import refactor #284
Changed
  • Raise more human-readable exceptions when the key is mistyped in the configuration #286

[0.16.1] - 2023-07-05

Fixed
  • Fix: ignore-init setting is not working from command line call #263

[0.16.0] - 2023-04-04

Added
  • Add support like command line commands in configuration files. #287
Changed
  • Raise more human-readable exceptions when the key is mistyped in the configuration. #286

[0.15.0] - 2023-03-31

Fixed
  • Fix: attribute as import refactor #284

[0.14.1] - 2023-02-04

Fixed
  • Running without options or a config file #281.

[0.14.0] - 2023-02-03

Added
  • Automatically pick up config options from setup.cfg if it is present in the project root else check and if it exists use pyproject.toml. #256

If you want you can disable this feature by passing --disable-auto-discovery-config

[0.13.0] - 2023-02-01

Changed
  • The remove command is set to the default behavior. #273
Fixes
  • pre-commit autoupdate yields a weird result #275

[0.12.3] - 2022-12-04

Added
  • Multiple versions of the docs

[0.12.2] - 2022-11-09

πŸ› Fixes
  • --color=never is now respected when showing the diffs

0.12.1

πŸ› Fixes
  • Changelog url PR #250
  • Name Error PR #250

0.12.0

πŸ”₯ Features
  • Add if condition analysis and πŸ§ͺ Refactor PR #247

For example;

import sys

if sys.version_info >= (3, 8):
    from typing import Literal
else:
    from typing_extensions import Literal
  • setup.py remove and pyproject.toml was added. PR #245

0.11.3

πŸ› Fixes
  • Fix main.py to run unimport

0.11.2

πŸ› Fixes
  • Re complile fail mentioning ‘ps_d’ when using –gitignore PR #241
Internal

For Python 3.7 and above

  • Drop support for patspec, 0.5.0 above and below 0.10.0 versions.
  • Only 0.10.0 and above versions are supported, in these versions the gitignore parameter works more accurately.
  • For more accurate results when using –gitignore parameter, please do not use Python 3.6 and Windows.
πŸ“ Docs
  • Docs update
Internal
  • Refactor main.py and add tests PR #238

0.11.1

πŸ› Fixes
  • Setup

0.11.0

πŸ“ Docs
  • Update docs
Deprecated
  • Remove requirements feature PR #234

    This feature alone is not enough and can be developed as a new project using unimport, it should not be a feature of unimport.

0.10.0

πŸ› Fixes
  • Configurations flow PR #230
  • Exit code behavior PR #225
Internal
  • πŸ”₯ Support Github action PR #231

0.9.6

Internal
  • 3.10+ Support πŸ”₯ PR #26

0.9.5

πŸ› Fixes
  • Refactor: tests using pytest, fix check method PR #208

0.9.4

πŸ› Fixes
  • i199 Refactor options & commands & Option color output PR #205
Internal
  • πŸ”₯ Build Docker image PR #202

0.9.2

πŸ› Fixes
  • setup.py

0.9.1

πŸ› Fixes
  • EOLs not being respected in modified files per PR #193
  • Respect the file’s current EOL (LF/CRLF) instead of the platform default
  • Add unit and integration tests that EOLs are respected

0.9.0

πŸ”₯ Features
  • Scope analyzer PR #189
  • Scope analyzer
  • Duplicate import feature has been enabled again.
πŸ› Fixes
  • Adding unnecessary rpar in vertical style PR #191

Δ°nput

import sys
from typing import (
    List,
)

test_list: List[str] = ["spam", "eggs"]

Output

from typing import (
  List,

)

test_list: List[str] = ["spam", "eggs"]

0.8.4

πŸ› Fixes
  • Emoji issues PR #185

0.8.0

0.7.4

πŸ› Fixes
  • list_paths in utils PR #172

0.7.3

πŸ”₯ Features
  • Add --ignore-init flag PR #169

0.7.2

πŸ”₯ Features
  • Python3.9 Support PR #166

0.7.1

πŸ› Fixes

0.7.0

πŸ”₯ Features
  • Star import more accurate suggestion PR #158
Internal
  • %15 performance increase & remove show-error flag PR #159
πŸ› Fixes
  • Fix: scanner PR #157
  • PR #155
  • Configuration Bug Fix ( Configuration priority, reading and merge )
  • %136 - %150 performance increase

0.6.8

πŸ› Fixes

0.6.6

πŸ”₯ Features
  • Support multiline skip import only py3.8 and plus PR #138
  • Support type variable PR #128
  • Support Windows OS coloring and encoding PR #116
πŸ› Fixes
  • Call attribute scanner PR #145
  • Requirements feature & star import suggestion PR #142
  • Initial imports from sys.modules PR #136
  • Import and name matcher PR #133
  • Type comment PR #130
  • Same line duplicates PR #125

0.3.0

πŸ”₯ Features
  • Configuration extend and refactoring PR #111
  • General refactoring PR #108
  • Support append and extend __all__ list
  • Star import suggestions improved
  • Support .gitignore exclude patterns PR #102
  • Support async def Issue #92
πŸ› Fixes
  • Improve: Names, Imports and star suggestion PR #112
  • Unnecessary refactoring PR #107
Internal
  • Optimize Python >=3.8 type comments support method PR #95
  • Improve test coverage PR #93

0.2.10

πŸ”₯ Features
πŸ› Fixes
  • Vertical style issue PR #86
from foo import (
    Foo,
    Bar,
    FooBar,
)
Foo, Bar

0.2.9

πŸ”₯ Features
  • Support for exit code and add some enhancement PR #81
πŸ› Fixes
  • Double underscore in builtins imports PR #82
  • Incorrect matching import and name PR #78

0.2.8

πŸ”₯ Features
  • Support: file-wide skips PR #77
  • Now, you can skip a file by typing # unimport: skip_file anywhere in that file.
  • Support: requirements.txt file PR #75
  • Now, You can automatically delete unused modules from the requirements.txt file ( unimport --requirements --remove), see the difference ( unimport --requirements --diff), delete it by requesting permission ( unimport --requirements --permission), or just check ( unimport --requirements).
  • Support for type hints (#58) & string typing PR #71
from typing import List, TYPE_TEST
test: 'List[TYPE_TEST]'
from typing import List, TYPE_TEST
test: "List['TYPE_TEST']"
πŸ› Fixes
  • Preserve import styles PR #76
  • Match error between import name and name PR #74
  • get_suggestion_modules function fix for __all__ name when import is star PR #64