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
4 changes: 2 additions & 2 deletions src/usethis/_integrations/pre_commit/hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
from usethis._integrations.pre_commit.init import (
ensure_pre_commit_config_exists,
)
from usethis._integrations.pre_commit.language import get_system_language
from usethis._integrations.pre_commit.schema import (
HookDefinition,
Language,
LocalRepo,
MetaRepo,
)
Expand Down Expand Up @@ -187,7 +187,7 @@ def _get_placeholder_repo_config() -> LocalRepo:
id=_PLACEHOLDER_ID,
name="Placeholder - add your own hooks!",
entry="""uv run --isolated --frozen --offline python -c "print('hello world!')\"""",
language=Language("system"),
language=get_system_language(),
)
],
)
Expand Down
19 changes: 19 additions & 0 deletions src/usethis/_integrations/pre_commit/language.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from packaging.version import Version

from usethis._integrations.pre_commit.schema import Language
from usethis._integrations.pre_commit.version import get_minimum_pre_commit_version


def get_system_language() -> Language:
"""Get the appropriate 'system' language keyword based on pre-commit version.

Returns 'unsupported' for pre-commit >= 4.4.0, otherwise 'system'.

In the future, there may be a deprecation of the 'system' language in pre-commit,
at which point falling back to 'system' may no longer be appropriate and this logic
will need to be revisited.
"""
min_version = get_minimum_pre_commit_version()
if min_version is not None and Version(min_version) >= Version("4.4.0"):
return Language("unsupported")
return Language("system")
7 changes: 4 additions & 3 deletions src/usethis/_tool/impl/deptry.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
from usethis._integrations.backend.dispatch import get_backend
from usethis._integrations.backend.uv.used import is_uv_used
from usethis._integrations.file.pyproject_toml.io_ import PyprojectTOMLManager
from usethis._integrations.pre_commit.schema import HookDefinition, Language, LocalRepo
from usethis._integrations.pre_commit.language import get_system_language
from usethis._integrations.pre_commit.schema import HookDefinition, LocalRepo
from usethis._integrations.project.layout import get_source_dir_str
from usethis._tool.base import Tool
from usethis._tool.config import (
Expand Down Expand Up @@ -102,7 +103,7 @@ def get_pre_commit_config(self) -> PreCommitConfig:
id="deptry",
name="deptry",
entry=f"uv run --frozen --offline deptry {_dir}",
language=Language("system"),
language=get_system_language(),
always_run=True,
pass_filenames=False,
)
Expand All @@ -120,7 +121,7 @@ def get_pre_commit_config(self) -> PreCommitConfig:
id="deptry",
name="deptry",
entry=f"deptry {_dir}",
language=Language("system"),
language=get_system_language(),
always_run=True,
pass_filenames=False,
)
Expand Down
7 changes: 4 additions & 3 deletions src/usethis/_tool/impl/import_linter.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
from usethis._integrations.file.ini.io_ import INIFileManager
from usethis._integrations.file.pyproject_toml.io_ import PyprojectTOMLManager
from usethis._integrations.file.setup_cfg.io_ import SetupCFGManager
from usethis._integrations.pre_commit.schema import HookDefinition, Language, LocalRepo
from usethis._integrations.pre_commit.language import get_system_language
from usethis._integrations.pre_commit.schema import HookDefinition, LocalRepo
from usethis._integrations.project.errors import ImportGraphBuildFailedError
from usethis._integrations.project.imports import (
LayeredArchitecture,
Expand Down Expand Up @@ -342,7 +343,7 @@ def get_pre_commit_config(self) -> PreCommitConfig:
name="import-linter",
pass_filenames=False,
entry="uv run --frozen --offline lint-imports",
language=Language("system"),
language=get_system_language(),
require_serial=True,
always_run=True,
)
Expand All @@ -361,7 +362,7 @@ def get_pre_commit_config(self) -> PreCommitConfig:
name="import-linter",
pass_filenames=False,
entry="lint-imports",
language=Language("system"),
language=get_system_language(),
)
],
),
Expand Down
5 changes: 3 additions & 2 deletions src/usethis/_tool/impl/requirements_txt.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
from usethis._config import usethis_config
from usethis._console import how_print
from usethis._integrations.backend.dispatch import get_backend
from usethis._integrations.pre_commit.schema import HookDefinition, Language, LocalRepo
from usethis._integrations.pre_commit.language import get_system_language
from usethis._integrations.pre_commit.schema import HookDefinition, LocalRepo
from usethis._tool.base import Tool
from usethis._tool.pre_commit import PreCommitConfig
from usethis._types.backend import BackendEnum
Expand Down Expand Up @@ -73,7 +74,7 @@ def get_pre_commit_config(self) -> PreCommitConfig:
files="^uv\\.lock$",
pass_filenames=False,
entry="uv export --frozen --offline --quiet -o=requirements.txt",
language=Language("system"),
language=get_system_language(),
require_serial=True,
)
],
Expand Down
107 changes: 107 additions & 0 deletions tests/usethis/_integrations/pre_commit/test_language.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
from pathlib import Path

