Skip to content

Commit

Permalink
chore: mypy
Browse files Browse the repository at this point in the history
  • Loading branch information
whisperity committed Aug 6, 2024
1 parent 42a5dc0 commit 49b03ee
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 31 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
run: make -k pycodestyle pylint

- name: Run codechecker_common mypy tests
working-directory: codechecker_common/tests
working-directory: codechecker_common
run: make mypy

tools:
Expand Down
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
.DS_Store

### Python ###
# Byte-compiled / optimized / DLL files
# Byte-compiled / optimized / DLL files.
__pycache__/
*.py[cod]
*.py[cdo]

build
build_dist
Expand Down
53 changes: 27 additions & 26 deletions codechecker_common/configuration_access.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from functools import partial
from enum import Enum, auto as Enumerator
from pathlib import Path, PosixPath, PurePosixPath
from typing import cast, Any, Callable, Dict, List, Optional, Tuple, TypeVar, \
from typing import cast, Any, Callable, Dict, List, Optional, Tuple, Type, \
Union

from .logger import get_logger
Expand All @@ -30,26 +30,22 @@
_K_REF = "__ref__"
_K_SCHEMA = "_schema"

_T_CONFIGURATION = TypeVar("_T_CONFIGURATION", bound="Configuration")
_T_OPTION_BASE = TypeVar("_T_OPTION_BASE", bound="OptionBase")
_T_SCHEMA = TypeVar("_T_SCHEMA", bound="Schema")

OptionDict = Dict[str, _T_OPTION_BASE]
OptionDict = Dict[str, "OptionBase"]


class AccessError(Exception):
pass


class BackingDataError(AccessError):
def __init__(self, option: _T_OPTION_BASE, cfg: _T_CONFIGURATION):
def __init__(self, option: "OptionBase", cfg: "Configuration"):
super().__init__(
f"'{option.basename}' ('{option.path}') not found in "
f"configuration file '{cfg.file_path}'")


