diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4999009c..be832ee9 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -10,7 +10,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, macos-latest, windows-latest] - python-version: ["3.11", "3.12", "3.13"] + python-version: ["3.11", "3.12", "3.13", "3.14"] steps: - name: Checkout code diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e243fc47..e193db8d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -12,7 +12,7 @@ repos: - id: isort - repo: https://github.com/hakancelikdev/unimport - rev: 1.3.1 + rev: 1.4.0 hooks: - id: unimport diff --git a/action.yml b/action.yml index fc2f1679..4488d0c2 100644 --- a/action.yml +++ b/action.yml @@ -10,7 +10,7 @@ inputs: runs: using: "composite" steps: - - run: pip install --upgrade pip && python -m pip install unimport==1.3.1 + - run: pip install --upgrade pip && python -m pip install unimport==1.4.0 shell: bash - run: unimport --color auto --gitignore --ignore-init ${{ inputs.extra_args }} shell: bash diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 7fed0ad7..44642ccf 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -2,6 +2,19 @@ All notable changes to this project will be documented in this file. +## [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](https://github.com/hakancelikdev/unimport/issues/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 diff --git a/docs/index.md b/docs/index.md index 91cff3f8..4d8ae057 100644 --- a/docs/index.md +++ b/docs/index.md @@ -29,4 +29,4 @@ process with Unimport. - **Documentation** https://unimport.hakancelik.dev/ - **Issues** https://github.com/hakancelikdev/unimport/issues/ -- **Changelog** https://unimport.hakancelik.dev/1.3.1/CHANGELOG/ +- **Changelog** https://unimport.hakancelik.dev/1.4.0/CHANGELOG/ diff --git a/docs/tutorial/use-with-github-action.md b/docs/tutorial/use-with-github-action.md index 77dbaaee..b7bd86ed 100644 --- a/docs/tutorial/use-with-github-action.md +++ b/docs/tutorial/use-with-github-action.md @@ -27,7 +27,7 @@ jobs: - uses: actions/checkout@v3.5.3 - uses: actions/setup-python@v4.6.1 - name: Check unused imports - uses: hakancelikdev/unimport@1.3.1 + uses: hakancelikdev/unimport@1.4.0 with: extra_args: --include src/ ``` diff --git a/pyproject.toml b/pyproject.toml index a549a15f..42a64c34 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -31,15 +31,16 @@ classifiers = [ "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", "Programming Language :: Python :: Implementation :: CPython", "Environment :: Console", "Topic :: Software Development :: Libraries :: Python Modules", ] -requires-python = ">=3.9,<3.14" +requires-python = ">=3.9,<3.15" dependencies = [ - "libcst>=0.4.10,<=1.8.2; python_version >= '3.11'", - "libcst>=0.3.7,<=1.8.2; python_version == '3.10'", - "libcst>=0.3.7,<=1.8.2; python_version == '3.9'", + "libcst>=0.4.10,<=1.8.6; python_version >= '3.11'", + "libcst>=0.3.7,<=1.8.6; python_version == '3.10'", + "libcst>=0.3.7,<=1.8.6; python_version == '3.9'", "pathspec>=0.10.1,<1", "toml>=0.9.0,<1", ] @@ -47,7 +48,7 @@ dependencies = [ [project.urls] Documentation = "https://unimport.hakancelik.dev/" Issues = "https://github.com/hakancelikdev/unimport/issues/" -Changelog = "https://unimport.hakancelik.dev/1.3.1/CHANGELOG/" +Changelog = "https://unimport.hakancelik.dev/1.4.0/CHANGELOG/" [project.optional-dependencies] docs = [ diff --git a/src/unimport/__init__.py b/src/unimport/__init__.py index faa01cd0..84e72088 100644 --- a/src/unimport/__init__.py +++ b/src/unimport/__init__.py @@ -1,2 +1,2 @@ -__version__ = "1.3.1" +__version__ = "1.4.0" __description__ = "A linter, formatter for finding and removing unused import statements." diff --git a/src/unimport/constants.py b/src/unimport/constants.py index 815f9709..72792219 100644 --- a/src/unimport/constants.py +++ b/src/unimport/constants.py @@ -12,6 +12,7 @@ "PY310_PLUS", "PY312_PLUS", "PY313_PLUS", + "PY314_PLUS", "STDLIB_PATH", "SUBSCRIPT_TYPE_VARIABLE", ) @@ -31,6 +32,7 @@ PY310_PLUS = sys.version_info >= (3, 10) PY312_PLUS = sys.version_info >= (3, 12) PY313_PLUS = sys.version_info >= (3, 13) +PY314_PLUS = sys.version_info >= (3, 14) SUBSCRIPT_TYPE_VARIABLE = frozenset( { diff --git a/tests/cases/analyzer/error/try_except_no_parens.py b/tests/cases/analyzer/error/try_except_no_parens.py new file mode 100644 index 00000000..434942cb --- /dev/null +++ b/tests/cases/analyzer/error/try_except_no_parens.py @@ -0,0 +1,20 @@ +from typing import Union + +from unimport.statement import Import, ImportFrom, Name + +__all__ = ["NAMES", "IMPORTS", "UNUSED_IMPORTS"] + + +NAMES: list[Name] = [ + Name(lineno=9, name="ValueError", is_all=False), + Name(lineno=9, name="TypeError", is_all=False), + Name(lineno=14, name="ValueError", is_all=False), + Name(lineno=14, name="TypeError", is_all=False), + Name(lineno=14, name="KeyError", is_all=False), +] +IMPORTS: list[Union[Import, ImportFrom]] = [ + Import(lineno=5, column=1, name="os", package="os"), +] +UNUSED_IMPORTS: list[Union[Import, ImportFrom]] = [ + Import(lineno=5, column=1, name="os", package="os"), +] diff --git a/tests/cases/refactor/error/try_except_no_parens.py b/tests/cases/refactor/error/try_except_no_parens.py new file mode 100644 index 00000000..cb8f3b08 --- /dev/null +++ b/tests/cases/refactor/error/try_except_no_parens.py @@ -0,0 +1,14 @@ +# pytest.mark.skipif(not PY314_PLUS, reason: "except without parens (PEP 758) is supported above python 3.14") + +# https://github.com/hakancelikdev/unimport/issues/326 + + +try: + pass +except ValueError, TypeError: + pass + +try: + pass +except ValueError, TypeError, KeyError: + pass diff --git a/tests/cases/source/error/try_except_no_parens.py b/tests/cases/source/error/try_except_no_parens.py new file mode 100644 index 00000000..387f153e --- /dev/null +++ b/tests/cases/source/error/try_except_no_parens.py @@ -0,0 +1,15 @@ +# pytest.mark.skipif(not PY314_PLUS, reason: "except without parens (PEP 758) is supported above python 3.14") + +# https://github.com/hakancelikdev/unimport/issues/326 + +import os + +try: + pass +except ValueError, TypeError: + pass + +try: + pass +except ValueError, TypeError, KeyError: + pass diff --git a/tests/cases/test_cases.py b/tests/cases/test_cases.py index 51bd28f3..842180e6 100644 --- a/tests/cases/test_cases.py +++ b/tests/cases/test_cases.py @@ -6,7 +6,7 @@ import pytest from unimport.analyzers import MainAnalyzer -from unimport.constants import PY310_PLUS, PY312_PLUS, PY313_PLUS # noqa using eval expression +from unimport.constants import PY310_PLUS, PY312_PLUS, PY313_PLUS, PY314_PLUS # noqa using eval expression from unimport.refactor import refactor_string from unimport.statement import Import, Name from unimport.utils import list_paths @@ -35,7 +35,7 @@ def test_cases(path: Path, logger): if ( skip_if and (condition := skip_if.group("condition")) - and condition in ("not PY310_PLUS", "not PY312_PLUS", "not PY313_PLUS") + and condition in ("not PY310_PLUS", "not PY312_PLUS", "not PY313_PLUS", "not PY314_PLUS") ): reason = skip_if.group("reason") pytest.mark.skipif(False, reason, allow_module_level=True) diff --git a/tox.ini b/tox.ini index d968d7b1..8a57ab81 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = 3.9, 3.10, 3.11, 3.12, 3.13, pre-commit +envlist = 3.9, 3.10, 3.11, 3.12, 3.13, 3.14, pre-commit isolated_build = true [testenv]