snakemake-interface-software-deployment-plugins 0.2.3__tar.gz → 0.3.0__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.
- {snakemake_interface_software_deployment_plugins-0.2.3 → snakemake_interface_software_deployment_plugins-0.3.0}/PKG-INFO +1 -1
- {snakemake_interface_software_deployment_plugins-0.2.3 → snakemake_interface_software_deployment_plugins-0.3.0}/pyproject.toml +1 -1
- {snakemake_interface_software_deployment_plugins-0.2.3 → snakemake_interface_software_deployment_plugins-0.3.0}/snakemake_interface_software_deployment_plugins/__init__.py +75 -26
- {snakemake_interface_software_deployment_plugins-0.2.3 → snakemake_interface_software_deployment_plugins-0.3.0}/snakemake_interface_software_deployment_plugins/registry/__init__.py +7 -0
- {snakemake_interface_software_deployment_plugins-0.2.3 → snakemake_interface_software_deployment_plugins-0.3.0}/snakemake_interface_software_deployment_plugins/registry/plugin.py +2 -0
- snakemake_interface_software_deployment_plugins-0.3.0/snakemake_interface_software_deployment_plugins/settings.py +46 -0
- {snakemake_interface_software_deployment_plugins-0.2.3 → snakemake_interface_software_deployment_plugins-0.3.0}/snakemake_interface_software_deployment_plugins/tests.py +2 -2
- snakemake_interface_software_deployment_plugins-0.2.3/snakemake_interface_software_deployment_plugins/settings.py +0 -17
- {snakemake_interface_software_deployment_plugins-0.2.3 → snakemake_interface_software_deployment_plugins-0.3.0}/LICENSE +0 -0
- {snakemake_interface_software_deployment_plugins-0.2.3 → snakemake_interface_software_deployment_plugins-0.3.0}/README.md +0 -0
- {snakemake_interface_software_deployment_plugins-0.2.3 → snakemake_interface_software_deployment_plugins-0.3.0}/snakemake_interface_software_deployment_plugins/_common.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: snakemake-interface-software-deployment-plugins
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: This package provides a stable interface for interactions between Snakemake and its software deployment plugins.
|
|
5
5
|
License: MIT
|
|
6
6
|
Author: Johannes Köster
|
|
@@ -5,7 +5,7 @@ license = "MIT"
|
|
|
5
5
|
name = "snakemake-interface-software-deployment-plugins"
|
|
6
6
|
packages = [{include = "snakemake_interface_software_deployment_plugins"}]
|
|
7
7
|
readme = "README.md"
|
|
8
|
-
version = "0.
|
|
8
|
+
version = "0.3.0"
|
|
9
9
|
|
|
10
10
|
[tool.poetry.dependencies]
|
|
11
11
|
argparse-dataclass = "^2.0.0"
|
|
@@ -5,11 +5,10 @@ __license__ = "MIT"
|
|
|
5
5
|
|
|
6
6
|
from abc import ABC, abstractmethod
|
|
7
7
|
from copy import copy
|
|
8
|
-
from dataclasses import dataclass, field
|
|
8
|
+
from dataclasses import dataclass, field
|
|
9
9
|
import hashlib
|
|
10
10
|
from pathlib import Path
|
|
11
|
-
import
|
|
12
|
-
from typing import Any, ClassVar, Dict, Optional, Tuple, Type
|
|
11
|
+
from typing import Any, ClassVar, Dict, Iterable, Optional, Self, Tuple, Type
|
|
13
12
|
import subprocess as sp
|
|
14
13
|
|
|
15
14
|
from snakemake_interface_software_deployment_plugins.settings import (
|
|
@@ -17,28 +16,84 @@ from snakemake_interface_software_deployment_plugins.settings import (
|
|
|
17
16
|
)
|
|
18
17
|
|
|
19
18
|
|
|
20
|
-
_MANAGED_FIELDS = {
|
|
21
|
-
"settings",
|
|
22
|
-
"_managed_hash_store",
|
|
23
|
-
"_managed_deployment_hash_store",
|
|
24
|
-
"_obj_hash",
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
@dataclass
|
|
29
19
|
class EnvSpecBase(ABC):
|
|
30
|
-
|
|
31
|
-
|
|
20
|
+
def __init__(self):
|
|
21
|
+
self.within: Optional["EnvSpecBase"] = None
|
|
22
|
+
self.fallback: Optional["EnvSpecBase"] = None
|
|
23
|
+
self.kind: str = self.__class__.__module__.common_settings.provides
|
|
24
|
+
self._obj_hash: Optional[int] = None
|
|
32
25
|
|
|
33
26
|
@classmethod
|
|
34
27
|
def env_cls(cls):
|
|
35
|
-
return
|
|
28
|
+
return cls.__module__.EnvBase
|
|
29
|
+
|
|
30
|
+
@abstractmethod
|
|
31
|
+
def identity_attributes(self) -> Iterable[str]:
|
|
32
|
+
"""Yield the attributes of the subclass that uniquely identify the
|
|
33
|
+
environment spec. These are used for hashing and equality comparison.
|
|
34
|
+
"""
|
|
35
|
+
...
|
|
36
|
+
|
|
37
|
+
@abstractmethod
|
|
38
|
+
def source_path_attributes(self) -> Iterable[str]:
|
|
39
|
+
"""Return iterable of attributes of the subclass that represent paths that are
|
|
40
|
+
supposed to be interpreted as being relative to the defining rule.
|
|
41
|
+
|
|
42
|
+
For example, this would be attributes pointing to conda environment files.
|
|
43
|
+
"""
|
|
44
|
+
...
|
|
45
|
+
|
|
46
|
+
def has_source_paths(self) -> bool:
|
|
47
|
+
if any(self.source_path_attributes()):
|
|
48
|
+
return True
|
|
49
|
+
if self.within is not None and self.within.has_source_paths():
|
|
50
|
+
return True
|
|
51
|
+
if self.fallback is not None and self.fallback.has_source_paths():
|
|
52
|
+
return True
|
|
53
|
+
return False
|
|
54
|
+
|
|
55
|
+
def modify_source_paths(self, modify_func) -> Self:
|
|
56
|
+
if self.has_source_paths():
|
|
57
|
+
self_or_copied = copy(self)
|
|
58
|
+
else:
|
|
59
|
+
return self
|
|
60
|
+
for attr in self_or_copied.source_path_attributes():
|
|
61
|
+
setattr(self_or_copied, attr, modify_func(getattr(self_or_copied, attr)))
|
|
62
|
+
|
|
63
|
+
if self_or_copied.within is not None:
|
|
64
|
+
self_or_copied.within = self_or_copied.within.modify_source_paths(
|
|
65
|
+
modify_func
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
if self_or_copied.fallback is not None:
|
|
69
|
+
self_or_copied.fallback = self_or_copied.fallback.modify_source_paths(
|
|
70
|
+
modify_func
|
|
71
|
+
)
|
|
72
|
+
return self_or_copied
|
|
36
73
|
|
|
37
74
|
def __or__(self, other: "EnvSpecBase") -> "EnvSpecBase":
|
|
38
75
|
copied = copy(self)
|
|
39
76
|
copied.fallback = other
|
|
77
|
+
copied._obj_hash = None
|
|
40
78
|
return copied
|
|
41
79
|
|
|
80
|
+
def managed_identity_attributes(self) -> Iterable[str]:
|
|
81
|
+
yield from self.identity_attributes()
|
|
82
|
+
yield "kind"
|
|
83
|
+
yield "within"
|
|
84
|
+
yield "fallback"
|
|
85
|
+
|
|
86
|
+
def __hash__(self) -> int:
|
|
87
|
+
return hash(
|
|
88
|
+
tuple(getattr(self, attr) for attr in self.managed_identity_attributes())
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
def __eq__(self, other) -> bool:
|
|
92
|
+
return self.__class__ == other.__class__ and all(
|
|
93
|
+
getattr(self, attr) == getattr(other, attr)
|
|
94
|
+
for attr in self.managed_identity_attributes()
|
|
95
|
+
)
|
|
96
|
+
|
|
42
97
|
|
|
43
98
|
@dataclass
|
|
44
99
|
class EnvBase:
|
|
@@ -119,20 +174,14 @@ class EnvBase:
|
|
|
119
174
|
def __hash__(self) -> int:
|
|
120
175
|
# take the hash of all fields by settings, _managed_hash_store and _managed_deployment_hash_store
|
|
121
176
|
if self._obj_hash is None:
|
|
122
|
-
self._obj_hash = hash(
|
|
123
|
-
tuple(
|
|
124
|
-
getattr(self, field.name)
|
|
125
|
-
for field in fields(self)
|
|
126
|
-
if field.name not in _MANAGED_FIELDS
|
|
127
|
-
)
|
|
128
|
-
)
|
|
177
|
+
self._obj_hash = hash(self.hash())
|
|
129
178
|
return self._obj_hash
|
|
130
179
|
|
|
131
180
|
def __eq__(self, other) -> bool:
|
|
132
|
-
return
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
181
|
+
return (
|
|
182
|
+
self.__class__ == other.__class__
|
|
183
|
+
and self.spec == other.spec
|
|
184
|
+
and self.hash() == other.hash()
|
|
136
185
|
)
|
|
137
186
|
|
|
138
187
|
|
|
@@ -6,6 +6,7 @@ __license__ = "MIT"
|
|
|
6
6
|
import types
|
|
7
7
|
from typing import Mapping
|
|
8
8
|
from snakemake_interface_software_deployment_plugins.settings import (
|
|
9
|
+
CommonSettings,
|
|
9
10
|
SoftwareDeploymentSettingsBase,
|
|
10
11
|
)
|
|
11
12
|
|
|
@@ -30,6 +31,7 @@ class SoftwareDeploymentPluginRegistry(PluginRegistryBase):
|
|
|
30
31
|
"""Load a plugin by name."""
|
|
31
32
|
return Plugin(
|
|
32
33
|
_name=name,
|
|
34
|
+
common_settings=module.common_settings,
|
|
33
35
|
_software_deployment_settings_cls=getattr(
|
|
34
36
|
module, "SoftwareDeploymentSettings", None
|
|
35
37
|
),
|
|
@@ -38,6 +40,11 @@ class SoftwareDeploymentPluginRegistry(PluginRegistryBase):
|
|
|
38
40
|
|
|
39
41
|
def expected_attributes(self) -> Mapping[str, AttributeType]:
|
|
40
42
|
return {
|
|
43
|
+
"common_settings": AttributeType(
|
|
44
|
+
cls=CommonSettings,
|
|
45
|
+
mode=AttributeMode.REQUIRED,
|
|
46
|
+
kind=AttributeKind.OBJECT,
|
|
47
|
+
),
|
|
41
48
|
"SoftwareDeploymentSettings": AttributeType(
|
|
42
49
|
cls=SoftwareDeploymentSettingsBase,
|
|
43
50
|
mode=AttributeMode.OPTIONAL,
|
|
@@ -7,6 +7,7 @@ from dataclasses import dataclass
|
|
|
7
7
|
from typing import Optional, Type
|
|
8
8
|
from snakemake_interface_software_deployment_plugins import EnvBase, EnvSpecBase
|
|
9
9
|
from snakemake_interface_software_deployment_plugins.settings import (
|
|
10
|
+
CommonSettings,
|
|
10
11
|
SoftwareDeploymentSettingsBase,
|
|
11
12
|
)
|
|
12
13
|
import snakemake_interface_software_deployment_plugins._common as common
|
|
@@ -16,6 +17,7 @@ from snakemake_interface_common.plugin_registry.plugin import PluginBase
|
|
|
16
17
|
|
|
17
18
|
@dataclass
|
|
18
19
|
class Plugin(PluginBase):
|
|
20
|
+
common_settings: CommonSettings
|
|
19
21
|
_software_deployment_settings_cls: Optional[Type[SoftwareDeploymentSettingsBase]]
|
|
20
22
|
_env_cls: Type[EnvBase]
|
|
21
23
|
_env_spec_cls: Type[EnvSpecBase]
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
import snakemake_interface_common.plugin_registry.plugin
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@dataclass
|
|
8
|
+
class SoftwareDeploymentSettingsBase(
|
|
9
|
+
snakemake_interface_common.plugin_registry.plugin.SettingsBase
|
|
10
|
+
):
|
|
11
|
+
"""Base class for software deployment settings.
|
|
12
|
+
|
|
13
|
+
Software deployment plugins can define a subclass of this class,
|
|
14
|
+
named 'SoftwareDeploymentProviderSettings'.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
pass
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@dataclass
|
|
21
|
+
class CommonSettings:
|
|
22
|
+
"""Common settings for software deployment plugins.
|
|
23
|
+
|
|
24
|
+
This class is used to define common settings for software deployment plugins.
|
|
25
|
+
|
|
26
|
+
Attributes
|
|
27
|
+
----------
|
|
28
|
+
provides : str
|
|
29
|
+
The kind of the software environment provided (e.g. conda, container).
|
|
30
|
+
This should not return something describing the tool to provide the software
|
|
31
|
+
environment but the resulting environment itself. For example,
|
|
32
|
+
it should return "conda" instead of mamba, rattler, pixi etc., or
|
|
33
|
+
"container" instead of docker, singularity, podman, or
|
|
34
|
+
"envmodules" instead of lmod, environment-modules, etc.
|
|
35
|
+
Snakemake will ensure that the user only activates one plugin per provided
|
|
36
|
+
kind.
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
provides: str
|
|
40
|
+
|
|
41
|
+
def __post_init__(self):
|
|
42
|
+
if not self.provides.isidentifier():
|
|
43
|
+
raise ValueError(
|
|
44
|
+
"CommonSettings.provides must be a valid Python identifier, but "
|
|
45
|
+
f"is {self.provides}."
|
|
46
|
+
)
|
|
@@ -46,10 +46,10 @@ class TestSoftwareDeploymentBase(ABC):
|
|
|
46
46
|
"""
|
|
47
47
|
...
|
|
48
48
|
|
|
49
|
+
@abstractmethod
|
|
49
50
|
def get_software_deployment_provider_settings(
|
|
50
51
|
self,
|
|
51
|
-
) -> Optional[SoftwareDeploymentSettingsBase]:
|
|
52
|
-
return None
|
|
52
|
+
) -> Optional[SoftwareDeploymentSettingsBase]: ...
|
|
53
53
|
|
|
54
54
|
def test_shellcmd(self, tmp_path):
|
|
55
55
|
env = self._get_env(tmp_path)
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
from dataclasses import dataclass
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import snakemake_interface_common.plugin_registry.plugin
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
@dataclass
|
|
8
|
-
class SoftwareDeploymentSettingsBase(
|
|
9
|
-
snakemake_interface_common.plugin_registry.plugin.SettingsBase
|
|
10
|
-
):
|
|
11
|
-
"""Base class for software deployment settings.
|
|
12
|
-
|
|
13
|
-
Software deployment plugins can define a subclass of this class,
|
|
14
|
-
named 'SoftwareDeploymentProviderSettings'.
|
|
15
|
-
"""
|
|
16
|
-
|
|
17
|
-
pass
|
|
File without changes
|
|
File without changes
|