from usethis._config_file import files_manager
from usethis._integrations.pre_commit.language import get_system_language
from usethis._integrations.pre_commit.schema import Language
from usethis._test import change_cwd


class TestGetSystemLanguage:
def test_returns_unsupported_when_minimum_version_is_4_4_0(self, tmp_path: Path):
# Arrange
(tmp_path / ".pre-commit-config.yaml").write_text("""\
minimum_pre_commit_version: '4.4.0'
repos:
- repo: https://github.com/abravalheri/validate-pyproject
rev: v0.23
hooks:
- id: validate-pyproject
""")

# Act
with change_cwd(tmp_path), files_manager():
result = get_system_language()

# Assert
assert result == Language("unsupported")

def test_returns_unsupported_when_minimum_version_is_above_4_4_0(
self, tmp_path: Path
):
# Arrange
(tmp_path / ".pre-commit-config.yaml").write_text("""\
minimum_pre_commit_version: '4.5.0'
repos:
- repo: https://github.com/abravalheri/validate-pyproject
rev: v0.23
hooks:
- id: validate-pyproject
""")

# Act
with change_cwd(tmp_path), files_manager():
result = get_system_language()

# Assert
assert result == Language("unsupported")

def test_returns_system_when_minimum_version_is_below_4_4_0(self, tmp_path: Path):
# Arrange
(tmp_path / ".pre-commit-config.yaml").write_text("""\
minimum_pre_commit_version: '4.3.0'
repos:
- repo: https://github.com/abravalheri/validate-pyproject
rev: v0.23
hooks:
- id: validate-pyproject
""")

# Act
with change_cwd(tmp_path), files_manager():
result = get_system_language()

# Assert
assert result == Language("system")

def test_returns_system_when_config_doesnt_exist(self, tmp_path: Path):
# Act
with change_cwd(tmp_path), files_manager():
result = get_system_language()

# Assert
assert result == Language("system")

def test_returns_system_when_minimum_version_not_declared(self, tmp_path: Path):
# Arrange
(tmp_path / ".pre-commit-config.yaml").write_text("""\
repos:
- repo: https://github.com/abravalheri/validate-pyproject
rev: v0.23
hooks:
- id: validate-pyproject
""")

# Act
with change_cwd(tmp_path), files_manager():
result = get_system_language()

# Assert
assert result == Language("system")

def test_returns_system_when_minimum_version_is_3_x(self, tmp_path: Path):
# Arrange
(tmp_path / ".pre-commit-config.yaml").write_text("""\
minimum_pre_commit_version: '3.7.1'
repos:
- repo: https://github.com/abravalheri/validate-pyproject
rev: v0.23
hooks:
- id: validate-pyproject
""")

# Act
with change_cwd(tmp_path), files_manager():
result = get_system_language()

# Assert
assert result == Language("system")
23 changes: 14 additions & 9 deletions tests/usethis/_integrations/pre_commit/test_yaml.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,15 +136,20 @@ def test_extra_config(self, tmp_path: Path):


class TestPreCommitFancyDump:
def test_placeholder(self):
_pre_commit_fancy_dump(
config=JsonSchemaForPreCommitConfigYaml(
repos=[
_get_placeholder_repo_config(),
]
),
reference={},
)
def test_placeholder(self, tmp_path: Path):
# Arrange - create a minimal pre-commit config for get_system_language()
(tmp_path / ".pre-commit-config.yaml").write_text("repos: []\n")

