From 5ed7df1134a80f4e63a6442e1c01e23b359f3e19 Mon Sep 17 00:00:00 2001 From: Fredrik Averpil Date: Fri, 28 Feb 2025 20:28:50 +0100 Subject: [PATCH 1/4] ci: use uv instead of pip (#267) --- .github/dependabot.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index ce5cb396..eb16f17e 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,10 +1,11 @@ version: 2 +enable-beta-ecosystems: true updates: - package-ecosystem: "github-actions" directory: "/" schedule: interval: "monthly" - - package-ecosystem: "pip" + - package-ecosystem: "uv" directory: "/" schedule: interval: "monthly" From 9fe9816b14477cd9f0b300486c7596c669e6766b Mon Sep 17 00:00:00 2001 From: Fredrik Averpil Date: Fri, 28 Feb 2025 20:34:17 +0100 Subject: [PATCH 2/4] ci: remove likely unused entries (#268) --- .github/dependabot.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index eb16f17e..80c134a0 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -9,6 +9,3 @@ updates: directory: "/" schedule: interval: "monthly" - allow: - - dependency-name: "*" - dependency-type: all From 4f360248fedde8aff44b9241a1fd746f6de5bdeb Mon Sep 17 00:00:00 2001 From: Fredrik Averpil Date: Sat, 1 Mar 2025 16:34:14 +0100 Subject: [PATCH 3/4] fix: support dependency spec where version can either be str or dict (#270) --- src/creosote/parsers.py | 51 +++++++++++++++++++++++++++------------- tests/deps_files/Pipfile | 2 +- 2 files changed, 36 insertions(+), 17 deletions(-) diff --git a/src/creosote/parsers.py b/src/creosote/parsers.py index 723e9030..409caeff 100644 --- a/src/creosote/parsers.py +++ b/src/creosote/parsers.py @@ -33,8 +33,12 @@ PEP735Types = Union[PEP735Type1, PEP735Type2] PoetryType1 = dict[PackageName, str] PoetryType2 = dict[PackageName, dict[str, str]] -PoetryTypes = Union[PoetryType1, PoetryType2] -PipfileType = dict[PackageName, str] +PoetryType3 = dict[PackageName, Union[str, dict[str, str]]] +PoetryTypes = Union[PoetryType1, PoetryType2, PoetryType3] +PipfileType1 = dict[PackageName, str] +PipfileType2 = dict[PackageName, dict[str, str]] +PipfileType3 = dict[PackageName, Union[str, dict[str, str]]] +PipfileTypes = Union[PipfileType1, PipfileType2, PipfileType3] AllSupportedTypes = Union[ PEP621Type1, PEP621Type2, @@ -42,30 +46,41 @@ PEP735Type2, PoetryType1, PoetryType2, - PipfileType, + PoetryType3, + PipfileType1, + PipfileType2, + PipfileType3, ] -def is_list_type(value: AllSupportedTypes) -> TypeGuard[PEP621Type1]: - return isinstance(value, list) +def is_list_type(var: AllSupportedTypes) -> TypeGuard[PEP621Type1]: + return isinstance(var, list) def is_dict_of_strings( - value: AllSupportedTypes, -) -> TypeGuard[Union[PoetryType1, PipfileType]]: - return isinstance(value, dict) and all(isinstance(v, str) for v in value.values()) + var: AllSupportedTypes, +) -> TypeGuard[Union[PoetryType1, PipfileType1]]: + return isinstance(var, dict) and all(isinstance(v, str) for v in var.values()) def is_dict_of_lists( - value: AllSupportedTypes, + var: AllSupportedTypes, ) -> TypeGuard[Union[PEP621Type2, PEP735Type1]]: - return isinstance(value, dict) and all(isinstance(v, list) for v in value.values()) + return isinstance(var, dict) and all(isinstance(v, list) for v in var.values()) def is_dict_of_dicts( - value: AllSupportedTypes, -) -> TypeGuard[PoetryType2]: - return isinstance(value, dict) and all(isinstance(v, dict) for v in value.values()) + var: AllSupportedTypes, +) -> TypeGuard[Union[PoetryType2, PipfileType2]]: + return isinstance(var, dict) and all(isinstance(v, dict) for v in var.values()) + + +def is_dict_of_union( + var: AllSupportedTypes, +) -> TypeGuard[Union[PoetryType3, PipfileType3]]: + if not isinstance(var, dict): + return False + return all(isinstance(v, (str, dict)) for v in var.values()) class DependencyReader: @@ -173,10 +188,14 @@ def get_deps_from_pep735_toml( def get_deps_from_toml_section_keys( self, - section_contents: Union[PoetryTypes, PipfileType], + section_contents: Union[PoetryTypes, PipfileTypes], ) -> list[PackageName]: """Get dependency names from toml section's dict keys.""" - if is_dict_of_strings(section_contents) or is_dict_of_dicts(section_contents): + if is_dict_of_strings(section_contents): + return list(section_contents.keys()) + if is_dict_of_dicts(section_contents): + return list(section_contents.keys()) + if is_dict_of_union(section_contents): return list(section_contents.keys()) raise TypeError("Unexpected dependency format, dict expected.") @@ -221,7 +240,7 @@ def read_toml(self, deps_file: str, sections: list[str]) -> list[str]: elif section.startswith("packages") or section.startswith("dev-packages"): logger.debug(f"Detected pipenv/Pipfile toml section in {deps_file}") section_dep_names = self.get_deps_from_toml_section_keys( - cast(PipfileType, section_contents) + cast(PipfileType1, section_contents) ) else: raise TypeError("Unsupported dependency format.") diff --git a/tests/deps_files/Pipfile b/tests/deps_files/Pipfile index a9d0f8a3..d89c7b1a 100644 --- a/tests/deps_files/Pipfile +++ b/tests/deps_files/Pipfile @@ -6,7 +6,7 @@ name = "pypi" [packages] dotty-dict = ">=1.3.1,<1.4" loguru = ">=0.6.0,<0.7" -toml = ">=0.10.2,<0.11" +toml = {version = "*"} [dev-packages] pytest = "*" From a78ad0ecaa21f449ef5ca66bbb6e5908c213b139 Mon Sep 17 00:00:00 2001 From: Fredrik Averpil Date: Sat, 1 Mar 2025 16:38:10 +0100 Subject: [PATCH 4/4] chore(main): release 4.0.1 (#271) --- .github/.release-please-manifest.json | 2 +- .pre-commit-config.yaml | 2 +- CHANGELOG.md | 7 +++++++ pyproject.toml | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/.github/.release-please-manifest.json b/.github/.release-please-manifest.json index e6f87756..cf533f28 100644 --- a/.github/.release-please-manifest.json +++ b/.github/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "4.0.0" + ".": "4.0.1" } diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 41286530..e06a0b0d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/fredrikaverpil/creosote - rev: v4.0.0 + rev: v4.0.1 hooks: - id: creosote args: diff --git a/CHANGELOG.md b/CHANGELOG.md index 349d626f..4480174e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [4.0.1](https://github.com/fredrikaverpil/creosote/compare/v4.0.0...v4.0.1) (2025-03-01) + + +### Bug Fixes + +* support dependency spec where version can either be str or dict ([#270](https://github.com/fredrikaverpil/creosote/issues/270)) ([4f36024](https://github.com/fredrikaverpil/creosote/commit/4f360248fedde8aff44b9241a1fd746f6de5bdeb)) + ## [4.0.0](https://github.com/fredrikaverpil/creosote/compare/v3.2.0...v4.0.0) (2025-01-05) diff --git a/pyproject.toml b/pyproject.toml index eda0cf62..a437f523 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "creosote" description = 'Identify unused dependencies and avoid a bloated virtual environment.' -version = "4.0.0" +version = "4.0.1" readme = "README.md" requires-python = ">=3.9" keywords = []