reyk-cli 0.0.1__tar.gz → 0.0.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,36 @@
1
+ # Byte-compiled
2
+ __pycache__/
3
+
4
+ # Distribution / packaging
5
+ build/
6
+ dist/
7
+
8
+ # Unit test / coverage reports
9
+ htmlcov/
10
+ .tox/
11
+ .nox/
12
+ .coverage
13
+ .coverage.*
14
+ .cache
15
+ nosetests.xml
16
+ coverage.xml
17
+ *.cover
18
+ *.py,cover
19
+ .hypothesis/
20
+ .pytest_cache/
21
+ coverage/
22
+ coverage.lcov
23
+
24
+ # Environments
25
+ .venv/
26
+
27
+ # PyPI configuration file
28
+ .pypirc
29
+
30
+ # Tests
31
+ tests/blackbox/locked_files_pending_deletion/
32
+ tests/blackbox/specific_libraries/test_libs
33
+ tests/blackbox/specific_libraries/vendor.lock
34
+
35
+ # Docs
36
+ .vercel
@@ -0,0 +1,8 @@
1
+ Metadata-Version: 2.5
2
+ Name: reyk-cli
3
+ Version: 0.0.2
4
+ Summary: Manage isolated environment dependencies.
5
+ License-Expression: MIT
6
+ Requires-Python: >=3.9
7
+ Requires-Dist: tomli>=2.4.0; python_version < '3.11'
8
+ Requires-Dist: typer>=0.20.0
@@ -1,17 +1,22 @@
1
1
  [project]
2
2
  name = "reyk-cli"
3
- version = "0.0.1"
3
+ dynamic = ["version"]
4
4
  description = "Manage isolated environment dependencies."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.9"
7
7
  dependencies = ["typer>=0.20.0", "tomli>=2.4.0; python_version < '3.11'"]
8
+ license = 'MIT'
9
+ license-files = ['LICENSE']
8
10
 
9
11
  [dependency-groups]
10
12
  dev = ["pytest>=8.4.2", "tomli-w>=1.2.0"]
11
13
 
12
14
  [build-system]
13
- requires = ["uv_build>=0.8.3,<0.9.0"]
14
- build-backend = "uv_build"
15
+ requires = ["hatchling"]
16
+ build-backend = "hatchling.build"
17
+
18
+ [tool.hatch.version]
19
+ path = "src/reyk_cli/version.py"
15
20
 
16
21
  [project.scripts]
17
22
  reyk-cli = "reyk_cli.cli:app"
@@ -35,6 +35,7 @@ def main(
35
35
  ctx.obj = UVBasedVendorizer(
36
36
  project_root=config.parent,
37
37
  vendor_groups=reyk_config.vendor_groups,
38
+ vendor_exclusions=reyk_config.vendor_exclusions,
38
39
  libraries_target_path=Path(reyk_config.libraries_path),
39
40
  )
40
41
 
@@ -20,6 +20,7 @@ DEFAULT_VENDOR_GROUPS = {DEFAULT_VENDOR_GROUP}
20
20
  class ReykConfiguration:
21
21
  libraries_path: str
22
22
  vendor_groups: set[str]
23
+ vendor_exclusions: set[str]
23
24
 
24
25
 
25
26
  def read_reyk_configuration(toml_path: Path) -> ReykConfiguration:
@@ -30,4 +31,5 @@ def read_reyk_configuration(toml_path: Path) -> ReykConfiguration:
30
31
  )
31
32
  configuration["libraries_path"] = configuration.pop("libraries-path", DEFAULT_LIBRARIES_TARGET_PATH)
32
33
  configuration["vendor_groups"] = set(configuration.pop("vendor-groups", DEFAULT_VENDOR_GROUPS))
34
+ configuration["vendor_exclusions"] = set(configuration.pop("vendor-exclusions", set()))
33
35
  return ReykConfiguration(**configuration)
