From 501f5797a2f4f028b2283751d03fe27b30450cdb Mon Sep 17 00:00:00 2001 From: Nathan McDougall Date: Thu, 24 Oct 2024 15:49:40 +1300 Subject: [PATCH] Add import-linter (#50) --- pyproject.toml | 17 ++++++ src/usethis/__init__.py | 6 -- src/usethis/__main__.py | 14 +++-- src/usethis/_console.py | 6 ++ .../__init__.py | 0 .../bitbucket}/__init__.py | 0 .../bitbucket}/cache.py | 2 +- .../bitbucket}/config.py | 2 +- .../bitbucket}/steps.py | 4 +- .../github}/__init__.py | 0 .../{_github => _integrations/github}/tags.py | 0 .../pre_commit}/__init__.py | 0 .../pre_commit}/config.py | 0 .../pre_commit}/core.py | 4 +- .../pre_commit}/hooks.py | 4 +- .../_integrations/pyproject/__init__.py | 0 .../pyproject}/config.py | 0 .../pyproject}/core.py | 5 +- .../pyproject}/io.py | 0 .../pyproject}/requires_python.py | 2 +- src/usethis/_integrations/pytest/__init__.py | 0 .../{_pytest => _integrations/pytest}/core.py | 2 +- src/usethis/_integrations/ruff/__init__.py | 0 .../{_ruff => _integrations/ruff}/rules.py | 4 +- src/usethis/_integrations/uv/__init__.py | 0 src/usethis/{_uv => _integrations/uv}/deps.py | 4 +- src/usethis/_interface/__init__.py | 3 + src/usethis/{ => _interface}/browse.py | 2 +- src/usethis/{ => _interface}/ci.py | 11 ++-- src/usethis/{ => _interface}/tool.py | 11 ++-- src/usethis/_tool.py | 16 +++--- src/usethis/_utils/__init__.py | 0 src/usethis/{ => _utils}/_test.py | 0 src/usethis/{ => _utils}/_yaml.py | 0 .../bitbucket}/test_cache.py | 4 +- .../bitbucket}/test_steps.py | 4 +- .../github}/test_tags.py | 2 +- .../pre_commit}/test_core.py | 4 +- .../pre_commit}/test_hooks.py | 6 +- .../pyproject}/test_core.py | 6 +- .../pyproject}/test_requires_python.py | 6 +- .../pytest}/test_core.py | 4 +- .../ruff}/test_rules.py | 10 +++- .../usethis/{_uv => _integrations/uv}/deps.py | 4 +- tests/usethis/{ => _interface}/test_browse.py | 2 +- tests/usethis/_interface/test_ci.py | 47 ++++++++++++++++ tests/usethis/{ => _interface}/test_tool.py | 47 ++++++++++------ uv.lock | 55 +++++++++++++++++++ 48 files changed, 234 insertions(+), 86 deletions(-) create mode 100644 src/usethis/_console.py rename src/usethis/{_pre_commit => _integrations}/__init__.py (100%) rename src/usethis/{_pyproject => _integrations/bitbucket}/__init__.py (100%) rename src/usethis/{_bitbucket => _integrations/bitbucket}/cache.py (96%) rename src/usethis/{_bitbucket => _integrations/bitbucket}/config.py (96%) rename src/usethis/{_bitbucket => _integrations/bitbucket}/steps.py (96%) rename src/usethis/{_pytest => _integrations/github}/__init__.py (100%) rename src/usethis/{_github => _integrations/github}/tags.py (100%) rename src/usethis/{_uv => _integrations/pre_commit}/__init__.py (100%) rename src/usethis/{_pre_commit => _integrations/pre_commit}/config.py (100%) rename src/usethis/{_pre_commit => _integrations/pre_commit}/core.py (93%) rename src/usethis/{_pre_commit => _integrations/pre_commit}/hooks.py (96%) create mode 100644 src/usethis/_integrations/pyproject/__init__.py rename src/usethis/{_pyproject => _integrations/pyproject}/config.py (100%) rename src/usethis/{_pyproject => _integrations/pyproject}/core.py (97%) rename src/usethis/{_pyproject => _integrations/pyproject}/io.py (100%) rename src/usethis/{_pyproject => _integrations/pyproject}/requires_python.py (92%) create mode 100644 src/usethis/_integrations/pytest/__init__.py rename src/usethis/{_pytest => _integrations/pytest}/core.py (96%) create mode 100644 src/usethis/_integrations/ruff/__init__.py rename src/usethis/{_ruff => _integrations/ruff}/rules.py (93%) create mode 100644 src/usethis/_integrations/uv/__init__.py rename src/usethis/{_uv => _integrations/uv}/deps.py (95%) create mode 100644 src/usethis/_interface/__init__.py rename src/usethis/{ => _interface}/browse.py (94%) rename src/usethis/{ => _interface}/ci.py (87%) rename src/usethis/{ => _interface}/tool.py (92%) create mode 100644 src/usethis/_utils/__init__.py rename src/usethis/{ => _utils}/_test.py (100%) rename src/usethis/{ => _utils}/_yaml.py (100%) rename tests/usethis/{_bitbucket => _integrations/bitbucket}/test_cache.py (72%) rename tests/usethis/{_bitbucket => _integrations/bitbucket}/test_steps.py (89%) rename tests/usethis/{_github => _integrations/github}/test_tags.py (96%) rename tests/usethis/{_pre_commit => _integrations/pre_commit}/test_core.py (97%) rename tests/usethis/{_pre_commit => _integrations/pre_commit}/test_hooks.py (94%) rename tests/usethis/{_pyproject => _integrations/pyproject}/test_core.py (97%) rename tests/usethis/{_pyproject => _integrations/pyproject}/test_requires_python.py (93%) rename tests/usethis/{_pytest => _integrations/pytest}/test_core.py (94%) rename tests/usethis/{_ruff => _integrations/ruff}/test_rules.py (91%) rename tests/usethis/{_uv => _integrations/uv}/deps.py (91%) rename tests/usethis/{ => _interface}/test_browse.py (94%) create mode 100644 tests/usethis/_interface/test_ci.py rename tests/usethis/{ => _interface}/test_tool.py (95%) diff --git a/pyproject.toml b/pyproject.toml index 94b6d98..5a7e40f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -33,6 +33,7 @@ dev-dependencies = [ "pytest-cov>=5.0.0", "gitpython>=3.1.43", "pre-commit>=4.0.1", + "import-linter>=2.1", ] [tool.ruff] @@ -52,3 +53,19 @@ addopts = [ [tool.coverage.run] source = ["src"] omit = ["*/pytest-of-*/*"] + +[tool.importlinter] +root_packages = ["usethis"] + +[[tool.importlinter.contracts]] +name = "Modular Design" +type = "layers" +layers = [ + "__main__", + "_interface", + "_tool", + "_integrations", + "_utils" +] +containers=["usethis"] +exhaustive=true \ No newline at end of file diff --git a/src/usethis/__init__.py b/src/usethis/__init__.py index f3392e6..e69de29 100644 --- a/src/usethis/__init__.py +++ b/src/usethis/__init__.py @@ -1,6 +0,0 @@ -import typer -from rich.console import Console - -console = Console() - -offline_opt = typer.Option(False, "--offline", help="Disable network access") diff --git a/src/usethis/__main__.py b/src/usethis/__main__.py index 8a6ddd2..cb60be8 100644 --- a/src/usethis/__main__.py +++ b/src/usethis/__main__.py @@ -1,8 +1,8 @@ import typer -import usethis.browse -import usethis.ci -import usethis.tool +import usethis._interface.browse +import usethis._interface.ci +import usethis._interface.tool app = typer.Typer( help=( @@ -10,7 +10,9 @@ "performed manually." ) ) -app.add_typer(usethis.tool.app, name="tool") -app.add_typer(usethis.browse.app, name="browse") -app.add_typer(usethis.ci.app, name="ci") +app.add_typer(usethis._interface.tool.app, name="tool") +app.add_typer(usethis._interface.browse.app, name="browse") +app.add_typer(usethis._interface.ci.app, name="ci") app(prog_name="usethis") + +__all__ = ["app"] diff --git a/src/usethis/_console.py b/src/usethis/_console.py new file mode 100644 index 0000000..f3392e6 --- /dev/null +++ b/src/usethis/_console.py @@ -0,0 +1,6 @@ +import typer +from rich.console import Console + +console = Console() + +offline_opt = typer.Option(False, "--offline", help="Disable network access") diff --git a/src/usethis/_pre_commit/__init__.py b/src/usethis/_integrations/__init__.py similarity index 100% rename from src/usethis/_pre_commit/__init__.py rename to src/usethis/_integrations/__init__.py diff --git a/src/usethis/_pyproject/__init__.py b/src/usethis/_integrations/bitbucket/__init__.py similarity index 100% rename from src/usethis/_pyproject/__init__.py rename to src/usethis/_integrations/bitbucket/__init__.py diff --git a/src/usethis/_bitbucket/cache.py b/src/usethis/_integrations/bitbucket/cache.py similarity index 96% rename from src/usethis/_bitbucket/cache.py rename to src/usethis/_integrations/bitbucket/cache.py index 2a2a64a..e2d616d 100644 --- a/src/usethis/_bitbucket/cache.py +++ b/src/usethis/_integrations/bitbucket/cache.py @@ -2,7 +2,7 @@ from pydantic import BaseModel -from usethis._yaml import edit_yaml, load_yaml +from usethis._utils._yaml import edit_yaml, load_yaml class Cache(BaseModel): diff --git a/src/usethis/_bitbucket/config.py b/src/usethis/_integrations/bitbucket/config.py similarity index 96% rename from src/usethis/_bitbucket/config.py rename to src/usethis/_integrations/bitbucket/config.py index 939273c..5d16384 100644 --- a/src/usethis/_bitbucket/config.py +++ b/src/usethis/_integrations/bitbucket/config.py @@ -1,6 +1,6 @@ from pathlib import Path -from usethis import console +from usethis._console import console _YAML_CONTENTS = """\ image: atlassian/default-image:3 diff --git a/src/usethis/_bitbucket/steps.py b/src/usethis/_integrations/bitbucket/steps.py similarity index 96% rename from src/usethis/_bitbucket/steps.py rename to src/usethis/_integrations/bitbucket/steps.py index c469bd2..306b7a6 100644 --- a/src/usethis/_bitbucket/steps.py +++ b/src/usethis/_integrations/bitbucket/steps.py @@ -3,8 +3,8 @@ from pydantic import BaseModel -from usethis._bitbucket.cache import Cache, add_cache -from usethis._yaml import edit_yaml +from usethis._integrations.bitbucket.cache import Cache, add_cache +from usethis._utils._yaml import edit_yaml class StepRef(BaseModel): diff --git a/src/usethis/_pytest/__init__.py b/src/usethis/_integrations/github/__init__.py similarity index 100% rename from src/usethis/_pytest/__init__.py rename to src/usethis/_integrations/github/__init__.py diff --git a/src/usethis/_github/tags.py b/src/usethis/_integrations/github/tags.py similarity index 100% rename from src/usethis/_github/tags.py rename to src/usethis/_integrations/github/tags.py diff --git a/src/usethis/_uv/__init__.py b/src/usethis/_integrations/pre_commit/__init__.py similarity index 100% rename from src/usethis/_uv/__init__.py rename to src/usethis/_integrations/pre_commit/__init__.py diff --git a/src/usethis/_pre_commit/config.py b/src/usethis/_integrations/pre_commit/config.py similarity index 100% rename from src/usethis/_pre_commit/config.py rename to src/usethis/_integrations/pre_commit/config.py diff --git a/src/usethis/_pre_commit/core.py b/src/usethis/_integrations/pre_commit/core.py similarity index 93% rename from src/usethis/_pre_commit/core.py rename to src/usethis/_integrations/pre_commit/core.py index 3089c59..9c48dc0 100644 --- a/src/usethis/_pre_commit/core.py +++ b/src/usethis/_integrations/pre_commit/core.py @@ -1,8 +1,8 @@ import subprocess from pathlib import Path -from usethis import console -from usethis._github.tags import GitHubTagError, get_github_latest_tag +from usethis._console import console +from usethis._integrations.github.tags import GitHubTagError, get_github_latest_tag _YAML_CONTENTS_TEMPLATE = """\ repos: diff --git a/src/usethis/_pre_commit/hooks.py b/src/usethis/_integrations/pre_commit/hooks.py similarity index 96% rename from src/usethis/_pre_commit/hooks.py rename to src/usethis/_integrations/pre_commit/hooks.py index f015d6f..c3bcc65 100644 --- a/src/usethis/_pre_commit/hooks.py +++ b/src/usethis/_integrations/pre_commit/hooks.py @@ -3,8 +3,8 @@ import ruamel.yaml -from usethis._pre_commit.config import PreCommitRepoConfig -from usethis._yaml import edit_yaml +from usethis._integrations.pre_commit.config import PreCommitRepoConfig +from usethis._utils._yaml import edit_yaml _HOOK_ORDER = [ "validate-pyproject", diff --git a/src/usethis/_integrations/pyproject/__init__.py b/src/usethis/_integrations/pyproject/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/usethis/_pyproject/config.py b/src/usethis/_integrations/pyproject/config.py similarity index 100% rename from src/usethis/_pyproject/config.py rename to src/usethis/_integrations/pyproject/config.py diff --git a/src/usethis/_pyproject/core.py b/src/usethis/_integrations/pyproject/core.py similarity index 97% rename from src/usethis/_pyproject/core.py rename to src/usethis/_integrations/pyproject/core.py index 81d12c0..598a63d 100644 --- a/src/usethis/_pyproject/core.py +++ b/src/usethis/_integrations/pyproject/core.py @@ -2,7 +2,10 @@ import mergedeep -from usethis._pyproject.io import read_pyproject_toml, write_pyproject_toml +from usethis._integrations.pyproject.io import ( + read_pyproject_toml, + write_pyproject_toml, +) class ConfigValueAlreadySetError(ValueError): diff --git a/src/usethis/_pyproject/io.py b/src/usethis/_integrations/pyproject/io.py similarity index 100% rename from src/usethis/_pyproject/io.py rename to src/usethis/_integrations/pyproject/io.py diff --git a/src/usethis/_pyproject/requires_python.py b/src/usethis/_integrations/pyproject/requires_python.py similarity index 92% rename from src/usethis/_pyproject/requires_python.py rename to src/usethis/_integrations/pyproject/requires_python.py index 2b36f7c..10f161f 100644 --- a/src/usethis/_pyproject/requires_python.py +++ b/src/usethis/_integrations/pyproject/requires_python.py @@ -1,6 +1,6 @@ from packaging.specifiers import SpecifierSet -from usethis._pyproject.io import read_pyproject_toml +from usethis._integrations.pyproject.io import read_pyproject_toml MIN_MAJOR_PY3 = 7 # Any earlier and uv won't support the executable. MAX_MAJOR_PY3 = 13 diff --git a/src/usethis/_integrations/pytest/__init__.py b/src/usethis/_integrations/pytest/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/usethis/_pytest/core.py b/src/usethis/_integrations/pytest/core.py similarity index 96% rename from src/usethis/_pytest/core.py rename to src/usethis/_integrations/pytest/core.py index 13b27a8..9abe8e1 100644 --- a/src/usethis/_pytest/core.py +++ b/src/usethis/_integrations/pytest/core.py @@ -1,7 +1,7 @@ import shutil from pathlib import Path -from usethis import console +from usethis._console import console def add_pytest_dir() -> None: diff --git a/src/usethis/_integrations/ruff/__init__.py b/src/usethis/_integrations/ruff/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/usethis/_ruff/rules.py b/src/usethis/_integrations/ruff/rules.py similarity index 93% rename from src/usethis/_ruff/rules.py rename to src/usethis/_integrations/ruff/rules.py index 872e999..2b17ca2 100644 --- a/src/usethis/_ruff/rules.py +++ b/src/usethis/_integrations/ruff/rules.py @@ -1,5 +1,5 @@ -from usethis import console -from usethis._pyproject.core import ( +from usethis._console import console +from usethis._integrations.pyproject.core import ( append_config_list, get_config_value, remove_from_config_list, diff --git a/src/usethis/_integrations/uv/__init__.py b/src/usethis/_integrations/uv/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/usethis/_uv/deps.py b/src/usethis/_integrations/uv/deps.py similarity index 95% rename from src/usethis/_uv/deps.py rename to src/usethis/_integrations/uv/deps.py index b63c6fa..f8d6fd5 100644 --- a/src/usethis/_uv/deps.py +++ b/src/usethis/_integrations/uv/deps.py @@ -4,8 +4,8 @@ from packaging.requirements import Requirement from pydantic import TypeAdapter -from usethis import console -from usethis._pyproject.io import read_pyproject_toml +from usethis._console import console +from usethis._integrations.pyproject.io import read_pyproject_toml def get_dev_deps() -> list[str]: diff --git a/src/usethis/_interface/__init__.py b/src/usethis/_interface/__init__.py new file mode 100644 index 0000000..a1f9160 --- /dev/null +++ b/src/usethis/_interface/__init__.py @@ -0,0 +1,3 @@ +import typer + +offline_opt = typer.Option(False, "--offline", help="Disable network access") diff --git a/src/usethis/browse.py b/src/usethis/_interface/browse.py similarity index 94% rename from src/usethis/browse.py rename to src/usethis/_interface/browse.py index 7c6a841..1a45d51 100644 --- a/src/usethis/browse.py +++ b/src/usethis/_interface/browse.py @@ -1,6 +1,6 @@ import typer -from usethis import console +from usethis._console import console app = typer.Typer(help="Visit important project-related web pages.") diff --git a/src/usethis/ci.py b/src/usethis/_interface/ci.py similarity index 87% rename from src/usethis/ci.py rename to src/usethis/_interface/ci.py index 451287e..f97ec09 100644 --- a/src/usethis/ci.py +++ b/src/usethis/_interface/ci.py @@ -2,13 +2,16 @@ import typer -from usethis import console, offline_opt -from usethis._bitbucket.config import ( +from usethis._console import console +from usethis._integrations.bitbucket.config import ( add_bitbucket_pipeline_config, remove_bitbucket_pipeline_config, ) -from usethis._bitbucket.steps import Step, StepRef, add_steps -from usethis._pyproject.requires_python import get_supported_major_python_versions +from usethis._integrations.bitbucket.steps import Step, StepRef, add_steps +from usethis._integrations.pyproject.requires_python import ( + get_supported_major_python_versions, +) +from usethis._interface import offline_opt from usethis._tool import PreCommitTool, PytestTool app = typer.Typer(help="Add config for Continuous Integration (CI) pipelines.") diff --git a/src/usethis/tool.py b/src/usethis/_interface/tool.py similarity index 92% rename from src/usethis/tool.py rename to src/usethis/_interface/tool.py index 4832ef8..45d0bfd 100644 --- a/src/usethis/tool.py +++ b/src/usethis/_interface/tool.py @@ -2,17 +2,18 @@ import typer -from usethis import console, offline_opt -from usethis._pre_commit.core import ( +from usethis._console import console +from usethis._integrations.pre_commit.core import ( add_pre_commit_config, install_pre_commit, remove_pre_commit_config, uninstall_pre_commit, ) -from usethis._pytest.core import add_pytest_dir, remove_pytest_dir -from usethis._ruff.rules import deselect_ruff_rules, select_ruff_rules +from usethis._integrations.pytest.core import add_pytest_dir, remove_pytest_dir +from usethis._integrations.ruff.rules import deselect_ruff_rules, select_ruff_rules +from usethis._integrations.uv.deps import add_dev_deps, remove_dev_deps +from usethis._interface import offline_opt from usethis._tool import ALL_TOOLS, DeptryTool, PreCommitTool, PytestTool, RuffTool -from usethis._uv.deps import add_dev_deps, remove_dev_deps app = typer.Typer(help="Add and configure development tools, e.g. linters.") diff --git a/src/usethis/_tool.py b/src/usethis/_tool.py index 6705dba..afedb31 100644 --- a/src/usethis/_tool.py +++ b/src/usethis/_tool.py @@ -2,23 +2,23 @@ from pathlib import Path from typing import Protocol -from usethis import console -from usethis._pre_commit.config import HookConfig, PreCommitRepoConfig -from usethis._pre_commit.core import add_pre_commit_config -from usethis._pre_commit.hooks import ( +from usethis._console import console +from usethis._integrations.pre_commit.config import HookConfig, PreCommitRepoConfig +from usethis._integrations.pre_commit.core import add_pre_commit_config +from usethis._integrations.pre_commit.hooks import ( add_hook, get_hook_names, remove_hook, ) -from usethis._pyproject.config import PyProjectConfig -from usethis._pyproject.core import ( +from usethis._integrations.pyproject.config import PyProjectConfig +from usethis._integrations.pyproject.core import ( ConfigValueAlreadySetError, ConfigValueMissingError, remove_config_value, set_config_value, ) -from usethis._pyproject.io import read_pyproject_toml -from usethis._uv.deps import is_dep_used +from usethis._integrations.pyproject.io import read_pyproject_toml +from usethis._integrations.uv.deps import is_dep_used class Tool(Protocol): diff --git a/src/usethis/_utils/__init__.py b/src/usethis/_utils/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/usethis/_test.py b/src/usethis/_utils/_test.py similarity index 100% rename from src/usethis/_test.py rename to src/usethis/_utils/_test.py diff --git a/src/usethis/_yaml.py b/src/usethis/_utils/_yaml.py similarity index 100% rename from src/usethis/_yaml.py rename to src/usethis/_utils/_yaml.py diff --git a/tests/usethis/_bitbucket/test_cache.py b/tests/usethis/_integrations/bitbucket/test_cache.py similarity index 72% rename from tests/usethis/_bitbucket/test_cache.py rename to tests/usethis/_integrations/bitbucket/test_cache.py index b4a482b..a41113a 100644 --- a/tests/usethis/_bitbucket/test_cache.py +++ b/tests/usethis/_integrations/bitbucket/test_cache.py @@ -1,7 +1,7 @@ from pathlib import Path -from usethis._bitbucket.cache import Cache, add_cache, get_caches -from usethis._test import change_cwd +from usethis._integrations.bitbucket.cache import Cache, add_cache, get_caches +from usethis._utils._test import change_cwd class TestAddCache: diff --git a/tests/usethis/_bitbucket/test_steps.py b/tests/usethis/_integrations/bitbucket/test_steps.py similarity index 89% rename from tests/usethis/_bitbucket/test_steps.py rename to tests/usethis/_integrations/bitbucket/test_steps.py index 5600894..287fba8 100644 --- a/tests/usethis/_bitbucket/test_steps.py +++ b/tests/usethis/_integrations/bitbucket/test_steps.py @@ -1,7 +1,7 @@ from pathlib import Path -from usethis._bitbucket.steps import Step, add_steps -from usethis._test import change_cwd +from usethis._integrations.bitbucket.steps import Step, add_steps +from usethis._utils._test import change_cwd class TestAddStep: diff --git a/tests/usethis/_github/test_tags.py b/tests/usethis/_integrations/github/test_tags.py similarity index 96% rename from tests/usethis/_github/test_tags.py rename to tests/usethis/_integrations/github/test_tags.py index d678888..c879b9e 100644 --- a/tests/usethis/_github/test_tags.py +++ b/tests/usethis/_integrations/github/test_tags.py @@ -1,7 +1,7 @@ import pytest import requests -from usethis._github.tags import ( +from usethis._integrations.github.tags import ( GitHubTagError, NoGitHubTagsFoundError, get_github_latest_tag, diff --git a/tests/usethis/_pre_commit/test_core.py b/tests/usethis/_integrations/pre_commit/test_core.py similarity index 97% rename from tests/usethis/_pre_commit/test_core.py rename to tests/usethis/_integrations/pre_commit/test_core.py index 6f53bbd..759346a 100644 --- a/tests/usethis/_pre_commit/test_core.py +++ b/tests/usethis/_integrations/pre_commit/test_core.py @@ -3,12 +3,12 @@ import pytest import requests -from usethis._pre_commit.core import ( +from usethis._integrations.pre_commit.core import ( _VALIDATEPYPROJECT_VERSION, add_pre_commit_config, remove_pre_commit_config, ) -from usethis._test import change_cwd +from usethis._utils._test import change_cwd class TestAddPreCommitConfig: diff --git a/tests/usethis/_pre_commit/test_hooks.py b/tests/usethis/_integrations/pre_commit/test_hooks.py similarity index 94% rename from tests/usethis/_pre_commit/test_hooks.py rename to tests/usethis/_integrations/pre_commit/test_hooks.py index e811e40..8b22086 100644 --- a/tests/usethis/_pre_commit/test_hooks.py +++ b/tests/usethis/_integrations/pre_commit/test_hooks.py @@ -2,14 +2,14 @@ import pytest -from usethis._pre_commit.config import HookConfig, PreCommitRepoConfig -from usethis._pre_commit.hooks import ( +from usethis._integrations.pre_commit.config import HookConfig, PreCommitRepoConfig +from usethis._integrations.pre_commit.hooks import ( DuplicatedHookNameError, add_hook, get_hook_names, remove_hook, ) -from usethis._test import change_cwd +from usethis._utils._test import change_cwd class TestAddHook: diff --git a/tests/usethis/_pyproject/test_core.py b/tests/usethis/_integrations/pyproject/test_core.py similarity index 97% rename from tests/usethis/_pyproject/test_core.py rename to tests/usethis/_integrations/pyproject/test_core.py index 426b036..2e33ed4 100644 --- a/tests/usethis/_pyproject/test_core.py +++ b/tests/usethis/_integrations/pyproject/test_core.py @@ -3,7 +3,7 @@ import pytest -from usethis._pyproject.core import ( +from usethis._integrations.pyproject.core import ( ConfigValueAlreadySetError, ConfigValueMissingError, append_config_list, @@ -11,8 +11,8 @@ remove_config_value, set_config_value, ) -from usethis._pyproject.io import PyProjectTOMLNotFoundError -from usethis._test import change_cwd +from usethis._integrations.pyproject.io import PyProjectTOMLNotFoundError +from usethis._utils._test import change_cwd class TestGetConfigValue: diff --git a/tests/usethis/_pyproject/test_requires_python.py b/tests/usethis/_integrations/pyproject/test_requires_python.py similarity index 93% rename from tests/usethis/_pyproject/test_requires_python.py rename to tests/usethis/_integrations/pyproject/test_requires_python.py index 90e2507..6ca20c1 100644 --- a/tests/usethis/_pyproject/test_requires_python.py +++ b/tests/usethis/_integrations/pyproject/test_requires_python.py @@ -5,14 +5,14 @@ import requests from packaging.specifiers import SpecifierSet -from usethis._pyproject.io import PyProjectTOMLNotFoundError -from usethis._pyproject.requires_python import ( +from usethis._integrations.pyproject.io import PyProjectTOMLNotFoundError +from usethis._integrations.pyproject.requires_python import ( MAX_MAJOR_PY3, MissingRequiresPythonError, get_requires_python, get_supported_major_python_versions, ) -from usethis._test import change_cwd +from usethis._utils._test import change_cwd class TestMaxMajorPy3: diff --git a/tests/usethis/_pytest/test_core.py b/tests/usethis/_integrations/pytest/test_core.py similarity index 94% rename from tests/usethis/_pytest/test_core.py rename to tests/usethis/_integrations/pytest/test_core.py index 27af335..ca5d309 100644 --- a/tests/usethis/_pytest/test_core.py +++ b/tests/usethis/_integrations/pytest/test_core.py @@ -2,8 +2,8 @@ import pytest -from usethis._pytest.core import add_pytest_dir, remove_pytest_dir -from usethis._test import change_cwd +from usethis._integrations.pytest.core import add_pytest_dir, remove_pytest_dir +from usethis._utils._test import change_cwd class TestAddPytestDir: diff --git a/tests/usethis/_ruff/test_rules.py b/tests/usethis/_integrations/ruff/test_rules.py similarity index 91% rename from tests/usethis/_ruff/test_rules.py rename to tests/usethis/_integrations/ruff/test_rules.py index e36ed6f..e4afb51 100644 --- a/tests/usethis/_ruff/test_rules.py +++ b/tests/usethis/_integrations/ruff/test_rules.py @@ -2,9 +2,13 @@ import pytest -from usethis._pyproject.io import PyProjectTOMLNotFoundError -from usethis._ruff.rules import deselect_ruff_rules, get_ruff_rules, select_ruff_rules -from usethis._test import change_cwd +from usethis._integrations.pyproject.io import PyProjectTOMLNotFoundError +from usethis._integrations.ruff.rules import ( + deselect_ruff_rules, + get_ruff_rules, + select_ruff_rules, +) +from usethis._utils._test import change_cwd class TestSelectRuffRules: diff --git a/tests/usethis/_uv/deps.py b/tests/usethis/_integrations/uv/deps.py similarity index 91% rename from tests/usethis/_uv/deps.py rename to tests/usethis/_integrations/uv/deps.py index ab0cf5f..7cb0e6b 100644 --- a/tests/usethis/_uv/deps.py +++ b/tests/usethis/_integrations/uv/deps.py @@ -1,7 +1,7 @@ from pathlib import Path -from usethis._test import change_cwd -from usethis._uv.deps import get_dev_deps +from usethis._integrations.uv.deps import get_dev_deps +from usethis._utils._test import change_cwd class TestGetDevDeps: diff --git a/tests/usethis/test_browse.py b/tests/usethis/_interface/test_browse.py similarity index 94% rename from tests/usethis/test_browse.py rename to tests/usethis/_interface/test_browse.py index 822c86f..04a3c2e 100644 --- a/tests/usethis/test_browse.py +++ b/tests/usethis/_interface/test_browse.py @@ -1,7 +1,7 @@ import pytest import typer -from usethis.browse import pypi +from usethis._interface.browse import pypi class TestPyPI: diff --git a/tests/usethis/_interface/test_ci.py b/tests/usethis/_interface/test_ci.py new file mode 100644 index 0000000..4475905 --- /dev/null +++ b/tests/usethis/_interface/test_ci.py @@ -0,0 +1,47 @@ +from pathlib import Path + +from usethis._interface.ci import _bitbucket +from usethis._utils._test import change_cwd, is_offline + + +class TestBitBucket: + class TestAdd: + class TestConfigFile: + def test_exists(self, uv_init_dir: Path): + # Act + with change_cwd(uv_init_dir): + _bitbucket(offline=is_offline()) + + # Assert + assert (uv_init_dir / "bitbucket-pipelines.yml").exists() + + def test_contents(self, uv_init_dir: Path): + # Act + with change_cwd(uv_init_dir): + _bitbucket(offline=is_offline()) + + # Assert + contents = (uv_init_dir / "bitbucket-pipelines.yml").read_text() + + assert ( + contents + == """\ +image: atlassian/default-image:3 + +definitions: + caches: + uv: ~/.cache/uv + scripts: + - script: &install-uv |- + curl -LsSf https://astral.sh/uv/install.sh | sh + source $HOME/.cargo/env + export UV_LINK_MODE=copy +pipelines: + default: + - step: + name: Placeholder - add your own steps! + script: + - *install-uv + - echo 'Hello, world!' +""" + ) diff --git a/tests/usethis/test_tool.py b/tests/usethis/_interface/test_tool.py similarity index 95% rename from tests/usethis/test_tool.py rename to tests/usethis/_interface/test_tool.py index ecb62e6..0a8a83a 100644 --- a/tests/usethis/test_tool.py +++ b/tests/usethis/_interface/test_tool.py @@ -3,18 +3,31 @@ import pytest -from usethis._pre_commit.core import _VALIDATEPYPROJECT_VERSION -from usethis._pre_commit.hooks import ( +from usethis._integrations.pre_commit.core import _VALIDATEPYPROJECT_VERSION +from usethis._integrations.pre_commit.hooks import ( _HOOK_ORDER, get_hook_names, ) -from usethis._test import change_cwd, is_offline +from usethis._integrations.uv.deps import add_dev_deps, get_dev_deps +from usethis._interface.tool import _deptry, _pre_commit, _pytest, _ruff from usethis._tool import ALL_TOOLS -from usethis._uv.deps import add_dev_deps, get_dev_deps -from usethis.tool import _deptry, _pre_commit, _ruff +from usethis._utils._test import change_cwd, is_offline -class TestToolPreCommit: +class TestAllHooksList: + def test_subset_hook_names(self): + for tool in ALL_TOOLS: + try: + hook_names = [ + hook.id for hook in tool.get_pre_commit_repo_config().hooks + ] + except NotImplementedError: + continue + for hook_name in hook_names: + assert hook_name in _HOOK_ORDER + + +class TestPreCommit: class TestAdd: def test_dependency_added(self, uv_init_dir: Path): # Act @@ -393,14 +406,14 @@ def test_config_file(self, uv_init_dir: Path): assert (uv_init_dir / "pyproject.toml").read_text() == "" -class TestAllHooksList: - def test_subset_hook_names(self): - for tool in ALL_TOOLS: - try: - hook_names = [ - hook.id for hook in tool.get_pre_commit_repo_config().hooks - ] - except NotImplementedError: - continue - for hook_name in hook_names: - assert hook_name in _HOOK_ORDER +class TestPytest: + def test_dep(self, uv_init_dir: Path): + with change_cwd(uv_init_dir): + _pytest(offline=is_offline()) + + assert { + "pytest", + "pytest-md", + "pytest-cov", + "coverage", + } <= set(get_dev_deps()) diff --git a/uv.lock b/uv.lock index cabcafb..eb6c539 100644 --- a/uv.lock +++ b/uv.lock @@ -190,6 +190,45 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e9/bd/cc3a402a6439c15c3d4294333e13042b915bbeab54edc457c723931fed3f/GitPython-3.1.43-py3-none-any.whl", hash = "sha256:eec7ec56b92aad751f9912a73404bc02ba212a23adb2c7098ee668417051a1ff", size = 207337 }, ] +[[package]] +name = "grimp" +version = "3.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/df/bd/4f919930f4b9c89a6d6905e4e8e4f11aa2489e385064501ff191c7b7d9cb/grimp-3.5.tar.gz", hash = "sha256:dc9560aed1d82222b361fe5f312a775b15a96b9237670f3a9fb20f44d30d5762", size = 833830 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5c/2d/3cdbde81fc35da435f71c1ac1756d54546340aeb73bd2435062f5d56fa96/grimp-3.5-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:e09db10a7395b3930ebe95eee2ac440c5ee24ce77b6171e807a8aacb4625cca2", size = 351992 }, + { url = "https://files.pythonhosted.org/packages/3b/1a/075518b888a9e0695f80f481563c62ed62cdc4a3bb5c3fc060392f63bee6/grimp-3.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:977c6b220671d7332657be13c51e4f6f38c76d911680f844806a5346142910fc", size = 343036 }, + { url = "https://files.pythonhosted.org/packages/7e/64/700b9a9434b3e419e8f2faba1d527cd04398b341e4c6f471fd61849de5ea/grimp-3.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4f4e2159c3c75b62f9ea59a539ac93f89b9ced38811b453d3b78be62c8395b01", size = 399805 }, + { url = "https://files.pythonhosted.org/packages/d9/da/391129fdca413bed18409d0594445b9c2b839b1265d8c207c82134bcfc7e/grimp-3.5-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8d7bb3f2178b3a8115eca5f6ea5f766a283b8a7ede84fbbdda2a40b7d28624cb", size = 405536 }, + { url = "https://files.pythonhosted.org/packages/95/63/f2c4d5796bde917f9ec37d8f1b555416a4f24af99899d4bb4131efa6d92a/grimp-3.5-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f4e023c883a83fa8ca1a613b1e8b39834545818971a8d94977bcd4b491537cde", size = 416903 }, + { url = "https://files.pythonhosted.org/packages/a5/4f/17e7c07872370b92560b189cc83714e358ba58a72fb4b4272b0977f32233/grimp-3.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce7440c8498fa5b47acfffce7fe42d6c63be94dbe2fff7f524522fa7e422e0eb", size = 437612 }, + { url = "https://files.pythonhosted.org/packages/ac/54/3319304f1f1050b8093314e875fcf73150323beb18cbf918c4ef6a8ef89b/grimp-3.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b0724f60d7cccf2c94616f0282ba8eec85a1956b59b8d22274409a60539fc462", size = 444189 }, + { url = "https://files.pythonhosted.org/packages/67/7a/fde60dfb1995e8b6a2f26ac280ca5ad3cdeec2d363172c12450850dc93ba/grimp-3.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a486e985fa4d4fb9dc6ebb094ed17a293809ff5cf6532bba26a5ae064d350539", size = 393776 }, + { url = "https://files.pythonhosted.org/packages/91/67/3cbb66ace2a4a253bfda3dbbcffc3b044e470d009a87cd75a7ed729d91f3/grimp-3.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8a98f06d58b0cb7b8bfe5846d8ab07adb36c313dd3c7298836ddd3df98a8344a", size = 573678 }, + { url = "https://files.pythonhosted.org/packages/8c/a0/deaeb03bbfac9e5503c270447724c10852679809cb26e57b3e4baaf60cf5/grimp-3.5-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:13924943d6e5a0f0150c8f2a05d87042f03510b633b198ac3dd5c4274d36f28c", size = 664438 }, + { url = "https://files.pythonhosted.org/packages/67/bf/6de7ec680daa963d215dc3bd71831c22e15e488ed7b835e65b36b8424aaf/grimp-3.5-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:8194ac4c54fac7641bfcef332aaec1af590e97b2aa8993e47a7c51ff84220f44", size = 589491 }, + { url = "https://files.pythonhosted.org/packages/73/a2/03ffdf03f2ab642bfe296eff94f51a6a8e3b04d4b5c7567a7b3c9261313c/grimp-3.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3f83b85aad278dfcaf2bf27b9cfa6dd6533dd96ecc510ba3bc0141344686857f", size = 560996 }, + { url = "https://files.pythonhosted.org/packages/13/52/fb9ad8e26710d7eb0afccf083087810d8cbd0f4eb3863f0641c8b251c046/grimp-3.5-cp312-none-win32.whl", hash = "sha256:f88307f0e50883ab73cc59164a5a9396e8e1c8b68b8e2edef68d478b91d81000", size = 222988 }, + { url = "https://files.pythonhosted.org/packages/2e/85/4058a766fc2b53b4b1318944c46bc9405fc7dea7ebb2eca377896f3fbfd5/grimp-3.5-cp312-none-win_amd64.whl", hash = "sha256:6fa422c150597f8e6ad51c4fe2b271747057abe638acca5eebb2162e536065ed", size = 236195 }, + { url = "https://files.pythonhosted.org/packages/31/02/33f4b4bc6d22b5ff7672ce5c67464f4dcee6e86cf3a072cdc9b1d46e5178/grimp-3.5-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:448dba63f938d0e13e6121559749816e3b2644202c912cc308e7608c6034737a", size = 351545 }, + { url = "https://files.pythonhosted.org/packages/78/e0/44bd64767763160ea0862ad756b88dfd375060b5636aaeb79c10861f09ae/grimp-3.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:17113aba41269d0ee91512c96eeb850c7c668440c6a8e0bfc94d17762184b293", size = 342780 }, + { url = "https://files.pythonhosted.org/packages/55/e6/b0fc52ab1ee04c80f1709eaa2e99468a8981d0a23dcbc7c2c6e781da22cc/grimp-3.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e6a55614945c319d1dc692c3e43f3a02b80c116a1298e593f5f887b97e6c983a", size = 399300 }, + { url = "https://files.pythonhosted.org/packages/dc/b9/aa6365859c96881d02f6ad6ab8aa38eaced5887f3cc431165ed9ee7b35ea/grimp-3.5-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:aba7ce7839b72efb4c6d06404d2b2a3026e28dd89816f4e546b3cd6626cbeeb1", size = 405288 }, + { url = "https://files.pythonhosted.org/packages/7d/f8/32446714ed0f23a1b8067f9f627c55f7c186d3477baa5c6e6312c95060ab/grimp-3.5-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eaedfba320a70d87b14acb25a685c8629586b943129c71ffd02b47d9531c11ce", size = 416565 }, + { url = "https://files.pythonhosted.org/packages/93/3c/185a0292111350823fdd7d61481157295d90260e248888ab274a00f84456/grimp-3.5-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:60a9afd3dd00ad1d301a07f97e26bc9ecdc3d2db39ab6ac46c315a7dea0a96cb", size = 437249 }, + { url = "https://files.pythonhosted.org/packages/1a/21/55ede2511dc111e9ca90d23e479e263e0845dc7e389515587f9575c5b139/grimp-3.5-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:11c66039c0475e5c9fc6a086264f11870181ae79f603caa5dffa1411ddad636b", size = 443560 }, + { url = "https://files.pythonhosted.org/packages/12/e1/79f6a4212d46ae6db6281c5b179990d2dd53c72eed7587592c0968f0d3f0/grimp-3.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bff39a0061790f074f86a7841cd8e6064aa7b2208cb1ee5c3f2e685dead2b66e", size = 393185 }, + { url = "https://files.pythonhosted.org/packages/46/62/1a7f8b54d73f3ef6595dd8bfa10686321c04b562fbb997e9d46f95fe7b96/grimp-3.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cf7f5367c4a87b8e9f08c09e7401d2d73f21cb65d6142445819f9df0d6ab3f6b", size = 573292 }, + { url = "https://files.pythonhosted.org/packages/24/1d/b90853a0b7eb7aa08073dafd896551d26a416e922a68eb1cab35319593c7/grimp-3.5-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:edee4b087f007dab8b65461caf6a1b67b2f9480cceb5f6aceea87008d8f283c4", size = 664226 }, + { url = "https://files.pythonhosted.org/packages/6b/7b/ce6cf6ba2da6305725692ea2a7a4080da60ac075d23353fc07cae7adb5b7/grimp-3.5-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:6af125013ad2a56c18f2f53a3fcabbfbe96c70374abecd6f14b82dc444726ebe", size = 589077 }, + { url = "https://files.pythonhosted.org/packages/ad/29/03156310a1bf278e8dd46e2e02311bad1d1551b1555d245e28008c318086/grimp-3.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:24aabae0183ca5fd5a710257ff37120b55d8e6d6d4cbb2c08481552832e5c901", size = 560463 }, + { url = "https://files.pythonhosted.org/packages/1e/29/300daf9b6a7f3f979a379cda69e04374912031fd85f3b6f0e03d9b637263/grimp-3.5-cp313-none-win32.whl", hash = "sha256:506091bfd600dd7ad427586998ef5e54a2098485148a1499bd9af5943d2fb0b7", size = 222673 }, + { url = "https://files.pythonhosted.org/packages/e5/8c/15834d919407c1ab11590367e03ac9d1c162d518a0f54f2970e315e0d623/grimp-3.5-cp313-none-win_amd64.whl", hash = "sha256:099388df82d922ddc589f362f1a523ab053c8dee5d29a6b622b2cddf481c6a2f", size = 236037 }, +] + [[package]] name = "identify" version = "2.6.1" @@ -208,6 +247,20 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442 }, ] +[[package]] +name = "import-linter" +version = "2.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "grimp" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5e/d3/546d27e9390061cbc692541612bbaa3f69a3ad23f592cfbfefe0517ff5b0/import_linter-2.1.tar.gz", hash = "sha256:393fadb2e91304c22c5ceab575213ed2b6a794abc7bd05ab345f2430930b2eae", size = 29160 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d8/38/137d5310c52c1b79d1588afa2ce5038cb3a10dbfd1a642962f3bc3ccbe61/import_linter-2.1-py3-none-any.whl", hash = "sha256:324d65035f0252a8e432f60256b0d0d32d8d5d6e4f8fd29716688b09d7a2217a", size = 41402 }, +] + [[package]] name = "iniconfig" version = "2.0.0" @@ -596,6 +649,7 @@ dev = [ { name = "coverage" }, { name = "deptry" }, { name = "gitpython" }, + { name = "import-linter" }, { name = "pre-commit" }, { name = "pytest" }, { name = "pytest-cov" }, @@ -621,6 +675,7 @@ dev = [ { name = "coverage", extras = ["toml"], specifier = ">=7.6.3" }, { name = "deptry", specifier = ">=0.20.0" }, { name = "gitpython", specifier = ">=3.1.43" }, + { name = "import-linter", specifier = ">=2.1" }, { name = "pre-commit", specifier = ">=4.0.1" }, { name = "pytest", specifier = ">=8.3.2" }, { name = "pytest-cov", specifier = ">=5.0.0" },