Skip to content

Commit

Permalink
Added typeguard, improved config handling (#20)
Browse files Browse the repository at this point in the history
  • Loading branch information
Florian Maas authored Sep 4, 2022
1 parent 043ec87 commit 93205c0
Show file tree
Hide file tree
Showing 6 changed files with 1,410 additions and 52 deletions.
23 changes: 11 additions & 12 deletions deptry/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,20 +54,19 @@ def check(
log_level = logging.DEBUG if verbose else logging.INFO
logging.basicConfig(level=log_level, handlers=[logging.StreamHandler()], format="%(message)s")

# a dictionary with the cli arguments, if they are used.
cli_arguments = {} # type: ignore
if len(ignore_dependencies) > 0:
cli_arguments["ignore_dependencies"] = list(ignore_dependencies)
if len(ignore_directories) > 0:
cli_arguments["ignore_directories"] = list(ignore_directories)
if ignore_notebooks:
cli_arguments["ignore_notebooks"] = True
config = Config(cli_arguments)
# Pass the CLI arguments to Config, if they are provided, otherwise pass 'None'.
# This way, we can distinguish if a argument was actually passed by the user
# (e.g. ignore_notebooks is 'False' by default).
config = Config(
ignore_dependencies=ignore_dependencies if ignore_dependencies else None,
ignore_directories=ignore_directories if ignore_directories else None,
ignore_notebooks=ignore_notebooks if ignore_notebooks else None,
)

obsolete_dependencies = Core(
ignore_dependencies=config.config["ignore_dependencies"],
ignore_directories=config.config["ignore_directories"],
ignore_notebooks=config.config["ignore_notebooks"],
ignore_dependencies=config.ignore_dependencies,
ignore_directories=config.ignore_directories,
ignore_notebooks=config.ignore_notebooks,
).run()
if len(obsolete_dependencies):
logging.info(f"pyproject.toml contains obsolete dependencies: {obsolete_dependencies}")
Expand Down
72 changes: 58 additions & 14 deletions deptry/config.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import logging
from pathlib import Path
from typing import Dict, Optional
from typing import Any, Dict, List, Optional

import toml
from typeguard import TypeCheckError, check_type

DEFAULTS = {"ignore_dependencies": None, "ignore_directories": [".venv"], "ignore_notebooks": False}

Expand All @@ -14,24 +15,25 @@ class Config:
either the defaults or pyproject.toml.
"""

def __init__(self, cli_arguments: Dict) -> None:
self.config = DEFAULTS
def __init__(
self,
ignore_dependencies: Optional[List[str]],
ignore_directories: Optional[List[str]],
ignore_notebooks: Optional[bool],
) -> None:
self._set_defaults()
self._override_config_with_pyproject_toml()
self._override_config_with_cli_arguments(cli_arguments)
self._override_config_with_cli_arguments(ignore_dependencies, ignore_directories, ignore_notebooks)

def _set_defaults(self) -> None:
self.ignore_dependencies = DEFAULTS["ignore_dependencies"]
self.ignore_directories = DEFAULTS["ignore_directories"]
self.ignore_notebooks = DEFAULTS["ignore_notebooks"]

def _override_config_with_pyproject_toml(self) -> None:
pyproject_toml_config = self._read_configuration_from_pyproject_toml()
if pyproject_toml_config:
for argument in self.config.keys():
if argument in pyproject_toml_config:
self.config[argument] = pyproject_toml_config[argument]
logging.debug(f"Argument {argument} set to {pyproject_toml_config[argument]} by pyproject.toml")

def _override_config_with_cli_arguments(self, cli_arguments: Dict) -> None:
for argument in cli_arguments.keys():
if cli_arguments[argument] is not None:
self.config[argument] = cli_arguments[argument]
logging.debug(f"Argument {argument} set to {cli_arguments[argument]} by command line argument")
self._override_with_toml_argument("ignore_dependencies", List[str], pyproject_toml_config)

def _read_configuration_from_pyproject_toml(self) -> Optional[Dict]:
try:
Expand All @@ -41,3 +43,45 @@ def _read_configuration_from_pyproject_toml(self) -> Optional[Dict]:
except: # noqa
logging.debug("No configuration for deptry was found in pyproject.toml.")
return None

def _override_with_toml_argument(self, argument: str, expected_type: Any, pyproject_toml_config: Dict) -> None:
"""
If argument is found in pyproject.toml, check if it's the correct type and then override the default argument with the found value.
"""
if argument in pyproject_toml_config:
value = pyproject_toml_config[argument]
try:
check_type(value, expected_type)
except TypeCheckError:
raise TypeCheckError(
f"Invalid argument supplied for `{argument}` in pyproject.toml. Should be {str(expected_type)}"
)
setattr(self, argument, value)
self._log_changed_by_pyproject_toml(argument, value)

def _override_config_with_cli_arguments(
self,
ignore_dependencies: Optional[List[str]],
ignore_directories: Optional[List[str]],
ignore_notebooks: Optional[bool],
) -> None:

if ignore_dependencies:
self.ignore_dependencies = ignore_dependencies
self._log_changed_by_command_line_argument("ignore_dependencies", ignore_dependencies)

if ignore_directories:
self.ignore_directories = ignore_directories
self._log_changed_by_command_line_argument("ignore_directories", ignore_directories)

if ignore_notebooks:
self.ignore_notebooks = ignore_notebooks
self._log_changed_by_command_line_argument("ignore_notebooks", ignore_notebooks)

@staticmethod
def _log_changed_by_pyproject_toml(argument: str, value: Any) -> None:
logging.debug(f"Argument {argument} set to {str(value)} by pyproject.toml")

@staticmethod
def _log_changed_by_command_line_argument(argument: str, value: Any) -> None:
logging.debug(f"Argument {argument} set to {str(value)} by pyproject.toml")
4 changes: 2 additions & 2 deletions deptry/imports_to_package_names.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import logging
import sys
from importlib.metadata import metadata
from typing import List
from typing import List, Set

from isort.stdlibs.py37 import stdlib as stdlib37
from isort.stdlibs.py38 import stdlib as stdlib38
Expand Down Expand Up @@ -50,7 +50,7 @@ def convert(self, imported_modules: List[str]) -> List[str]:

return packages

def _get_stdlib_packages(self):
def _get_stdlib_packages(self) -> Set[str]:
incorrect_version_error = ValueError(
f"Incorrect Python version {'.'.join([str(x) for x in sys.version_info[0:3]])}. Only 3.7, 3.8, 3.9 and 3.10 are currently supported."
)
Expand Down
2 changes: 1 addition & 1 deletion deptry/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@


@contextmanager
def run_within_dir(path: Path) -> None:
def run_within_dir(path: Path):
"""
Utility function to run some code within a directory, and change back to the current directory afterwards.
Expand Down
Loading

0 comments on commit 93205c0

Please sign in to comment.