@@ -10,9 +10,16 @@ LOCK_FILE_NAME = "vendor.lock"
10
10
 
11
11
 
12
12
  class UVBasedVendorizer:
13
- def __init__(self, project_root: Path, vendor_groups: set[str], libraries_target_path: Path) -> None:
13
+ def __init__(
14
+ self,
15
+ project_root: Path,
16
+ vendor_groups: set[str],
17
+ vendor_exclusions: set[str],
18
+ libraries_target_path: Path,
19
+ ) -> None:
14
20
  self._project_root = project_root
15
21
  self._vendor_groups = vendor_groups
22
+ self._vendor_exclusions = vendor_exclusions
16
23
  self._libraries_target_path = libraries_target_path
17
24
 
18
25
  def add_new_requirement_to_pyproject(self, vendor_group: str, command_args: Sequence[str]) -> None:
@@ -44,6 +51,7 @@ class UVBasedVendorizer:
44
51
  "uv",
45
52
  "export",
46
53
  *itertools.chain.from_iterable([("--only-group", group) for group in self._vendor_groups]),
54
+ *itertools.chain.from_iterable([("--no-emit-package", package) for package in self._vendor_exclusions]),
47
55
  "--no-header",
48
56
  "--quiet",
49
57
  "--no-emit-project",
