snk-cli 0.5.0__tar.gz → 0.5.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.
- {snk_cli-0.5.0 → snk_cli-0.5.2}/PKG-INFO +1 -1
- {snk_cli-0.5.0 → snk_cli-0.5.2}/src/snk_cli/__about__.py +1 -1
- {snk_cli-0.5.0 → snk_cli-0.5.2}/src/snk_cli/config/config.py +11 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/src/snk_cli/dynamic_typer.py +5 -2
- snk_cli-0.5.2/tests/test_SnkConfig.py +125 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/tests/test_cli/test_validate.py +6 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/.github/workflows/publish.yml +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/.github/workflows/tests.yml +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/.gitignore +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/LICENSE.txt +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/README.md +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/docs/index.md +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/docs/reference/cli.md +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/docs/reference/config.md +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/docs/reference/dynamic_typer.md +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/docs/reference/options.md +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/docs/reference/subcommands.md +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/docs/reference/testing.md +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/docs/reference/utils.md +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/docs/reference/validate.md +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/docs/reference/workflow.md +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/mkdocs.yml +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/pyproject.toml +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/src/snk_cli/__init__.py +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/src/snk_cli/cli.py +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/src/snk_cli/conda.py +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/src/snk_cli/config/__init__.py +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/src/snk_cli/config/utils.py +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/src/snk_cli/options/__init__.py +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/src/snk_cli/options/option.py +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/src/snk_cli/options/utils.py +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/src/snk_cli/subcommands/__init__.py +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/src/snk_cli/subcommands/config.py +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/src/snk_cli/subcommands/env.py +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/src/snk_cli/subcommands/profile.py +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/src/snk_cli/subcommands/run.py +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/src/snk_cli/subcommands/script.py +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/src/snk_cli/testing.py +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/src/snk_cli/utils.py +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/src/snk_cli/validate.py +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/src/snk_cli/workflow.py +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/tests/__init__.py +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/tests/conftest.py +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/tests/data/artic_v4.1.bed +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/tests/data/config.yaml +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/tests/data/cov.fasta +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/tests/data/print_config/Snakefile +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/tests/data/print_config/cli.py +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/tests/data/print_config/config.yaml +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/tests/data/print_config/snk.yaml +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/tests/data/workflow/cli.py +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/tests/data/workflow/config.yaml +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/tests/data/workflow/resources/data.txt +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/tests/data/workflow/snk.yaml +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/tests/data/workflow/things/__about__.py +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/tests/data/workflow/workflow/Snakefile +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/tests/data/workflow/workflow/envs/wget.yml +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/tests/data/workflow/workflow/profiles/base/config.yaml +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/tests/data/workflow/workflow/profiles/slurm/config.yaml +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/tests/data/workflow/workflow/scripts/hello.py +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/tests/test_cli/__init__.py +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/tests/test_cli/test_dynamic_options.py +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/tests/test_cli/test_profile.py +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/tests/test_cli/test_run.py +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/tests/test_cli/test_snk_config.py +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/tests/test_cli/test_subcommands.py +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/tests/test_cli/test_workflow_cli.py +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/tests/test_conda_env.py +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/tests/test_dynamic_typer.py +0 -0
- {snk_cli-0.5.0 → snk_cli-0.5.2}/tests/utils.py +0 -0
|
@@ -205,6 +205,17 @@ class SnkConfig:
|
|
|
205
205
|
>>> snk_config.to_yaml(Path("snk.yaml"))
|
|
206
206
|
"""
|
|
207
207
|
config_dict = {k: v for k, v in vars(self).items() if not k.startswith("_")}
|
|
208
|
+
def convert_paths(data):
|
|
209
|
+
if isinstance(data, dict):
|
|
210
|
+
return {key: convert_paths(value) for key, value in data.items()}
|
|
211
|
+
elif isinstance(data, list):
|
|
212
|
+
return [convert_paths(item) for item in data]
|
|
213
|
+
elif isinstance(data, Path):
|
|
214
|
+
return str(data)
|
|
215
|
+
return data
|
|
216
|
+
|
|
217
|
+
config_dict = convert_paths(config_dict)
|
|
218
|
+
|
|
208
219
|
with open(path, "w") as f:
|
|
209
220
|
yaml.dump(config_dict, f)
|
|
210
221
|
|
|
@@ -152,9 +152,12 @@ class DynamicTyper:
|
|
|
152
152
|
if option.type is Enum or option.choices:
|
|
153
153
|
if not option.choices:
|
|
154
154
|
raise ValueError(f"Enum type {option.name} requires choices to be defined.")
|
|
155
|
-
annotation_type = Enum('
|
|
155
|
+
annotation_type = Enum(f'{option.name}', {str(e): str(e) for e in option.choices})
|
|
156
156
|
if default:
|
|
157
|
-
|
|
157
|
+
try:
|
|
158
|
+
default = annotation_type(default)
|
|
159
|
+
except ValueError:
|
|
160
|
+
raise ValueError(f"Default value {default} for option {option.name} is not a valid choice.")
|
|
158
161
|
return Parameter(
|
|
159
162
|
option.name,
|
|
160
163
|
kind=Parameter.POSITIONAL_OR_KEYWORD,
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from snk_cli.config.config import SnkConfig
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def test_snk_config_creation():
|
|
6
|
+
snk_config = SnkConfig()
|
|
7
|
+
assert snk_config.tagline == "A Snakemake workflow CLI generated with Snk"
|
|
8
|
+
assert snk_config.font == "small"
|
|
9
|
+
assert snk_config.resources == []
|
|
10
|
+
assert snk_config.cli == {}
|
|
11
|
+
assert snk_config.symlink_resources is False
|
|
12
|
+
assert snk_config.version is None
|
|
13
|
+
assert snk_config.skip_missing is False
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def test_validate_resources_with_existing_files(tmp_path):
|
|
17
|
+
resources = [tmp_path / "file1", tmp_path / "file2"]
|
|
18
|
+
for resource in resources:
|
|
19
|
+
resource.touch()
|
|
20
|
+
snk_config = SnkConfig()
|
|
21
|
+
# Should not raise an exception
|
|
22
|
+
snk_config.validate_resources(resources)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def test_validate_resources_with_missing_files(tmp_path):
|
|
26
|
+
resources = [tmp_path / "file1", tmp_path / "missing_file"]
|
|
27
|
+
resources[0].touch()
|
|
28
|
+
snk_config = SnkConfig()
|
|
29
|
+
with pytest.raises(FileNotFoundError):
|
|
30
|
+
snk_config.validate_resources(resources)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def test_add_resources(tmp_path):
|
|
34
|
+
resources = [tmp_path / "file1", tmp_path / "file2"]
|
|
35
|
+
for resource in resources:
|
|
36
|
+
resource.touch()
|
|
37
|
+
snk_config = SnkConfig()
|
|
38
|
+
snk_config.add_resources(resources)
|
|
39
|
+
assert len(snk_config.resources) == 2
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def test_from_path_with_existing_file(tmp_path):
|
|
43
|
+
config_file = tmp_path / "snk.yaml"
|
|
44
|
+
config_file.touch()
|
|
45
|
+
config_file.write_text("logo: test_logo")
|
|
46
|
+
snk_config = SnkConfig.from_path(config_file)
|
|
47
|
+
assert snk_config._snk_config_path == config_file
|
|
48
|
+
|
|
49
|
+
def test_missing_file(tmp_path):
|
|
50
|
+
config_file = tmp_path / "snk.yaml"
|
|
51
|
+
with pytest.raises(FileNotFoundError):
|
|
52
|
+
SnkConfig.from_path(config_file)
|
|
53
|
+
|
|
54
|
+
def test_empty_file(tmp_path):
|
|
55
|
+
config_file = tmp_path / "snk.yaml"
|
|
56
|
+
config_file.touch()
|
|
57
|
+
with pytest.raises(ValueError):
|
|
58
|
+
SnkConfig.from_path(config_file)
|
|
59
|
+
|
|
60
|
+
def test_invalid_yaml(tmp_path):
|
|
61
|
+
config_file = tmp_path / "snk.yaml"
|
|
62
|
+
config_file.touch()
|
|
63
|
+
config_file.write_text("logo: test_logo\ninvalid_yaml")
|
|
64
|
+
with pytest.raises(Exception):
|
|
65
|
+
SnkConfig.from_path(config_file)
|
|
66
|
+
|
|
67
|
+
def test_from_dir_with_existing_file(tmp_path):
|
|
68
|
+
config_file = tmp_path / ".snk"
|
|
69
|
+
config_file.touch()
|
|
70
|
+
config_file.write_text("logo: test_logo")
|
|
71
|
+
# catch warning
|
|
72
|
+
with pytest.warns(DeprecationWarning):
|
|
73
|
+
snk_config = SnkConfig.from_workflow_dir(tmp_path)
|
|
74
|
+
assert snk_config._snk_config_path == config_file
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def test_from_path_with_missing_file(tmp_path):
|
|
78
|
+
config_file = tmp_path / "missing_file.yaml"
|
|
79
|
+
# assert it raises FileNotFoundError
|
|
80
|
+
with pytest.raises(FileNotFoundError):
|
|
81
|
+
SnkConfig.from_path(config_file)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def test_to_yaml(tmp_path):
|
|
85
|
+
snk_config = SnkConfig(art="test_art", logo="test_logo")
|
|
86
|
+
yaml_file = tmp_path / "snk.yaml"
|
|
87
|
+
snk_config.to_yaml(yaml_file)
|
|
88
|
+
assert yaml_file.exists()
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def test_save(tmp_path):
|
|
92
|
+
config_file = tmp_path / "snk.yaml"
|
|
93
|
+
snk_config = SnkConfig(_snk_config_path=config_file)
|
|
94
|
+
snk_config.art = "new_art"
|
|
95
|
+
snk_config.save()
|
|
96
|
+
saved_snk_config = SnkConfig.from_path(config_file)
|
|
97
|
+
assert saved_snk_config.art == "new_art"
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def test_version_from_about_file(tmp_path):
|
|
101
|
+
config_file = tmp_path / "snk.yaml"
|
|
102
|
+
about_file = tmp_path / "__about__.py"
|
|
103
|
+
about_file.touch()
|
|
104
|
+
about_file.write_text("__version__ = '0.0.1'")
|
|
105
|
+
config_file.write_text("version: __about__.py")
|
|
106
|
+
snk_config = SnkConfig.from_path(config_file)
|
|
107
|
+
assert snk_config.version == "0.0.1"
|
|
108
|
+
|
|
109
|
+
def test_version_from_about_file_with_missing_file(tmp_path):
|
|
110
|
+
config_file = tmp_path / "snk.yaml"
|
|
111
|
+
about_file = tmp_path / "__about__.py"
|
|
112
|
+
config_file.write_text("version: __about__.py")
|
|
113
|
+
with pytest.raises(FileNotFoundError):
|
|
114
|
+
SnkConfig.from_path(config_file)
|
|
115
|
+
|
|
116
|
+
def test_paths_are_written_as_strings(tmp_path):
|
|
117
|
+
config_file = tmp_path / "snk.yaml"
|
|
118
|
+
snk_config = SnkConfig(snakefile=tmp_path / "snakefile", resources=[tmp_path / "file1", tmp_path / "file2"])
|
|
119
|
+
snk_config.to_yaml(config_file)
|
|
120
|
+
with open(config_file) as f:
|
|
121
|
+
config = f.read()
|
|
122
|
+
print(config)
|
|
123
|
+
assert f"snakefile: {tmp_path / 'snakefile'}" in config
|
|
124
|
+
assert f"- {tmp_path / 'file1'}" in config
|
|
125
|
+
assert f"- {tmp_path / 'file2'}" in config
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|