# Act
with change_cwd(tmp_path), files_manager():
_pre_commit_fancy_dump(
config=JsonSchemaForPreCommitConfigYaml(
repos=[
_get_placeholder_repo_config(),
]
),
reference={},
)

def test_invalid(self):
with pytest.raises(TypeError):
Expand Down
100 changes: 100 additions & 0 deletions tests/usethis/_tool/impl/test_deptry.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from usethis._config_file import files_manager
from usethis._integrations.file.pyproject_toml.io_ import PyprojectTOMLManager
from usethis._integrations.pre_commit.schema import Language
from usethis._test import change_cwd
from usethis._tool.config import ConfigEntry, ConfigItem
from usethis._tool.impl.deptry import DeptryTool
Expand Down Expand Up @@ -268,3 +269,102 @@ def test_pyproject_toml_exists(self, tmp_path: Path):

# Assert
assert (tmp_path / "pyproject.toml").exists()

class TestGetPreCommitConfig:
def test_uses_system_language_when_no_minimum_version(self, tmp_path: Path):
# Arrange
(tmp_path / "pyproject.toml").write_text("""\
[project]
name = "test-project"
""")
(tmp_path / "src").mkdir()
(tmp_path / "src" / "test_project").mkdir()
(tmp_path / "src" / "test_project" / "__init__.py").touch()

# Act
with change_cwd(tmp_path), files_manager():
result = DeptryTool().get_pre_commit_config()

# Assert
assert result.repo_configs is not None
assert result.repo_configs[0].repo.hooks is not None
assert result.repo_configs[0].repo.hooks[0].language == Language("system")

def test_uses_system_language_when_minimum_version_below_4_4_0(
self, tmp_path: Path
):
# Arrange
(tmp_path / "pyproject.toml").write_text("""\
[project]
name = "test-project"
""")
(tmp_path / ".pre-commit-config.yaml").write_text("""\
minimum_pre_commit_version: '4.3.0'
repos: []
""")
(tmp_path / "src").mkdir()
(tmp_path / "src" / "test_project").mkdir()
(tmp_path / "src" / "test_project" / "__init__.py").touch()

# Act
with change_cwd(tmp_path), files_manager():
result = DeptryTool().get_pre_commit_config()

# Assert
assert result.repo_configs is not None
assert result.repo_configs[0].repo.hooks is not None
assert result.repo_configs[0].repo.hooks[0].language == Language("system")

def test_uses_unsupported_language_when_minimum_version_is_4_4_0(
self, tmp_path: Path
):
# Arrange
(tmp_path / "pyproject.toml").write_text("""\
[project]
name = "test-project"
""")
(tmp_path / ".pre-commit-config.yaml").write_text("""\
minimum_pre_commit_version: '4.4.0'
repos: []
""")
(tmp_path / "src").mkdir()
(tmp_path / "src" / "test_project").mkdir()
(tmp_path / "src" / "test_project" / "__init__.py").touch()

# Act
with change_cwd(tmp_path), files_manager():
result = DeptryTool().get_pre_commit_config()

# Assert
assert result.repo_configs is not None
assert result.repo_configs[0].repo.hooks is not None
assert result.repo_configs[0].repo.hooks[0].language == Language(
"unsupported"
)

def test_uses_unsupported_language_when_minimum_version_above_4_4_0(
self, tmp_path: Path
):
# Arrange
(tmp_path / "pyproject.toml").write_text("""\
[project]
name = "test-project"
""")
(tmp_path / ".pre-commit-config.yaml").write_text("""\
minimum_pre_commit_version: '4.5.0'
repos: []
""")
(tmp_path / "src").mkdir()
(tmp_path / "src" / "test_project").mkdir()
(tmp_path / "src" / "test_project" / "__init__.py").touch()

# Act
with change_cwd(tmp_path), files_manager():
result = DeptryTool().get_pre_commit_config()

# Assert
assert result.repo_configs is not None
assert result.repo_configs[0].repo.hooks is not None
assert result.repo_configs[0].repo.hooks[0].language == Language(
"unsupported"
)