diff --git a/.flake8 b/.flake8 deleted file mode 100644 index 2bcd70e..0000000 --- a/.flake8 +++ /dev/null @@ -1,2 +0,0 @@ -[flake8] -max-line-length = 88 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..7de5efd --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,21 @@ +# See https://pre-commit.com for more information +# See https://pre-commit.com/hooks.html for more hooks +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.5.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-added-large-files + + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: 'v0.1.9' + hooks: + - id: ruff + args: [--fix, --exit-non-zero-on-fix, --show-fixes] + - id: ruff-format + + - repo: https://github.com/pre-commit/mirrors-mypy + rev: v1.8.0 + hooks: + - id: mypy diff --git a/pyproject.toml b/pyproject.toml index 9eec394..66806c7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -31,8 +31,8 @@ pr = "onepm:pr" pun = "onepm:pun" pa = "onepm:pa" -[tool.pdm] -version = {source = "scm"} +[tool.pdm.version] +source = "scm" [tool.pdm.dev-dependencies] test = [ @@ -42,3 +42,19 @@ test = [ [build-system] requires = ["pdm-backend"] build-backend = "pdm.backend" + +[tool.ruff] +target-version = "py310" + +[tool.ruff.lint] +extend-select = [ + "I", # isort + "B", # flake8-bugbear + "C4", # flake8-comprehensions + "RUF", # ruff + "W", # pycodestyle + "YTT", # flake8-2020 +] + +[tool.ruff.isort] +known-first-party = ["onepm"] diff --git a/src/onepm/__init__.py b/src/onepm/__init__.py index 130e3af..37ebb75 100644 --- a/src/onepm/__init__.py +++ b/src/onepm/__init__.py @@ -1,6 +1,8 @@ +from __future__ import annotations + import os import sys -from typing import Callable, Dict, List, NoReturn, Optional, Type +from typing import Callable, NoReturn from onepm.base import PackageManager from onepm.pdm import PDM @@ -14,8 +16,9 @@ import tomli as tomllib -PACKAGE_MANAGERS: Dict[str, Type[PackageManager]] = { - p.name: p for p in [Pip, Pipenv, Poetry, PDM] +PACKAGE_MANAGERS: dict[str, type[PackageManager]] = { + p.name: p # type: ignore[type-abstract] + for p in [Pip, Pipenv, Poetry, PDM] } @@ -40,8 +43,8 @@ def determine_package_manager() -> str: return "pip" -def make_shortcut(method_name: str) -> Callable[[Optional[List[str]]], NoReturn]: - def main(args: Optional[List[str]] = None) -> NoReturn: +def make_shortcut(method_name: str) -> Callable[[list[str] | None], NoReturn]: + def main(args: list[str] | None = None) -> NoReturn: # type: ignore[misc] if args is None: args = sys.argv[1:] package_manager = PACKAGE_MANAGERS[determine_package_manager()]() diff --git a/src/onepm/base.py b/src/onepm/base.py index 40c17ad..c22c99e 100644 --- a/src/onepm/base.py +++ b/src/onepm/base.py @@ -1,16 +1,18 @@ +from __future__ import annotations + import abc import os import shutil import subprocess import sys -from typing import Iterable, List, NoReturn +from typing import Iterable, NoReturn class PackageManager(metaclass=abc.ABCMeta): name: str @staticmethod - def has_unknown_args(args: Iterable[str], expecting_values: List[str]) -> bool: + def has_unknown_args(args: Iterable[str], expecting_values: list[str]) -> bool: args_iter = iter(args) for arg in args_iter: @@ -42,14 +44,14 @@ def execute(self, *args: str) -> NoReturn: self._execute_command(command_args) @staticmethod - def _execute_command(args: List[str]) -> NoReturn: + def _execute_command(args: list[str]) -> NoReturn: if sys.platform == "win32": sys.exit(subprocess.run(args).returncode) else: os.execvp(args[0], args) @abc.abstractmethod - def get_command(self) -> List[str]: + def get_command(self) -> list[str]: pass @abc.abstractmethod diff --git a/src/onepm/pdm.py b/src/onepm/pdm.py index 101fe31..60ed0bf 100644 --- a/src/onepm/pdm.py +++ b/src/onepm/pdm.py @@ -1,4 +1,6 @@ -from typing import List, NoReturn +from __future__ import annotations + +from typing import NoReturn from onepm.base import PackageManager @@ -6,7 +8,7 @@ class PDM(PackageManager): name = "pdm" - def get_command(self) -> List[str]: + def get_command(self) -> list[str]: return [self.find_executable(self.name)] def install(self, *args: str) -> NoReturn: diff --git a/src/onepm/pip.py b/src/onepm/pip.py index d87232f..7b84a8a 100644 --- a/src/onepm/pip.py +++ b/src/onepm/pip.py @@ -1,6 +1,8 @@ +from __future__ import annotations + import os import sys -from typing import List, NoReturn, Optional +from typing import NoReturn from onepm.base import PackageManager @@ -22,23 +24,23 @@ def _ensure_virtualenv(self) -> str: except ImportError: raise Exception( "To use pip, you must activate a virtualenv or create one at `.venv`." - ) + ) from None venv.create(this_venv, with_pip=True) return this_venv - def _find_requirements_txt(self) -> Optional[str]: + def _find_requirements_txt(self) -> str | None: for filename in ["requirements.txt", "requirements.in"]: if os.path.exists(filename): return filename return None - def _find_setup_py(self) -> Optional[str]: + def _find_setup_py(self) -> str | None: for filename in ["setup.py", "pyproject.toml"]: if os.path.exists(filename): return filename return None - def get_command(self) -> List[str]: + def get_command(self) -> list[str]: venv = self._ensure_virtualenv() if sys.platform == "win32": bin_dir = "Scripts" @@ -62,7 +64,7 @@ def install(self, *args: str) -> NoReturn: "please specify packages to install." ) else: - expanded_args = ["install"] + list(args) + expanded_args = ["install", *args] self.execute(*expanded_args) def update(self, *args: str) -> NoReturn: diff --git a/src/onepm/pipenv.py b/src/onepm/pipenv.py index a848652..830fd3c 100644 --- a/src/onepm/pipenv.py +++ b/src/onepm/pipenv.py @@ -1,4 +1,6 @@ -from typing import List, NoReturn +from __future__ import annotations + +from typing import NoReturn from onepm.base import PackageManager @@ -6,7 +8,7 @@ class Pipenv(PackageManager): name = "pipenv" - def get_command(self) -> List[str]: + def get_command(self) -> list[str]: return [self.find_executable(self.name)] def install(self, *args: str) -> NoReturn: diff --git a/src/onepm/poetry.py b/src/onepm/poetry.py index 51eb7a6..1782f46 100644 --- a/src/onepm/poetry.py +++ b/src/onepm/poetry.py @@ -1,4 +1,6 @@ -from typing import List, NoReturn +from __future__ import annotations + +from typing import NoReturn from onepm.base import PackageManager @@ -6,7 +8,7 @@ class Poetry(PackageManager): name = "poetry" - def get_command(self) -> List[str]: + def get_command(self) -> list[str]: return [self.find_executable(self.name)] def install(self, *args: str) -> NoReturn: diff --git a/tests/conftest.py b/tests/conftest.py index 65fed97..a2a3e99 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,5 +1,6 @@ import os from unittest import mock + import pytest diff --git a/tests/test_pdm.py b/tests/test_pdm.py index d044c30..d2184b0 100644 --- a/tests/test_pdm.py +++ b/tests/test_pdm.py @@ -1,6 +1,7 @@ -from onepm import pi, pa, pu, pun, pr import pytest +from onepm import pa, pi, pr, pu, pun + pytestmark = pytest.mark.usefixtures("pdm") @@ -17,7 +18,7 @@ ) def test_pdm_pi_dispatch(project, execute_args, args, expected_command): pi(args) - assert execute_args[1:] == [expected_command] + args + assert execute_args[1:] == [expected_command, *args] def test_pdm_pr(project, execute_args): diff --git a/tests/test_pip.py b/tests/test_pip.py index 0faa015..88b2857 100644 --- a/tests/test_pip.py +++ b/tests/test_pip.py @@ -2,6 +2,7 @@ import sys import pytest + from onepm import pa, pi, pr, pu, pun from onepm.pip import Pip diff --git a/tests/test_pipenv.py b/tests/test_pipenv.py index 6c6885a..2f31736 100644 --- a/tests/test_pipenv.py +++ b/tests/test_pipenv.py @@ -1,6 +1,6 @@ import pytest -from onepm import pi, pa, pu, pun, pr +from onepm import pa, pi, pr, pu, pun pytestmark = pytest.mark.usefixtures("pipenv") @@ -8,7 +8,7 @@ @pytest.mark.parametrize("args", [[], ["--dev"], ["--keep-outdated", "requests"]]) def test_pipenv_pi(project, execute_args, args): pi(args) - assert execute_args[1:] == ["install"] + args + assert execute_args[1:] == ["install", *args] def test_pipenv_pr(project, execute_args): diff --git a/tests/test_poetry.py b/tests/test_poetry.py index 4a9578b..4fe21f5 100644 --- a/tests/test_poetry.py +++ b/tests/test_poetry.py @@ -1,4 +1,5 @@ import pytest + from onepm import pa, pi, pr, pu, pun pytestmark = pytest.mark.usefixtures("poetry") @@ -16,7 +17,7 @@ ) def test_poetry_pi_dispatch(project, execute_args, args, expected_command): pi(args) - assert execute_args[1:] == [expected_command] + args + assert execute_args[1:] == [expected_command, *args] def test_poetry_pu(project, execute_args): diff --git a/tests/test_utils.py b/tests/test_utils.py index eb6a6df..9fead4e 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -1,4 +1,5 @@ import pytest + from onepm import determine_package_manager