diff --git a/cmake_pc_hooks/_argparse.py b/cmake_pc_hooks/_argparse.py index b059968..652ade1 100644 --- a/cmake_pc_hooks/_argparse.py +++ b/cmake_pc_hooks/_argparse.py @@ -28,6 +28,44 @@ # ============================================================================== +class InvalidExecutablePathError(argparse.ArgumentTypeError): + """Exception raised when a path to an executable is invalid.""" + + def __init__(self, path: Path) -> None: + """Initialize an InvalidExecutablePathError.""" + super().__init__(f'{path} is not a valid file and/or does not appear executable') + + +class TOMLFileNotFoundError(FileNotFoundError): + """Exception raised when a TOML file cannot be found.""" + + def __init__(self, path: Path) -> None: + """Initialize a TOMLFileNotFoundError object.""" + super().__init__(f'Unable to locate TOML file {path}') + + +class TOMLSectionKeyError(KeyError): + """Exception raised when a TOML key cannot be found.""" + + def __init__(self, section: str, path: Path) -> None: + """Initialize a TOMLSectionKeyError object.""" + super().__init__(f'Unable to locate section {section} in TOML file {path}') + + +class TOMLTypeError(argparse.ArgumentTypeError): + """Exception raised when a TOML key does not match the type of a default value.""" + + def __init__(self, value_type: type, default_value_type: type, toml_key: str) -> None: + """Initialize a TOMLSectionKeyError object.""" + super().__init__( + f'TOML value type {value_type} not compatible with parser argument ' + f'{default_value_type} for key "{toml_key}"' + ) + + +# ============================================================================== + + def _append_in_namespace(namespace, key, values): current = getattr(namespace, key, []) if current is None: @@ -65,14 +103,14 @@ def executable_path(path: str) -> Path: """ if Path(path).is_file() and os.access(path, os.X_OK): return path - raise argparse.ArgumentTypeError(f'{path} is not a valid file and/or does not appear executable') + raise InvalidExecutablePathError(path) # ============================================================================== def _load_data_from_toml( - path: Path, section: str, path_must_exist: bool = True, section_must_exist: bool = True + path: Path, section: str, *, path_must_exist: bool = True, section_must_exist: bool = True ) -> dict: """ Load a TOML file and return the corresponding config dictionary. @@ -98,15 +136,16 @@ def _load_data_from_toml( else: config = {key: value for key, value in config.items() if not isinstance(value, dict)} logging.debug('Loading data from root table of %s', path) - return config except FileNotFoundError as err: if path_must_exist: - raise FileNotFoundError(f'Unable to locate TOML file {path}') from err + raise TOMLFileNotFoundError(path) from err logging.debug('TOML file %s does not exist (not an error)', str(path)) except KeyError as err: if section_must_exist: - raise KeyError(f'Unable to locate section {section} in TOML file {path}') from err + raise TOMLSectionKeyError(section, path) from err logging.debug('TOML file %s does not have a %s section (not an error)', str(path), section) + else: + return config return {} @@ -226,13 +265,11 @@ def parse_known_args( if namespace.dump_toml: exclude_keys = {'positionals', 'dump_toml'} print( - toml.dumps( - { - key: value - for key, value in vars(namespace).items() - if value != self._default_args[key] and key not in exclude_keys - } - ) + toml.dumps({ + key: value + for key, value in vars(namespace).items() + if value != self._default_args[key] and key not in exclude_keys + }) ) sys.exit(0) @@ -243,6 +280,7 @@ def _load_from_toml( # noqa: PLR0913 namespace: argparse.Namespace, path: Path, section: str = '', + *, path_must_exist: bool = True, section_must_exist: bool = True, overridable_keys: set | None = None, @@ -258,7 +296,9 @@ def _load_from_toml( # noqa: PLR0913 section_must_exist: Whether a missing section in the TOML file is considered an error or not overridable_keys: List of keys that can be overridden by values in the TOML file """ - config = _load_data_from_toml(path, section, path_must_exist, section_must_exist) + config = _load_data_from_toml( + path, section, path_must_exist=path_must_exist, section_must_exist=section_must_exist + ) for key, value in config.items(): if key not in self._default_args: @@ -267,10 +307,7 @@ def _load_from_toml( # noqa: PLR0913 # NB: we can only do proper type check if the default value is given... default_value = self._default_args[key] if default_value is not None and not isinstance(value, type(default_value)): - raise argparse.ArgumentTypeError( - f'TOML value type {type(value)} not compatible with parser argument ' - f'{type(default_value)} for key "{key}"' - ) + raise TOMLTypeError(type(value), type(default_value), key) if overridable_keys is not None and key not in overridable_keys: logging.debug(' skipping non-overridable key: "%s"', key) continue diff --git a/cmake_pc_hooks/_cmake.py b/cmake_pc_hooks/_cmake.py index 6a7f691..b0471ff 100644 --- a/cmake_pc_hooks/_cmake.py +++ b/cmake_pc_hooks/_cmake.py @@ -14,6 +14,8 @@ """CMake related function and classes.""" +from __future__ import annotations + import contextlib import json import logging @@ -33,6 +35,25 @@ # ============================================================================== +def _try_calling_cmake(cmake_cmd: list[str | Path]) -> bool: + """ + Try to call CMake using the provided command. + + Args: + cmake_cmd: CMake command line + + Return: + True if command line is valid, False otherwise + """ + with Path(os.devnull).open(mode='w', encoding='utf-8') as devnull: + try: + sp.check_call([*cmake_cmd, '--version'], stdout=devnull, stderr=devnull) + except (OSError, sp.CalledProcessError): + return False + else: + return True + + def get_cmake_command(cmake_names=None): # pragma: nocover """ Get the path to a CMake executable on the PATH or in the virtual environment. @@ -45,42 +66,33 @@ def get_cmake_command(cmake_names=None): # pragma: nocover cmake_names = ['cmake', 'cmake3'] for cmake in cmake_names: - with Path(os.devnull).open(mode='w', encoding='utf-8') as devnull: - try: - sp.check_call([cmake, '--version'], stdout=devnull, stderr=devnull) - return [shutil.which(cmake)] - except (OSError, sp.CalledProcessError): - pass - - # CMake not in PATH, should have installed Python CMake module - # -> try to find out where it is - python_executable = Path(sys.executable) - try: - root_path = Path(os.environ['VIRTUAL_ENV']) - python = python_executable.name - except KeyError: - root_path = python_executable.parent - python = python_executable.name - - search_paths = [root_path, root_path / 'bin', root_path / 'Scripts'] - - # First try executing CMake directly - for base_path in search_paths: - try: - cmake_cmd = base_path / cmake - sp.check_call([cmake_cmd, '--version'], stdout=devnull, stderr=devnull) - return [cmake_cmd] - except (OSError, sp.CalledProcessError): - pass - - # That did not work: try calling it through Python - for base_path in search_paths: - try: - cmake_cmd = [python, base_path / 'cmake'] - sp.check_call([*cmake_cmd, '--version'], stdout=devnull, stderr=devnull) - return cmake_cmd - except (OSError, sp.CalledProcessError): - pass + cmake_cmd = [shutil.which(cmake)] + if cmake_cmd is not None and _try_calling_cmake(cmake_cmd): + return cmake_cmd + + # CMake not in PATH, should have installed Python CMake module + # -> try to find out where it is + python_executable = Path(sys.executable) + try: + root_path = Path(os.environ['VIRTUAL_ENV']) + python = python_executable.name + except KeyError: + root_path = python_executable.parent + python = python_executable.name + + search_paths = [root_path, root_path / 'bin', root_path / 'Scripts'] + + # First try executing CMake directly + for base_path in search_paths: + cmake_cmd = [base_path / cmake] + if _try_calling_cmake(cmake_cmd): + return cmake_cmd + + # That did not work: try calling it through Python + for base_path in search_paths: + cmake_cmd = [python, base_path / 'cmake'] + if _try_calling_cmake(cmake_cmd): + return cmake_cmd # Nothing worked -> give up! return None @@ -107,7 +119,8 @@ def __init__(self, cmake_names=None): self.cmake_configured_files = [] self.no_cmake_configure = False - def add_cmake_arguments_to_parser(self, parser): + @staticmethod + def add_cmake_arguments_to_parser(parser): """Add CMake options to an argparse.ArgumentParser.""" # Create option group here to control the order cmake_options = parser.add_argument_group( @@ -203,7 +216,7 @@ def add_cmake_arguments_to_parser(self, parser): '-Wno-dev', dest='no_dev_warnings', action='store_true', help='Suppress developer warnings.' ) - def resolve_build_directory(self, build_dir_list=None, automatic_discovery=True): + def resolve_build_directory(self, build_dir_list=None, *, automatic_discovery=True): """Locate a valid build directory based on internal list and automatic discovery if enabled.""" # First try to locate a valid build directory based on internal list build_dir_list = [] if build_dir_list is None else [Path(path) for path in build_dir_list] @@ -232,7 +245,7 @@ def resolve_build_directory(self, build_dir_list=None, automatic_discovery=True) self.build_dir = Path(build_dir_list[0]).resolve() logging.info('Unable to locate a valid build directory. Will be creating one at %s', str(self.build_dir)) - def setup_cmake_args(self, cmake_args): + def setup_cmake_args(self, cmake_args): # noqa: C901 """ Setup CMake arguments. @@ -305,7 +318,7 @@ def setup_cmake_args(self, cmake_args): for arg in platform_args: self.cmake_args.append(arg.strip('"\'')) - def configure(self, command, clean_build=False): + def configure(self, command, *, clean_build=False): """ Run a CMake configure step (multi-process safe). @@ -357,14 +370,12 @@ def _call_cmake(self, extra_args=None): result = _call_process.call_process( [*command, str(self.source_dir), *self.cmake_args, *extra_args], cwd=str(self.build_dir) ) - result.stdout = '\n'.join( - [ - f'Running CMake with: {[*command, str(self.source_dir), *self.cmake_args]}', - f' from within {self.build_dir}', - result.stdout, - '', - ] - ) + result.stdout = '\n'.join([ + f'Running CMake with: {[*command, str(self.source_dir), *self.cmake_args]}', + f' from within {self.build_dir}', + result.stdout, + '', + ]) return result diff --git a/cmake_pc_hooks/_utils.py b/cmake_pc_hooks/_utils.py index c7870ec..5130768 100644 --- a/cmake_pc_hooks/_utils.py +++ b/cmake_pc_hooks/_utils.py @@ -32,6 +32,13 @@ logging.getLogger('filelock').setLevel(logging.WARNING) +class CMakePresetError(Exception): + """Exception raised if a command line incompatibility with --preset is detected.""" + + def __init__(self) -> None: + super().__init__('You *must* specify -B|--build-dir if you pass --preset as a CMake argument!') + + def _read_compile_commands_json(compile_db: Path) -> list[str]: """Read a JSON compile database and return the list of files contained within.""" if compile_db.exists(): @@ -98,7 +105,7 @@ def parse_args(self, args): self.build_dir_list.extend(known_args.build_dir if known_args.build_dir else []) if not known_args.build_dir and known_args.preset: - raise RuntimeError('You *must* specify -B|--build-dir if you pass --preset as a CMake argument!') + raise CMakePresetError if self.setup_cmake: self.cmake.setup_cmake_args(known_args) @@ -152,10 +159,11 @@ def _clinters_compat(self): self.stderr = self.history[-1].stderr.encode() self.returncode = self.history[-1].returncode - def _parse_output(self, result): # noqa: ARG002 + def _parse_output(self, result): # noqa: ARG002, PLR6301 return NotImplemented - def _resolve_compilation_database(self, cmake_build_dir, build_dir_list): + @staticmethod + def _resolve_compilation_database(cmake_build_dir: Path, build_dir_list: list[Path]) -> Path | None: """Locate a compilation database based on internal list of directories.""" if cmake_build_dir and cmake_build_dir / 'compile_commands.json': return cmake_build_dir / 'compile_commands.json' diff --git a/cmake_pc_hooks/clang_tidy.py b/cmake_pc_hooks/clang_tidy.py index a2142f5..8e54ed6 100644 --- a/cmake_pc_hooks/clang_tidy.py +++ b/cmake_pc_hooks/clang_tidy.py @@ -37,7 +37,7 @@ def __init__(self, args): if not self.cmake.no_cmake_configure or compile_db: self.add_if_missing([f'-p={compile_db}']) - def _parse_output(self, result): + def _parse_output(self, result): # noqa: PLR6301 """ Parse output and check whether some errors occurred. diff --git a/cmake_pc_hooks/cppcheck.py b/cmake_pc_hooks/cppcheck.py index e63e948..0e5ae68 100644 --- a/cmake_pc_hooks/cppcheck.py +++ b/cmake_pc_hooks/cppcheck.py @@ -62,9 +62,9 @@ def _parse_output(self, result): # Useless error see https://stackoverflow.com/questions/6986033 logging.debug('parsing output from %s', result.stderr) useless_error_part = 'Cppcheck cannot find all the include files' - result.stderr = ''.join( - [line for line in result.stderr.splitlines(keepends=True) if useless_error_part not in line] - ) + result.stderr = ''.join([ + line for line in result.stderr.splitlines(keepends=True) if useless_error_part not in line + ]) self._clinters_compat() return result.returncode != 0 diff --git a/cmake_pc_hooks/include_what_you_use.py b/cmake_pc_hooks/include_what_you_use.py index bbac553..04222ae 100644 --- a/cmake_pc_hooks/include_what_you_use.py +++ b/cmake_pc_hooks/include_what_you_use.py @@ -76,9 +76,11 @@ def __init__(self, args): IWYUToolCmd.command_for_version = get_iwyu_command() if IWYUToolCmd.command is None: - raise FileNotFoundError('Unable to locate path to iwyu-tool') + msg = 'Unable to locate path to iwyu-tool' + raise FileNotFoundError(msg) if IWYUToolCmd.command_for_version is None: - raise FileNotFoundError('Unable to locate path to include-what-you-use executable!') + msg = 'Unable to locate path to include-what-you-use executable!' + raise FileNotFoundError(msg) super().__init__(self.command, self.lookbehind, args) self.check_installed() @@ -90,7 +92,7 @@ def __init__(self, args): if compile_db: self.add_if_missing([f'-p={compile_db}']) - def _parse_output(self, result): + def _parse_output(self, result): # noqa: PLR6301 """ Parse output and check whether some errors occurred. diff --git a/setup.cfg b/setup.cfg index ad5ded5..ffc5efe 100644 --- a/setup.cfg +++ b/setup.cfg @@ -55,18 +55,4 @@ test = [bdist_wheel] universal = True - -# ============================================================================== - -[flake8] - -max-line-length = 120 -exclude = - .git, - __pycache__, - build, - dist, - __init__.py -docstring-quotes = """ - # ============================================================================== diff --git a/setup.py b/setup.py index 326e601..5abcc05 100644 --- a/setup.py +++ b/setup.py @@ -14,6 +14,8 @@ """Dummy setup script.""" +from __future__ import annotations + import logging import os import shutil @@ -25,6 +27,25 @@ from setuptools.command.egg_info import egg_info +def _try_calling_executable(exec_cmd: list[str | Path]) -> bool: + """ + Try to call CMake using the provided command. + + Args: + exec_cmd: CMake command line + + Return: + True if command line is valid, False otherwise + """ + with Path(os.devnull).open(mode='w', encoding='utf-8') as devnull: + try: + subprocess.check_call([*exec_cmd, '--version'], stdout=devnull, stderr=devnull) + except (OSError, subprocess.CalledProcessError): + return False + else: + return True + + def get_executable(exec_name): """Try to locate an executable in a Python virtual environment.""" python_executable = Path(sys.executable) @@ -43,27 +64,20 @@ def get_executable(exec_name): # First try executing the program directly for base_path in search_paths: - try: - cmd = base_path / exec_name - with Path(os.devnull).open(mode='w', encoding='utf-8') as devnull: - subprocess.check_call([cmd, '--version'], stdout=devnull, stderr=devnull) - except (OSError, subprocess.CalledProcessError): - logging.info(' failed in %s', base_path) - else: + cmd = [base_path / exec_name] + if _try_calling_executable(cmd): logging.info(' command found: %s', cmd) return cmd + logging.info(' failed in %s', base_path) # That did not work: try calling it through Python for base_path in search_paths: - try: - cmd = [python, base_path / exec_name] - with Path(os.devnull).open(mode='w', encoding='utf-8') as devnull: - subprocess.check_call([*cmd, '--version'], stdout=devnull, stderr=devnull) - except (OSError, subprocess.CalledProcessError): - logging.info(' failed in %s', base_path) - else: + cmd = [python, base_path / exec_name] + + if _try_calling_executable(cmd): logging.info(' command found: %s', cmd) return cmd + logging.info(' failed in %s', base_path) logging.info(' command *not* found in virtualenv!') diff --git a/tests/python/_argparse_test.py b/tests/python/_argparse_test.py index 211ac35..e31fd5d 100644 --- a/tests/python/_argparse_test.py +++ b/tests/python/_argparse_test.py @@ -17,11 +17,11 @@ import platform from textwrap import dedent +from cmake_pc_hooks import _argparse + import pytest from _test_utils import ExitError -from cmake_pc_hooks import _argparse - # ============================================================================== @@ -38,7 +38,7 @@ def _add_simple_args(parser): @pytest.fixture() def simple_toml_content(): return dedent( - ''' + """ flag = false no_flag = true int = 1 @@ -49,7 +49,7 @@ def simple_toml_content(): no_flag = false int = 2 string = 'two' - ''' + """ ) @@ -97,7 +97,7 @@ def toml_generate(tmp_path, request): 'non_overridable': 'none', } content = dedent( - ''' + """ flag = true no_flag = false string = 'one' @@ -120,7 +120,7 @@ def toml_generate(tmp_path, request): int = 3 files = ['100.txt', '200.txt'] non_overridable = 'none' - ''' + """ ) path.write_text(content) @@ -179,7 +179,8 @@ def test_argument_parser_init(): def test_argument_parser_load_from_toml_unknown_key(mocker, toml_generate): def exit_raise(status): - raise RuntimeError(f'{status}') + msg = f'{status}' + raise RuntimeError(msg) mocker.patch('sys.exit', exit_raise) path, with_content, toml_section, _ = toml_generate @@ -202,16 +203,16 @@ def test_argument_parser_load_from_toml_invalid(toml_generate): return content = dedent( - ''' + """ other = 'one' - ''' + """ ) if toml_section: content += dedent( - f''' + f""" [{toml_section}] other = 'ten' - ''' + """ ) path.write_text(content) @@ -287,11 +288,11 @@ def test_argument_parser_pyproject_toml_missing_section(tmp_path, monkeypatch): pyproject_file.parent.mkdir(parents=True, exist_ok=True) pyproject_file.write_text( dedent( - ''' + """ flag = true int = 1 string = 'one' - ''' + """ ) ) diff --git a/tests/python/_call_process_test.py b/tests/python/_call_process_test.py index b3987fd..88a7472 100644 --- a/tests/python/_call_process_test.py +++ b/tests/python/_call_process_test.py @@ -14,10 +14,10 @@ import subprocess as sp -import pytest - from cmake_pc_hooks._call_process import History, call_process +import pytest + # ============================================================================== diff --git a/tests/python/_cmake_test.py b/tests/python/_cmake_test.py index 837116e..f531a7c 100644 --- a/tests/python/_cmake_test.py +++ b/tests/python/_cmake_test.py @@ -16,14 +16,15 @@ import platform from pathlib import Path from textwrap import dedent +import sys + +from cmake_pc_hooks._cmake import CMakeCommand, get_cmake_command, _try_calling_cmake import fasteners import filelock import pytest from _test_utils import ExitError -from cmake_pc_hooks._cmake import CMakeCommand, get_cmake_command - # ============================================================================== _has_cmake = get_cmake_command() is not None @@ -49,6 +50,14 @@ def parser(): # ============================================================================== +@pytest.mark.parametrize(('cmd', 'is_valid'), [('cmake-INVALID', False), (sys.executable, True)]) +def test_try_calling_cmake(cmd, is_valid): + assert _try_calling_cmake([cmd]) == is_valid + + +# ============================================================================== + + def test_cmake_command_init(): cmake = CMakeCommand() assert cmake.command is None or isinstance(cmake.command, list) @@ -139,7 +148,7 @@ def test_resolve_build_directory(tmp_path, dir_list, build_dir_tree, ref_path): @pytest.mark.parametrize('system', ['Linux', 'Darwin', 'Windows']) @pytest.mark.parametrize('no_cmake_configure', [False, True]) -def test_setup_cmake_args(mocker, system, no_cmake_configure): # noqa: PLR0915, PLR0912 +def test_setup_cmake_args(mocker, system, no_cmake_configure): # noqa: PLR0915, PLR0912, C901 original_system = platform.system() def system_stub(): @@ -223,7 +232,7 @@ def system_stub(): @pytest.mark.parametrize('returncode', [0, 1]) @pytest.mark.parametrize('clean_build', [False, True]) @pytest.mark.parametrize('no_cmake_configure', [False, True]) -def test_configure_cmake(mocker, tmp_path, clean_build, returncode, no_cmake_configure, detect_configured_files): +def test_configure_cmake(mocker, tmp_path, clean_build, returncode, no_cmake_configure, detect_configured_files): # noqa: PLR0917 sys_exit = mocker.patch('sys.exit') FileLock = mocker.MagicMock(filelock.FileLock) # noqa: N806 mocker.patch(filelock_module_name, FileLock) @@ -424,7 +433,7 @@ def test_parse_cmake_trace_log(mocker, tmp_path, with_cache_variables, detect_co '' if not with_cache_variables else dedent( - f''' + f""" CMAKE_ADDR2LINE:FILEPATH=/usr/bin/addr2line CMAKE_CXX_FLAGS:STRING= CMAKE_CXX_FLAGS_DEBUG:STRING=-g @@ -437,7 +446,7 @@ def test_parse_cmake_trace_log(mocker, tmp_path, with_cache_variables, detect_co CMAKE_LINKER:FILEPATH=/usr/bin/ld CMAKE_VERBOSE_MAKEFILE:BOOL=FALSE FETCHCONTENT_BASE_DIR:PATH={tmp_path.as_posix()}/build/_deps - ''' + """ ) ) @@ -451,14 +460,14 @@ def test_parse_cmake_trace_log(mocker, tmp_path, with_cache_variables, detect_co cmake_trace_log = tmp_path / 'log.json' cmake_trace_log.write_text( dedent( - f'''{{"version":{{"major":1,"minor":2}}}} + f"""{{"version":{{"major":1,"minor":2}}}} {{"args":["VERSION","3.20"],"cmd":"cmake_minimum_required","file":"{tmp_path.as_posix()}/CMakeLists.txt","frame":1,"global_frame":1,"line":1,"time":1684940081.6217611}} {{"args":["test","LANGUAGES","CXX"],"cmd":"project","file":"{tmp_path.as_posix()}/CMakeLists.txt","frame":1,"global_frame":1,"line":3,"time":1684940081.6219001}} {{"args":["/usr/share/cmake/Modules/FetchContent/CMakeLists.cmake.in","{tmp_path.as_posix()}/build/_deps/catch2-subbuild/CMakeLists.txt"],"cmd":"configure_file","file":"/usr/share/cmake/Modules/FetchContent.cmake","frame":5,"global_frame":5,"line":1598,"line_end":1599,"time":1684940081.7072489}} {{"args":["{tmp_path.as_posix()}/build/_deps/catch2-src/src/catch2/catch_user_config.hpp.in","{tmp_path.as_posix()}/build/generated-includes/catch2/catch_user_config.hpp"],"cmd":"configure_file","file":"{tmp_path.as_posix()}/build/_deps/catch2-src/src/CMakeLists.txt","frame":1,"global_frame":4,"line":308,"line_end":311,"time":1684940082.2564831}} {{"args":["test.cpp.in","test.cpp"],"cmd":"configure_file","file":"{tmp_path.as_posix()}/CMakeLists.txt","frame":1,"global_frame":1,"line":17,"time":1684940082.260792}} {{"args":["test.cpp.in","{tmp_path.as_posix()}/other.cpp"],"cmd":"configure_file","file":"{tmp_path.as_posix()}/CMakeLists.txt","frame":1,"global_frame":1,"line":18,"time":1684940082.2613621}} - ''' + """ ) ) diff --git a/tests/python/_test_utils.py b/tests/python/_test_utils.py index e21d72e..ec81969 100644 --- a/tests/python/_test_utils.py +++ b/tests/python/_test_utils.py @@ -24,7 +24,8 @@ class ExitError(Exception): # ============================================================================== -def run_command_default_assertions( +def run_command_default_assertions( # noqa: C901 + *, read_json_db, json_db_file_list, file_list, diff --git a/tests/python/_utils_test.py b/tests/python/_utils_test.py index 9385dcc..da14947 100644 --- a/tests/python/_utils_test.py +++ b/tests/python/_utils_test.py @@ -13,12 +13,12 @@ # limitations under the License. -import pytest -from _test_utils import run_command_default_assertions - from cmake_pc_hooks import _utils from cmake_pc_hooks._cmake import CMakeCommand +import pytest +from _test_utils import run_command_default_assertions + # ============================================================================== @@ -92,7 +92,7 @@ def test_command_parse_args_invalid(mocker, tmp_path, look_behind): # ---------------------------------- - with pytest.raises(RuntimeError, match='pass --preset as a CMake argument'): + with pytest.raises(_utils.CMakePresetError, match='pass --preset as a CMake argument'): command.parse_args([*args, f'-S{source_dir}', '--preset=/path/to/CMakePreset.json']) command.parse_args([*args, f'-S{tmp_path / "other"}']) diff --git a/tests/python/clang_format_test.py b/tests/python/clang_format_test.py index ebb274e..75c7506 100644 --- a/tests/python/clang_format_test.py +++ b/tests/python/clang_format_test.py @@ -12,11 +12,11 @@ # See the License for the specific language governing permissions and # limitations under the License. +from cmake_pc_hooks import clang_format + import pytest from _test_utils import command_main_asserts -from cmake_pc_hooks import clang_format - # ============================================================================== @@ -24,9 +24,7 @@ def test_clang_format_command(mocker, tmp_path, format_success): mocker.patch('hooks.utils.Command.check_installed', return_value=True) - return_values = [] - for char in (chr(n) for n in range(ord('a'), ord('z') + 1)): - return_values.append(f'{char*3}'.encode()) + return_values = [f'{char * 3}'.encode() for char in (chr(n) for n in range(ord('a'), ord('z') + 1))] def _get_filelines(filename_str): # noqa: ARG001 if format_success: diff --git a/tests/python/clang_tidy_test.py b/tests/python/clang_tidy_test.py index 3bd740e..97ca401 100644 --- a/tests/python/clang_tidy_test.py +++ b/tests/python/clang_tidy_test.py @@ -13,11 +13,11 @@ # limitations under the License. +from cmake_pc_hooks import clang_tidy + import pytest from _test_utils import command_main_asserts, run_command_default_assertions -from cmake_pc_hooks import clang_tidy - # ============================================================================== diff --git a/tests/python/conftest.py b/tests/python/conftest.py index 5787eba..624f40a 100644 --- a/tests/python/conftest.py +++ b/tests/python/conftest.py @@ -22,13 +22,11 @@ def compile_commands(tmp_path): for fname in file_list: fname.parent.mkdir(parents=True, exist_ok=True) fname.write_text('') - data.append( - { - 'directory': str(fname.parent), - 'file': str(fname), - 'command': f'/usr/bin/c++ -DONE -DTWO -Wall -c {fname}', - } - ) + data.append({ + 'directory': str(fname.parent), + 'file': str(fname), + 'command': f'/usr/bin/c++ -DONE -DTWO -Wall -c {fname}', + }) path.parent.mkdir(parents=True, exist_ok=True) with path.open(mode='w', encoding='utf-8') as fd: diff --git a/tests/python/cppcheck_test.py b/tests/python/cppcheck_test.py index 3456f34..551a2b1 100644 --- a/tests/python/cppcheck_test.py +++ b/tests/python/cppcheck_test.py @@ -13,10 +13,10 @@ # limitations under the License. -from _test_utils import command_main_asserts, run_command_default_assertions - from cmake_pc_hooks import cppcheck +from _test_utils import command_main_asserts, run_command_default_assertions + # ============================================================================== diff --git a/tests/python/iwyu_test.py b/tests/python/iwyu_test.py index 19a7416..80d9051 100644 --- a/tests/python/iwyu_test.py +++ b/tests/python/iwyu_test.py @@ -13,11 +13,11 @@ # limitations under the License. +from cmake_pc_hooks import include_what_you_use + import pytest from _test_utils import command_main_asserts, run_command_default_assertions -from cmake_pc_hooks import include_what_you_use - # ============================================================================== diff --git a/tests/python/lizard_test.py b/tests/python/lizard_test.py index 03c5f5a..4eeff8f 100644 --- a/tests/python/lizard_test.py +++ b/tests/python/lizard_test.py @@ -13,10 +13,10 @@ # limitations under the License. -from _test_utils import command_main_asserts, run_command_default_assertions - from cmake_pc_hooks import lizard +from _test_utils import command_main_asserts, run_command_default_assertions + # ==============================================================================