Skip to content

Commit

Permalink
refactor: use generic types instead of typing (#217)
Browse files Browse the repository at this point in the history
  • Loading branch information
mkniewallner authored Nov 25, 2022
1 parent 2823be6 commit 83ba733
Show file tree
Hide file tree
Showing 22 changed files with 139 additions and 112 deletions.
27 changes: 14 additions & 13 deletions deptry/cli.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from __future__ import annotations

import logging
from pathlib import Path
from typing import List, Optional, Tuple, Union

import click

Expand All @@ -15,10 +16,10 @@ class CommaSeparatedTupleParamType(click.ParamType):

def convert(
self,
value: Union[str, List[str], Tuple[str, ...]],
param: Optional[click.Parameter],
ctx: Optional[click.Context],
) -> Tuple[str, ...]:
value: str | list[str] | tuple[str, ...],
param: click.Parameter | None,
ctx: click.Context | None,
) -> tuple[str, ...]:
if isinstance(value, str):
return tuple(value.split(","))
if isinstance(value, list):
Expand Down Expand Up @@ -189,19 +190,19 @@ def display_deptry_version(ctx: click.Context, _param: click.Parameter, value: b
)
def deptry(
root: Path,
ignore_obsolete: Tuple[str, ...],
ignore_missing: Tuple[str, ...],
ignore_transitive: Tuple[str, ...],
ignore_misplaced_dev: Tuple[str, ...],
ignore_obsolete: tuple[str, ...],
ignore_missing: tuple[str, ...],
ignore_transitive: tuple[str, ...],
ignore_misplaced_dev: tuple[str, ...],
skip_obsolete: bool,
skip_missing: bool,
skip_transitive: bool,
skip_misplaced_dev: bool,
exclude: Tuple[str, ...],
extend_exclude: Tuple[str, ...],
exclude: tuple[str, ...],
extend_exclude: tuple[str, ...],
ignore_notebooks: bool,
requirements_txt: Tuple[str, ...],
requirements_txt_dev: Tuple[str, ...],
requirements_txt: tuple[str, ...],
requirements_txt_dev: tuple[str, ...],
json_output: str,
) -> None:
"""Find dependency issues in your Python project.
Expand Down
8 changes: 5 additions & 3 deletions deptry/config.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
from __future__ import annotations

import logging
from typing import Any, Dict, Optional
from typing import Any

import click

from deptry.utils import load_pyproject_toml


def read_configuration_from_pyproject_toml(ctx: click.Context, _param: click.Parameter, value: str) -> Optional[str]:
def read_configuration_from_pyproject_toml(ctx: click.Context, _param: click.Parameter, value: str) -> str | None:
"""
Callback that, given a click context, overrides the default values with configuration options set in a
pyproject.toml file.
Expand All @@ -28,7 +30,7 @@ def read_configuration_from_pyproject_toml(ctx: click.Context, _param: click.Par
logging.debug("No configuration for deptry was found in pyproject.toml.")
return None

click_default_map: Dict[str, Any] = {}
click_default_map: dict[str, Any] = {}

if ctx.default_map:
click_default_map.update(ctx.default_map)
Expand Down
25 changes: 13 additions & 12 deletions deptry/core.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
from __future__ import annotations

import logging
import os
import sys
from dataclasses import dataclass
from pathlib import Path
from typing import Dict, List, Set, Tuple

from deptry.dependency import Dependency
from deptry.dependency_getter.base import DependenciesExtract
Expand All @@ -28,19 +29,19 @@

@dataclass
class Core:
ignore_obsolete: Tuple[str, ...]
ignore_missing: Tuple[str, ...]
ignore_transitive: Tuple[str, ...]
ignore_misplaced_dev: Tuple[str, ...]
ignore_obsolete: tuple[str, ...]
ignore_missing: tuple[str, ...]
ignore_transitive: tuple[str, ...]
ignore_misplaced_dev: tuple[str, ...]
skip_obsolete: bool
skip_missing: bool
skip_transitive: bool
skip_misplaced_dev: bool
exclude: Tuple[str, ...]
extend_exclude: Tuple[str, ...]
exclude: tuple[str, ...]
extend_exclude: tuple[str, ...]
ignore_notebooks: bool
requirements_txt: Tuple[str, ...]
requirements_txt_dev: Tuple[str, ...]
requirements_txt: tuple[str, ...]
requirements_txt_dev: tuple[str, ...]
json_output: str

def run(self) -> None:
Expand Down Expand Up @@ -69,7 +70,7 @@ def run(self) -> None:

self._exit(issues)

def _find_issues(self, imported_modules: List[Module], dependencies: List[Dependency]) -> Dict[str, List[str]]:
def _find_issues(self, imported_modules: list[Module], dependencies: list[Dependency]) -> dict[str, list[str]]:
result = {}
if not self.skip_obsolete:
result["obsolete"] = ObsoleteDependenciesFinder(imported_modules, dependencies, self.ignore_obsolete).find()
Expand Down Expand Up @@ -97,7 +98,7 @@ def _get_dependencies(self, dependency_management_format: DependencyManagementFo
raise ValueError("Incorrect dependency manage format. Only poetry, pdm and requirements.txt are supported.")

@staticmethod
def _get_local_modules() -> Set[str]:
def _get_local_modules() -> set[str]:
directories = [f for f in os.listdir() if Path(f).is_dir()]
return {subdir for subdir in directories if "__init__.py" in os.listdir(subdir)}

Expand All @@ -108,5 +109,5 @@ def _log_config(self) -> None:
logging.debug("")

@staticmethod
def _exit(issues: Dict[str, List[str]]) -> None:
def _exit(issues: dict[str, list[str]]) -> None:
sys.exit(int(any(issues.values())))
9 changes: 5 additions & 4 deletions deptry/dependency.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from __future__ import annotations

import logging
import re
from typing import List, Set

from deptry.compat import PackageNotFoundError, metadata

Expand All @@ -25,7 +26,7 @@ def __init__(self, name: str, conditional: bool = False, optional: bool = False)
self.found = self.find_metadata(name)
self.top_levels = self._get_top_levels(name)

def _get_top_levels(self, name: str) -> Set[str]:
def _get_top_levels(self, name: str) -> set[str]:
top_levels = []

if self.found:
Expand Down Expand Up @@ -68,7 +69,7 @@ def _string_for_printing(self) -> str:
else:
return " "

def _get_top_level_module_names_from_top_level_txt(self) -> List[str]:
def _get_top_level_module_names_from_top_level_txt(self) -> list[str]:
"""
top-level.txt is a metadata file added by setuptools that looks as follows:
Expand All @@ -86,7 +87,7 @@ def _get_top_level_module_names_from_top_level_txt(self) -> List[str]:
else:
return []

def _get_top_level_module_names_from_record_file(self) -> List[str]:
def _get_top_level_module_names_from_record_file(self) -> list[str]:
"""
Get the top-level module names from the RECORD file, whose contents usually look as follows:
Expand Down
9 changes: 5 additions & 4 deletions deptry/dependency_getter/base.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
from __future__ import annotations

import logging
from abc import ABC, abstractmethod
from dataclasses import dataclass
from typing import List

from deptry.dependency import Dependency


@dataclass
class DependenciesExtract:
dependencies: List[Dependency]
dev_dependencies: List[Dependency]
dependencies: list[Dependency]
dev_dependencies: list[Dependency]


@dataclass
Expand All @@ -22,7 +23,7 @@ def get(self) -> DependenciesExtract:
raise NotImplementedError()

@staticmethod
def _log_dependencies(dependencies: List[Dependency], is_dev: bool = False) -> None:
def _log_dependencies(dependencies: list[Dependency], is_dev: bool = False) -> None:
logging.debug(f"The project contains the following {'dev ' if is_dev else ''}dependencies:")
for dependency in dependencies:
logging.debug(str(dependency))
Expand Down
9 changes: 5 additions & 4 deletions deptry/dependency_getter/pdm.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from __future__ import annotations

import logging
from dataclasses import dataclass
from typing import Dict, List

from deptry.dependency import Dependency
from deptry.dependency_getter.base import DependenciesExtract
Expand All @@ -23,7 +24,7 @@ def get(self) -> DependenciesExtract:
return DependenciesExtract(pep_621_dependencies_extract.dependencies, dev_dependencies)

@classmethod
def _get_pdm_dev_dependencies(cls) -> List[Dependency]:
def _get_pdm_dev_dependencies(cls) -> list[Dependency]:
"""
Try to get development dependencies from pyproject.toml, which with PDM are specified as:
Expand All @@ -39,9 +40,9 @@ def _get_pdm_dev_dependencies(cls) -> List[Dependency]:
"""
pyproject_data = load_pyproject_toml()

dev_dependency_strings: List[str] = []
dev_dependency_strings: list[str] = []
try:
dev_dependencies_dict: Dict[str, str] = pyproject_data["tool"]["pdm"]["dev-dependencies"]
dev_dependencies_dict: dict[str, str] = pyproject_data["tool"]["pdm"]["dev-dependencies"]
for deps in dev_dependencies_dict.values():
dev_dependency_strings += deps
except KeyError:
Expand Down
13 changes: 7 additions & 6 deletions deptry/dependency_getter/pep_621.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from __future__ import annotations

import itertools
import re
from dataclasses import dataclass
from typing import Dict, List, Optional

from deptry.dependency import Dependency
from deptry.dependency_getter.base import DependenciesExtract, DependencyGetter
Expand All @@ -17,13 +18,13 @@ def get(self) -> DependenciesExtract:
return DependenciesExtract(dependencies, [])

@classmethod
def _get_dependencies(cls) -> List[Dependency]:
def _get_dependencies(cls) -> list[Dependency]:
pyproject_data = load_pyproject_toml()
dependency_strings: List[str] = pyproject_data["project"]["dependencies"]
dependency_strings: list[str] = pyproject_data["project"]["dependencies"]
return cls._extract_pep_508_dependencies(dependency_strings)

@classmethod
def _get_optional_dependencies(cls) -> Dict[str, List[Dependency]]:
def _get_optional_dependencies(cls) -> dict[str, list[Dependency]]:
pyproject_data = load_pyproject_toml()

return {
Expand All @@ -32,7 +33,7 @@ def _get_optional_dependencies(cls) -> Dict[str, List[Dependency]]:
}

@classmethod
def _extract_pep_508_dependencies(cls, dependencies: List[str]) -> List[Dependency]:
def _extract_pep_508_dependencies(cls, dependencies: list[str]) -> list[Dependency]:
extracted_dependencies = []

for spec in dependencies:
Expand All @@ -54,7 +55,7 @@ def _is_conditional(dependency_specification: str) -> bool:
return ";" in dependency_specification

@staticmethod
def _find_dependency_name_in(spec: str) -> Optional[str]:
def _find_dependency_name_in(spec: str) -> str | None:
match = re.search("[a-zA-Z0-9-_]+", spec)
if match:
return match.group(0)
Expand Down
18 changes: 10 additions & 8 deletions deptry/dependency_getter/poetry.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from __future__ import annotations

import contextlib
from dataclasses import dataclass
from typing import Any, Dict, List, Union
from typing import Any

from deptry.dependency import Dependency
from deptry.dependency_getter.base import DependenciesExtract, DependencyGetter
Expand All @@ -21,13 +23,13 @@ def get(self) -> DependenciesExtract:
return DependenciesExtract(dependencies, dev_dependencies)

@classmethod
def _get_poetry_dependencies(cls) -> List[Dependency]:
def _get_poetry_dependencies(cls) -> list[Dependency]:
pyproject_data = load_pyproject_toml()
dependencies: Dict[str, Any] = pyproject_data["tool"]["poetry"]["dependencies"]
dependencies: dict[str, Any] = pyproject_data["tool"]["poetry"]["dependencies"]
return cls._get_dependencies(dependencies)

@classmethod
def _get_poetry_dev_dependencies(cls) -> List[Dependency]:
def _get_poetry_dev_dependencies(cls) -> list[Dependency]:
"""
These can be either under;
Expand All @@ -36,7 +38,7 @@ def _get_poetry_dev_dependencies(cls) -> List[Dependency]:
or both.
"""
dependencies: Dict[str, str] = {}
dependencies: dict[str, str] = {}
pyproject_data = load_pyproject_toml()

with contextlib.suppress(KeyError):
Expand All @@ -48,7 +50,7 @@ def _get_poetry_dev_dependencies(cls) -> List[Dependency]:
return cls._get_dependencies(dependencies)

@classmethod
def _get_dependencies(cls, poetry_dependencies: Dict[str, Any]) -> List[Dependency]:
def _get_dependencies(cls, poetry_dependencies: dict[str, Any]) -> list[Dependency]:
dependencies = []
for dep, spec in poetry_dependencies.items():
# dep is the dependency name, spec is the version specification, e.g. "^0.2.2" or {"*", optional = true}
Expand All @@ -60,11 +62,11 @@ def _get_dependencies(cls, poetry_dependencies: Dict[str, Any]) -> List[Dependen
return dependencies

@staticmethod
def _is_optional(spec: Union[str, Dict[str, Any]]) -> bool:
def _is_optional(spec: str | dict[str, Any]) -> bool:
# if of the shape `isodate = {version = "*", optional = true}` mark as optional`
return bool(isinstance(spec, dict) and spec.get("optional"))

@staticmethod
def _is_conditional(spec: Union[str, Dict[str, Any]]) -> bool:
def _is_conditional(spec: str | dict[str, Any]) -> bool:
# if of the shape `tomli = { version = "^2.0.1", python = "<3.11" }`, mark as conditional.
return isinstance(spec, dict) and "python" in spec and "version" in spec
Loading

0 comments on commit 83ba733

Please sign in to comment.