Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,40 +3,40 @@ repos:
hooks:
- id: ruff
name: ruff
entry: bash -c "cd python_coderunner && ruff check ."
entry: bash -c "cd python_coderunner && exec ruff check --fix ."
language: system
pass_filenames: false
types: [python]
stages: [pre-commit]
verbose: true
pass_filenames: false

- id: ruff_format
name: ruff_format
# not in args, because entry is bash
entry: bash -c "cd python_coderunner && ruff format --quiet ."
entry: bash -c "cd python_coderunner && exec ruff format --quiet ."
language: system
pass_filenames: false
types: [python]
stages: [pre-commit]
verbose: true
pass_filenames: false

- id: mypy
name: mypy
entry: bash -c "cd python_coderunner && mypy ."
- id: pyright
name: pyright
entry: bash -c "cd python_coderunner && exec pyright ."
language: system
pass_filenames: false
types: [python]
stages: [pre-commit]
verbose: true
pass_filenames: false

- id: pylint
name: pylint
entry: bash -c "cd python_coderunner && pylint ."
entry: bash -c "cd python_coderunner && exec pylint ."
language: system
pass_filenames: false
types: [python]
stages: [pre-commit]
verbose: true
pass_filenames: false

- id: commitlint
name: commitlint
Expand Down
46 changes: 20 additions & 26 deletions python_coderunner/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,24 @@ name = "vim-code-runner"
authors = [
{name = "Zahar Chernenko", email = "zaharchernenko35@gmail.com"},
]
version = "1.0.2"
version = "1.0.3"
requires-python = ">=3.10"