class BackingDataIndexError(AccessError, IndexError):
def __init__(self, option: _T_OPTION_BASE, cfg: _T_CONFIGURATION,
def __init__(self, option: "OptionBase", cfg: "Configuration",
index: int, count: int):
super().__init__(
f"list index {index} out of range for '{option.basename}' "
Expand Down Expand Up @@ -84,7 +80,7 @@ def _step_into_child(option, name: str):

class OptionBase:
def __init__(self,
schema: _T_SCHEMA,
schema: "Schema",
name: Optional[str],
path: str,
description: Optional[str] = None):
Expand Down Expand Up @@ -145,7 +141,7 @@ class _Access:
core objects it was originally instantiated with.
"""

def __init__(self, option: _T_OPTION_BASE, cfg: _T_CONFIGURATION,
def __init__(self, option: "OptionBase", cfg: "Configuration",
data_slice):
# This code is frightening at first, but, unfortunately, the usual
# 'self.member' syntax must be side-stepped such that
Expand All @@ -165,7 +161,7 @@ def _set(self, _value: Any) -> Any:
f"{str(type(object.__getattribute__(self, _K_OPTION)))} "
"can not be set!")

def _access(self, _cfg: _T_CONFIGURATION, _data_slice: Dict[str, Any]) \
def _access(self, _cfg: "Configuration", _data_slice: Dict[str, Any]) \
-> Any:
raise NotImplementedError(f"{str(type(self))} can not be accessed")

Expand All @@ -178,7 +174,7 @@ class OptionDirectory(OptionBase):
"""

def __init__(self,
schema: _T_SCHEMA,
schema: "Schema",
name: Optional[str],
path: str,
description: Optional[str] = None):
Expand All @@ -195,10 +191,12 @@ def add_option(self, name: Optional[str], path: str, *args, **kwargs):
if not path.startswith("./"):
raise ValueError("'path' must be relative to the OptionDirectory")

# MyPy has a bug for this forwarding idiom, see
# http://github.com/python/mypy/issues/6799.
return self._schema.add_option(name=name,
path=path,
parent=self,
*args, **kwargs)
*args, **kwargs) # type: ignore

def get_children(self) -> OptionDict:
return _get_children_options(self.path, self._schema.options)
Expand All @@ -209,7 +207,7 @@ class _Access(OptionBase._Access):
"directories" (option groups).
"""

def __init__(self, option: OptionBase, cfg: _T_CONFIGURATION,
def __init__(self, option: OptionBase, cfg: "Configuration",
data_slice: Dict[str, Any]):
if option.basename != '':
try:
Expand Down Expand Up @@ -268,7 +266,7 @@ def _set(self, _value: Any):
f"'{option.basename}' ('{option.path}') directory can not be "
"set directly!")

def _access(self, cfg: _T_CONFIGURATION, data_slice: Dict[str, Any]) \
def _access(self, cfg: "Configuration", data_slice: Dict[str, Any]) \
-> Any:
return OptionDirectory._Access(self, cfg, data_slice)

Expand All @@ -287,7 +285,7 @@ class OptionDirectoryList(OptionDirectory):
"""

def __init__(self,
schema: _T_SCHEMA,
schema: "Schema",
name: Optional[str],
path: str,
description: Optional[str] = None):
Expand All @@ -303,7 +301,7 @@ class _Access(OptionDirectory._Access):
Allows accessing, as if members of a list, the first-level children of
"directories" (option groups).
"""
def __init__(self, option: OptionBase, cfg: _T_CONFIGURATION,
def __init__(self, option: OptionBase, cfg: "Configuration",
data_slice: Dict[str, Any]):
super().__init__(option=option, cfg=cfg, data_slice=data_slice)

Expand Down Expand Up @@ -361,7 +359,7 @@ def _set(self, _value: Any):
f"'{option.basename}' ('{option.path}') directory can not be "
"set directly!")

def _access(self, cfg: _T_CONFIGURATION, data_slice: Dict[str, Any]) \
def _access(self, cfg: "Configuration", data_slice: Dict[str, Any]) \
-> Any:
return OptionDirectoryList._Access(self, cfg, data_slice)

Expand Down Expand Up @@ -409,7 +407,7 @@ class Option(OptionBase):
"""

def __init__(self,
schema: _T_SCHEMA,
schema: "Schema",
name: Optional[str],
path: str,
description: Optional[str] = None,
Expand Down Expand Up @@ -497,6 +495,7 @@ def __init__(self,
self._update_callback = update_callback

self._validator = validation_predicate
self._fail_callback: Optional[Callable[[OptionBase, Any], None]] = None
if validation_fail_action is None:
self._fail_callback = _log_validation_failure
elif isinstance(validation_fail_action, str):
Expand All @@ -518,7 +517,7 @@ class _Access(OptionBase._Access):
Allows retrieving and setting the value of a leaf configuration option.
"""

def __init__(self, option: OptionBase, cfg: _T_CONFIGURATION,
def __init__(self, option: OptionBase, cfg: "Configuration",
data_slice: Dict[str, Any]):
if not isinstance(data_slice, dict):
raise TypeError("data captured in an access to a scalar "
Expand Down Expand Up @@ -562,7 +561,7 @@ def _set(self, value: Any):
except KeyError:
raise BackingDataError(opt, cfg)

def _access(self, cfg: _T_CONFIGURATION, data_slice: Dict[str, Any]) \
def _access(self, cfg: "Configuration", data_slice: Dict[str, Any]) \
-> Any:
return Option._Access(self, cfg, data_slice)

Expand Down Expand Up @@ -620,13 +619,15 @@ def run_update_callback(self, path: str, old_value: Any, value: Any):
return None


def _value_or_secret(option: Option, value: Any):
def _value_or_secret(option: Option, value: Any) -> str:
return "(secret!)" if option.is_secret else f"'{value}'"


def _log_validation_failure(option: Option, value: Any):
def _log_validation_failure(option: OptionBase, value: Any) -> None:
LOG.error("Invalid value %s passed to option '%s' ('%s')",
_value_or_secret(option, value), option.basename, option.path)
'?' if not isinstance(option, Option)
else _value_or_secret(option, value),
option.basename, option.path)


class Schema:
Expand Down Expand Up @@ -656,7 +657,7 @@ def options(self) -> OptionDict:

@property
def Root(self) -> OptionDirectory:
return self.options['/']
return cast(OptionDirectory, self.options['/'])

def add_option(self, name: Optional[str], path: str,
parent: Optional[OptionDirectory] = None,
Expand Down Expand Up @@ -693,7 +694,7 @@ def add_option(self, name: Optional[str], path: str,
if ' ' in path:
raise ValueError(f"Path '{path}' must not contain spaces")

clazz = Option
clazz: Type[OptionBase] = Option
if path.endswith('/'):
clazz = OptionDirectory
path = path.rstrip('/')
Expand Down
5 changes: 3 additions & 2 deletions codechecker_common/tests/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

CURRENT_DIR = ${CURDIR}
# Root of the repository.
REPO_ROOT ?= REPO_ROOT=$(CURRENT_DIR)/..
REPO_ROOT ?= $(CURRENT_DIR)/..
REPO_ROOT_ENV_VAR ?= REPO_ROOT=$(REPO_ROOT)

MYPY_CMD = mypy --ignore-missing-imports $(REPO_ROOT)/codechecker_common

Expand All @@ -18,7 +19,7 @@ test_in_env: test_unit_in_env

# pytest test runner configuration options.
PYTESTCFG = -c pytest.ini ${EXTRA_PYTEST_ARGS}
UNIT_TEST_CMD = $(REPO_ROOT) pytest $(PYTESTCFG) tests/unit
UNIT_TEST_CMD = $(REPO_ROOT_ENV_VAR) pytest $(PYTESTCFG) tests/unit

test_unit:
$(UNIT_TEST_CMD)
Expand Down

0 comments on commit 49b03ee

Please sign in to comment.