@@ -0,0 +1 @@
1
+ VERSION = "0.0.2"
File without changes
@@ -0,0 +1,21 @@
1
+ from collections.abc import Iterable
2
+ from pathlib import Path
3
+ import os
4
+ import pytest
5
+ from typer.testing import CliRunner
6
+ from tests.example_project import ExampleProject
7
+
8
+
9
+ @pytest.fixture(scope="session")
10
+ def runner() -> CliRunner:
11
+ return CliRunner()
12
+
13
+
14
+ @pytest.fixture
15
+ def example_project(request: pytest.FixtureRequest, tmpdir: Path) -> Iterable[ExampleProject]:
16
+ example_project = ExampleProject(Path(tmpdir), getattr(request, "param", None))
17
+ example_project.write_pyproject_toml()
18
+ previous_cwd = Path.cwd()
19
+ os.chdir(tmpdir)
20
+ yield example_project
21
+ os.chdir(previous_cwd)
@@ -0,0 +1,67 @@
1
+ from pathlib import Path
2
+ from typing import Any, Optional
3
+
4
+ import tomli_w
5
+ from reyk_cli.configuration_reader import (
6
+ DEFAULT_LIBRARIES_TARGET_PATH,
7
+ DEFAULT_VENDOR_GROUPS,
8
+ ReykConfiguration,
9
+ )
10
+
11
+ PYPROJECT_TOML_NAME = "pyproject.toml"
12
+ DIST_INFO_SUBSTRING = "dist-info"
13
+ IGNORED_DIRECTORIES_IN_LIBS = {"bin"} # Directories which aren't packages
14
+
15
+ PYPROJECT_EXAMPLE: dict[str, Any] = {
16
+ "project": {
17
+ "name": "project-example",
18
+ "version": "0.0.1",
19
+ "description": "Example Pyproject",
20
+ "readme": "README.md",
21
+ "requires-python": ">=3.8",
22
+ "dependencies": [],
23
+ }
24
+ }
25
+
26
+
27
+ class ExampleProject:
28
+ def __init__(self, project_path: Path, configuration: Optional[ReykConfiguration]) -> None:
29
+ self._project_path = project_path
30
+ self._configuration = (
31
+ ReykConfiguration(DEFAULT_LIBRARIES_TARGET_PATH, DEFAULT_VENDOR_GROUPS, set())
32
+ if configuration is None
33
+ else configuration
34
+ )
35
+
36
+ def write_pyproject_toml(self) -> None:
37
+ pyproject = PYPROJECT_EXAMPLE.copy()
38
+ # Only add values if any are not the default:
39
+ if (
40
+ self._configuration.libraries_path != DEFAULT_LIBRARIES_TARGET_PATH
41
+ or self._configuration.vendor_groups != DEFAULT_VENDOR_GROUPS
42
+ or len(self._configuration.vendor_exclusions) > 0
43
+ ):
44
+ pyproject["tool"] = {
45
+ "reyk": {
46
+ "libraries-path": self._configuration.libraries_path,
47
+ "vendor-groups": list(self._configuration.vendor_groups),
48
+ "vendor-exclusions": list(self._configuration.vendor_exclusions),
49
+ },
50
+ }
51
+
52
+ with (self._project_path / PYPROJECT_TOML_NAME).open("wb") as fp:
53
+ tomli_w.dump(pyproject, fp)
54
+
55
+ def get_existing_libraries(self) -> set[str]:
56
+ return {
57
+ library_path.name
58
+ for library_path in (self._project_path / self._configuration.libraries_path).iterdir()
59
+ if (
60
+ library_path.is_dir()
61
+ and library_path.name not in IGNORED_DIRECTORIES_IN_LIBS
62
+ and DIST_INFO_SUBSTRING not in library_path.name
63
+ )
64
+ }
65
+
66
+ def has_libs_directory(self) -> bool:
67
+ return (self._project_path / self._configuration.libraries_path).exists()
@@ -0,0 +1,137 @@
1
+ import pytest
2
+ from reyk_cli.cli import app
3
+ from reyk_cli.configuration_reader import (
4
+ DEFAULT_LIBRARIES_TARGET_PATH,
5
+ DEFAULT_VENDOR_GROUP,
6
+ DEFAULT_VENDOR_GROUPS,
7
+ ReykConfiguration,
8
+ )
9
+ from typer.testing import CliRunner
10
+
11
+ from tests.example_project import ExampleProject
12
+
13
+
14
+ def test_add(runner: CliRunner, example_project: ExampleProject) -> None:
15
+ result = runner.invoke(app, ["add", "tomli"])
16
+ assert result.exit_code == 0
17
+ assert example_project.get_existing_libraries() == {"tomli"}
18
+
19
+
20
+ def test_remove_existing_package(runner: CliRunner, example_project: ExampleProject) -> None:
21
+ result = runner.invoke(app, ["add", "tomli"])
22
+ assert result.exit_code == 0
23
+
24
+ result = runner.invoke(app, ["remove", "tomli"])
25
+ assert result.exit_code == 0
26
+ assert example_project.get_existing_libraries() == set()
27
+
28
+
29
+ def test_remove_non_existing_package(runner: CliRunner, example_project: ExampleProject) -> None:
30
+ result = runner.invoke(app, ["add", "tomli"])
31
+ assert result.exit_code == 0
32
+
33
+ result = runner.invoke(app, ["remove", "pytest"])
34
+ assert result.exit_code != 0
35
+ assert example_project.get_existing_libraries() == {"tomli"}
36
+
37
+
38
+ def test_add_then_sync_multiple_times(runner: CliRunner, example_project: ExampleProject) -> None:
39
+ result = runner.invoke(app, ["add", "tomli"])
40
+ assert result.exit_code == 0
41
+
42
+ for _ in range(10):
43
+ result = runner.invoke(app, ["sync"])
44
+ assert result.exit_code == 0
45
+
46
+ assert example_project.get_existing_libraries() == {"tomli"}
47
+
48
+
49
+ def test_add_to_unrelated_group(runner: CliRunner, example_project: ExampleProject) -> None:
50
+ result = runner.invoke(app, ["add", "tomli"])
51
+ assert result.exit_code == 0
52
+ result = runner.invoke(app, ["add", "tomli-w", "--group", "unrelated-group"])
53
+ assert result.exit_code != 0, (
54
+ "Adding to a group with reyk-cli that isn't in 'vendor-groups' should result in an error"
55
+ )
56
+
57
+ assert example_project.get_existing_libraries() == {"tomli"}
58
+
59
+
60
+ @pytest.mark.parametrize(
61
+ "example_project",
62
+ [
63
+ ReykConfiguration(
64
+ libraries_path=DEFAULT_LIBRARIES_TARGET_PATH,
65
+ vendor_groups={DEFAULT_VENDOR_GROUP, "another-vendored-group"},
66
+ vendor_exclusions=set(),
67
+ ),
68
+ ],
69
+ indirect=True,
70
+ )
71
+ def test_add_to_new_vendor_groups(runner: CliRunner, example_project: ExampleProject) -> None:
72
+ result = runner.invoke(app, ["add", "tomli"])
73
+ assert result.exit_code != 0 # Because another-vendored-group does not exist
74
+ result = runner.invoke(app, ["add", "tomli-w", "--group", "another-vendored-group"])
75
+ assert result.exit_code == 0
76
+
77
+ assert example_project.get_existing_libraries() == {"tomli", "tomli_w"}
78
+
79
+
80
+ @pytest.mark.parametrize(
81
+ "example_project",
82
+ [
83
+ ReykConfiguration(
84
+ libraries_path=DEFAULT_LIBRARIES_TARGET_PATH,
85
+ vendor_groups={"different-vendored-group"},
86
+ vendor_exclusions=set(),
87
+ ),
88
+ ],
89
+ indirect=True,
90
+ )
91
+ def test_change_vendor_libs(runner: CliRunner, example_project: ExampleProject) -> None:
92
+ result = runner.invoke(app, ["add", "tomli", "--group", "different-vendored-group"])
93
+ assert result.exit_code == 0
94
+
95
+ assert example_project.get_existing_libraries() == {"tomli"}
96
+
97
+
98
+ def test_sync_no_vendor_groups(runner: CliRunner, example_project: ExampleProject) -> None:
99
+ result = runner.invoke(app, "sync")
100
+ assert result.exit_code != 0, "Vendor groups does not exist in pyproject toml but sync works."
101
+ assert not example_project.has_libs_directory() # sync did not work
102
+
103
+
104
+ @pytest.mark.parametrize(
105
+ "example_project",
106
+ [
107
+ ReykConfiguration(
108
+ libraries_path="different_libs",
109
+ vendor_groups=DEFAULT_VENDOR_GROUPS,
110
+ vendor_exclusions=set(),
111
+ ),
112
+ ],
113
+ indirect=True,
114
+ )
115
+ def test_change_vendor_target(runner: CliRunner, example_project: ExampleProject) -> None:
116
+ result = runner.invoke(app, ["add", "tomli"])
117
+ assert result.exit_code == 0
118
+
119
+ assert example_project.get_existing_libraries() == {"tomli"}
120
+
121
+
122
+ @pytest.mark.parametrize(
123
+ "example_project",
124
+ [
125
+ ReykConfiguration(
126
+ libraries_path=DEFAULT_LIBRARIES_TARGET_PATH,
127
+ vendor_groups=DEFAULT_VENDOR_GROUPS,
128
+ vendor_exclusions={"colorama"},
129
+ ),
130
+ ],
131
+ indirect=True,
132
+ )
133
+ def test_vendor_exclusions(runner: CliRunner, example_project: ExampleProject) -> None:
134
+ result = runner.invoke(app, ["add", "tqdm"])
135
+ assert result.exit_code == 0
136
+
137
+ assert example_project.get_existing_libraries() == {"tqdm"}
reyk_cli-0.0.1/PKG-INFO DELETED
@@ -1,9 +0,0 @@
1
- Metadata-Version: 2.3
2
- Name: reyk-cli
3
- Version: 0.0.1
4
- Summary: Manage isolated environment dependencies.
5
- Requires-Dist: typer>=0.20.0
6
- Requires-Dist: tomli>=2.4.0 ; python_full_version < '3.11'
7
- Requires-Python: >=3.9
8
- Description-Content-Type: text/markdown
9
-
File without changes