[dependency-groups]
dev = [
"commitlint>=1.3.0",
"mypy>=0.910",
"pre-commit>=1.21.0",
"pylint>=2.6.2",
"pyright>=1.1.411",
"pytest>=6.1.2,<8.0.0",
"pytest-lazy-fixture>=0.6.3",
"pytest-mock>=3.5.1",
"ruff>=0.12.0",
]
pre-commit = [
"mypy>=0.910",
"pre-commit>=1.21.0",
"pylint>=2.6.2",
"pyright>=1.1.411",
"ruff>=0.12.0",
]
test = [
Expand All @@ -33,33 +33,27 @@ test = [
pythonpath = ["."] # to run without python -m, otherwise there will be no src in the path
testpaths = ["tests"]

[tool.mypy]
check_untyped_defs = true
explicit_package_bases = true # without this, mypy complains about duplicate packages.
ignore_missing_imports = true
disable_error_code = [
"attr-defined",
"import-untyped",
"union-attr",
]
[tool.pyright]
typeCheckingMode = "basic"
reportMissingModuleSource = false
reportMissingParameterType = true
reportMissingTypeArgument = true
stubPath = "typings"
[[tool.pyright.executionEnvironments]]
root = "tests"
reportMissingImports = false

[tool.ruff]
line-length = 120
[tool.ruff.format]
quote-style = "double"
[tool.ruff.lint]
extend-select = ["I", "F401"]
extend-select = ["D213", "D415", "I"]
extend-unsafe-fixes = ["F401"]
ignore = ["W292"]
[tool.ruff.lint.per-file-ignores]
"__init__.py" = [
"F401", # ignore unused imports
]
"conftest.py" = [
"E402",
"F401",
"F811",
]
"__init__.py" = [ "F401" ] # Ignore unused imports.
"conftest.py" = [ "E402", "F401", "F811" ]
[tool.ruff.format]
quote-style = "double"

[tool.pylint]
[tool.pylint.main]
Expand All @@ -80,13 +74,13 @@ disable = [
"trailing-newlines",
"too-few-public-methods",
"too-many-arguments",
"too-many-positional-arguments",
"too-many-instance-attributes",
"too-many-positional-arguments",
"raise-missing-from",
"line-too-long",
]
ignored-modules = ["vim"]
[tool.pylint.VARIABLES]
[tool.pylint.variables]
argument-naming-style = "snake_case"
attr-naming-style = "snake_case"
class-attribute-naming-style = "any"
Expand All @@ -95,7 +89,7 @@ class-rgx="^(((I|T|E)[A-Z][a-zA-Z0-9]*)|([A-Z][a-zA-Z0-9]*(Error|Protocol)))$"
const-naming-style= "any"
function-naming-style = "snake_case"
typealias-rgx="^(((I|T|E)[A-Z][a-zA-Z0-9]*)|([A-Z][a-zA-Z0-9]*(Error|Protocol)))$"
typevar-rgx="^[A-Z][a-zA-Z0-9]*Type$"
typevar-rgx="^[A-Z][a-zA-Z0-9]*Type(_co|_contra)?$"
variable-naming-style = "snake_case"
module-naming-style = "snake_case"
inlinevar-naming-style = "any"
2 changes: 1 addition & 1 deletion python_coderunner/src/config/config_field.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class TConfigField(Generic[ValueType]):
- Getting value (getter)
- Validating value (validator)
- Field metadata (name, allowed_values)
- Error handling
- Error handling.
"""

def __init__(
Expand Down
2 changes: 1 addition & 1 deletion python_coderunner/src/config/getter/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
class UndefinedValueError(ValueError):
"""Config value is not defined"""
"""Config value is not defined."""
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@


class TBaseVimConfigValueGetter(IConfigValueGetter):
"""Base class for getting Vim config values"""
"""Base class for getting Vim config values."""

def _get_vim_var(self, var_name: str) -> Any:
try:
Expand Down
22 changes: 11 additions & 11 deletions python_coderunner/src/config/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,55 +11,55 @@ class EDispatchersTypes(StrEnum):
class IConfig(ABC):
@abstractmethod
def get_by_file_ext(self) -> dict[str, str]:
"""Gets config for file extension-based dispatching"""
"""Gets config for file extension-based dispatching."""
raise NotImplementedError

@abstractmethod
def get_by_file_type(self) -> dict[str, str]:
"""Gets config for file type-based dispatching"""
"""Gets config for file type-based dispatching."""
raise NotImplementedError

@abstractmethod
def get_by_glob(self) -> dict[str, str]:
"""Gets config for glob pattern-based dispatching"""
"""Gets config for glob pattern-based dispatching."""
raise NotImplementedError

@abstractmethod
def get_dispatchers_order(self) -> list[EDispatchersTypes]:
"""Gets the priority order of dispatchers"""
"""Gets the priority order of dispatchers."""
raise NotImplementedError

@abstractmethod
def get_coderunner_tempfile_prefix(self) -> str:
"""Gets the prefix for coderunner temporary files"""
"""Gets the prefix for coderunner temporary files."""
raise NotImplementedError

@abstractmethod
def get_executor(self) -> str:
"""Gets the command executor"""
"""Gets the command executor."""
raise NotImplementedError

@abstractmethod
def get_ignore_selection(self) -> bool:
"""Gets the flag for ignoring selection"""
"""Gets the flag for ignoring selection."""
raise NotImplementedError

@abstractmethod
def get_respect_shebang(self) -> bool:
"""Gets the flag for respecting shebang"""
"""Gets the flag for respecting shebang."""
raise NotImplementedError

@abstractmethod
def get_remove_coderunner_tempfiles_on_exit(self) -> bool:
"""Gets the flag for removing temporary files on exit"""
"""Gets the flag for removing temporary files on exit."""
raise NotImplementedError

@abstractmethod
def get_save_all_files_before_run(self) -> bool:
"""Gets the flag for saving all files before run"""
"""Gets the flag for saving all files before run."""
raise NotImplementedError

@abstractmethod
def get_save_file_before_run(self) -> bool:
"""Gets the flag for saving current file before run"""
"""Gets the flag for saving current file before run."""
raise NotImplementedError
2 changes: 1 addition & 1 deletion python_coderunner/src/config/validator/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
class ValidationError(Exception):
"""Raised when value validation fails"""
"""Raised when value validation fails."""
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from pathlib import Path
from unittest.mock import MagicMock

import pytest
from pytest_mock import MockerFixture

from src.command_builder import ICommandBuilder
from src.command_builders_dispatcher import (
Expand Down Expand Up @@ -64,6 +64,7 @@
],
)
def test_basic_command_dispatcher_strategy_selector(
mocker: MockerFixture,
fixture_shebang_command_builders_dispatcher: TShebangCommandBuildersDispatcher,
fixture_glob_command_builders_dispatcher: TGlobCommandBuildersDispatcher,
fixture_file_ext_command_builders_dispatcher: TFileExtCommandBuildersDispatcher,
Expand All @@ -77,8 +78,9 @@ def test_basic_command_dispatcher_strategy_selector(
) -> None:
file_path_abs = tmp_path / file_path
file_path_abs.write_bytes(content)
config: TBasicConfig = MagicMock(
get_dispatchers_order=MagicMock(return_value=order), get_respect_shebang=MagicMock(return_value=respect_shebang)
config: TBasicConfig = mocker.MagicMock(
get_dispatchers_order=mocker.MagicMock(return_value=order),
get_respect_shebang=mocker.MagicMock(return_value=respect_shebang),
)
selector: TBasicCommandDispatcherStrategySelector = TBasicCommandDispatcherStrategySelector(
shebang_command_builders_dispatcher=fixture_shebang_command_builders_dispatcher,
Expand Down
19 changes: 10 additions & 9 deletions python_coderunner/tests/unit/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
import tempfile
import unittest
from typing import Generator
from unittest import mock
from unittest.mock import MagicMock

import pytest
from pytest_lazyfixture import lazy_fixture
from pytest_mock import MockerFixture

sys.modules["vim"] = MagicMock()
from src.command_builder import ICommandBuilder
Expand Down Expand Up @@ -179,7 +179,7 @@ def fixture_glob_command_builders_dispatcher() -> TGlobCommandBuildersDispatcher
"**/*.log",
"**/*.*.*",
)
glob_to_builder: tuple[tuple[re.Pattern, ICommandBuilder], ...] = tuple(
glob_to_builder: tuple[tuple[re.Pattern[str], ICommandBuilder], ...] = tuple(
(
re.compile(glob.translate(pattern, recursive=True, include_hidden=True)),
MagicMock(spec=ICommandBuilder, build=MagicMock(return_value=pattern)),
Expand All @@ -197,16 +197,17 @@ def fixture_project_info_extractor(request: pytest.FixtureRequest) -> IProjectIn

@pytest.fixture
def fixture_vim_project_info_extractor(
mocker: MockerFixture,
fixture_file_info_extractor: IFileInfoExtractor,
) -> Generator[IProjectInfoExtractor, None, None]:
with tempfile.TemporaryDirectory() as temp_dir:
extractor: TVimProjectInfoExtractor = TVimProjectInfoExtractor(fixture_file_info_extractor)
with mock.patch.object(
mocker.patch.object(
extractor,
"get_workspace_root",
return_value=temp_dir,
):
yield extractor
)
yield extractor


@pytest.fixture(params=(lazy_fixture("fixture_vim_file_info_extractor"),))
Expand All @@ -215,7 +216,7 @@ def fixture_file_info_extractor(request: pytest.FixtureRequest) -> IFileInfoExtr


@pytest.fixture
def fixture_vim_file_info_extractor() -> Generator[IFileInfoExtractor, None, None]:
def fixture_vim_file_info_extractor(mocker: MockerFixture) -> IFileInfoExtractor:
extractor: TVimFileInfoExtractor = TVimFileInfoExtractor()
ext_to_lang: dict[str, str] = {
".py": "python",
Expand All @@ -224,9 +225,9 @@ def fixture_vim_file_info_extractor() -> Generator[IFileInfoExtractor, None, Non
".ts": "typescript",
".js": "javascript",
}
with mock.patch.object(
mocker.patch.object(
extractor,
"get_file_type",
side_effect=lambda file_path_abs: ext_to_lang.get(extractor.get_file_ext(file_path_abs)),
):
yield extractor
)
return extractor
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import os
import tempfile
from unittest.mock import patch

import pytest
from pytest_mock import MockerFixture

from src.file_info_extractor import IFileInfoExtractor

Expand Down Expand Up @@ -86,10 +86,14 @@ def test_get_shebang(
finally:
os.unlink(file_path)

def test_get_shebang_io_error_handling(self, fixture_file_info_extractor: IFileInfoExtractor) -> None:
with patch("builtins.open", side_effect=IOError("Permission denied")):
assert fixture_file_info_extractor.get_shebang("/some/file") is None
def test_get_shebang_io_error_handling(
self, mocker: MockerFixture, fixture_file_info_extractor: IFileInfoExtractor
) -> None:
mocker.patch("builtins.open", side_effect=IOError("Permission denied"))
assert fixture_file_info_extractor.get_shebang("/some/file") is None

def test_get_shebang_unicode_decode_error_handling(self, fixture_file_info_extractor: IFileInfoExtractor) -> None:
with patch("builtins.open", side_effect=UnicodeDecodeError("utf-8", b"", 0, 1, "Invalid byte")):
assert fixture_file_info_extractor.get_shebang("/some/file") is None
def test_get_shebang_unicode_decode_error_handling(
self, mocker: MockerFixture, fixture_file_info_extractor: IFileInfoExtractor
) -> None:
mocker.patch("builtins.open", side_effect=UnicodeDecodeError("utf-8", b"", 0, 1, "Invalid byte"))
assert fixture_file_info_extractor.get_shebang("/some/file") is None
Loading
Loading