antsibull-nox 0.0.1__py3-none-any.whl → 0.2.0__py3-none-any.whl
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.
- antsibull_nox/__init__.py +66 -3
- antsibull_nox/ansible.py +260 -0
- antsibull_nox/collection/__init__.py +56 -0
- antsibull_nox/collection/data.py +106 -0
- antsibull_nox/collection/extract.py +23 -0
- antsibull_nox/collection/install.py +523 -0
- antsibull_nox/collection/search.py +456 -0
- antsibull_nox/config.py +332 -0
- antsibull_nox/data/action-groups.py +199 -0
- antsibull_nox/data/antsibull_nox_data_util.py +91 -0
- antsibull_nox/data/license-check.py +144 -0
- antsibull_nox/data/license-check.py.license +3 -0
- antsibull_nox/data/no-unwanted-files.py +123 -0
- antsibull_nox/data/plugin-yamllint.py +244 -0
- antsibull_nox/data_util.py +38 -0
- antsibull_nox/interpret_config.py +235 -0
- antsibull_nox/paths.py +220 -0
- antsibull_nox/python.py +81 -0
- antsibull_nox/sessions.py +1389 -168
- antsibull_nox/utils.py +85 -0
- {antsibull_nox-0.0.1.dist-info → antsibull_nox-0.2.0.dist-info}/METADATA +14 -4
- antsibull_nox-0.2.0.dist-info/RECORD +25 -0
- antsibull_nox-0.0.1.dist-info/RECORD +0 -7
- {antsibull_nox-0.0.1.dist-info → antsibull_nox-0.2.0.dist-info}/WHEEL +0 -0
- {antsibull_nox-0.0.1.dist-info → antsibull_nox-0.2.0.dist-info}/licenses/LICENSES/GPL-3.0-or-later.txt +0 -0
antsibull_nox/__init__.py
CHANGED
@@ -10,8 +10,71 @@ Antsibull Nox Helper.
|
|
10
10
|
|
11
11
|
from __future__ import annotations
|
12
12
|
|
13
|
-
from .
|
13
|
+
from .collection import CollectionSource, setup_collection_sources
|
14
|
+
from .config import load_config_from_toml
|
15
|
+
from .interpret_config import interpret_config
|
16
|
+
from .sessions import (
|
17
|
+
ActionGroup,
|
18
|
+
add_all_ansible_test_sanity_test_sessions,
|
19
|
+
add_all_ansible_test_unit_test_sessions,
|
20
|
+
add_ansible_lint,
|
21
|
+
add_ansible_test_integration_sessions_default_container,
|
22
|
+
add_ansible_test_sanity_test_session,
|
23
|
+
add_ansible_test_session,
|
24
|
+
add_ansible_test_unit_test_session,
|
25
|
+
add_build_import_check,
|
26
|
+
add_docs_check,
|
27
|
+
add_extra_checks,
|
28
|
+
add_license_check,
|
29
|
+
add_lint_sessions,
|
30
|
+
add_matrix_generator,
|
31
|
+
)
|
14
32
|
|
15
|
-
__version__ = "0.0
|
33
|
+
__version__ = "0.2.0"
|
16
34
|
|
17
|
-
|
35
|
+
|
36
|
+
def setup(
|
37
|
+
*,
|
38
|
+
collection_sources: dict[str, str | CollectionSource] | None = None,
|
39
|
+
) -> None:
|
40
|
+
"""
|
41
|
+
Set-up antsibull-nox.
|
42
|
+
"""
|
43
|
+
if collection_sources:
|
44
|
+
setup_collection_sources(
|
45
|
+
{
|
46
|
+
name: CollectionSource.parse(name, source)
|
47
|
+
for name, source in collection_sources.items()
|
48
|
+
}
|
49
|
+
)
|
50
|
+
|
51
|
+
|
52
|
+
def load_antsibull_nox_toml() -> None:
|
53
|
+
"""
|
54
|
+
Load and interpret antsibull-nox.toml config file.
|
55
|
+
"""
|
56
|
+
config = load_config_from_toml("antsibull-nox.toml")
|
57
|
+
interpret_config(config)
|
58
|
+
|
59
|
+
|
60
|
+
# pylint:disable=duplicate-code
|
61
|
+
__all__ = (
|
62
|
+
"__version__",
|
63
|
+
"ActionGroup",
|
64
|
+
"add_build_import_check",
|
65
|
+
"add_docs_check",
|
66
|
+
"add_extra_checks",
|
67
|
+
"add_license_check",
|
68
|
+
"add_lint_sessions",
|
69
|
+
"add_ansible_test_session",
|
70
|
+
"add_ansible_test_sanity_test_session",
|
71
|
+
"add_all_ansible_test_sanity_test_sessions",
|
72
|
+
"add_ansible_test_unit_test_session",
|
73
|
+
"add_all_ansible_test_unit_test_sessions",
|
74
|
+
"add_ansible_test_integration_sessions_default_container",
|
75
|
+
"add_ansible_lint",
|
76
|
+
"add_matrix_generator",
|
77
|
+
"CollectionSource",
|
78
|
+
"setup",
|
79
|
+
"load_antsibull_nox_toml",
|
80
|
+
)
|
antsibull_nox/ansible.py
ADDED
@@ -0,0 +1,260 @@
|
|
1
|
+
# Author: Felix Fontein <felix@fontein.de>
|
2
|
+
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or
|
3
|
+
# https://www.gnu.org/licenses/gpl-3.0.txt)
|
4
|
+
# SPDX-License-Identifier: GPL-3.0-or-later
|
5
|
+
# SPDX-FileCopyrightText: 2025, Ansible Project
|
6
|
+
|
7
|
+
"""
|
8
|
+
Ansible-core version utilities.
|
9
|
+
"""
|
10
|
+
|
11
|
+
from __future__ import annotations
|
12
|
+
|
13
|
+
import functools
|
14
|
+
import typing as t
|
15
|
+
from dataclasses import dataclass
|
16
|
+
|
17
|
+
from antsibull_fileutils.yaml import load_yaml_file
|
18
|
+
from packaging.specifiers import SpecifierSet as PckgSpecifierSet
|
19
|
+
from packaging.version import Version as PckgVersion
|
20
|
+
|
21
|
+
from .utils import Version, version_range
|
22
|
+
|
23
|
+
AnsibleCoreVersion = t.Union[Version, t.Literal["milestone", "devel"]]
|
24
|
+
|
25
|
+
|
26
|
+
@dataclass(frozen=True)
|
27
|
+
class AnsibleCoreInfo:
|
28
|
+
"""
|
29
|
+
Information on an ansible-core version.
|
30
|
+
"""
|
31
|
+
|
32
|
+
ansible_core_version: Version
|
33
|
+
controller_python_versions: tuple[Version, ...]
|
34
|
+
remote_python_versions: tuple[Version, ...]
|
35
|
+
|
36
|
+
|
37
|
+
_SUPPORTED_CORE_VERSIONS: dict[Version, AnsibleCoreInfo] = {
|
38
|
+
Version.parse(ansible_version): AnsibleCoreInfo(
|
39
|
+
ansible_core_version=Version.parse(ansible_version),
|
40
|
+
controller_python_versions=tuple(
|
41
|
+
Version.parse(v) for v in controller_python_versions
|
42
|
+
),
|
43
|
+
remote_python_versions=tuple(Version.parse(v) for v in remote_python_versions),
|
44
|
+
)
|
45
|
+
for ansible_version, (controller_python_versions, remote_python_versions) in {
|
46
|
+
"2.9": [
|
47
|
+
["2.7", "3.5", "3.6", "3.7", "3.8"],
|
48
|
+
["2.6", "2.7", "3.5", "3.6", "3.7", "3.8"],
|
49
|
+
],
|
50
|
+
"2.10": [
|
51
|
+
["2.7", "3.5", "3.6", "3.7", "3.8", "3.9"],
|
52
|
+
["2.6", "2.7", "3.5", "3.6", "3.7", "3.8", "3.9"],
|
53
|
+
],
|
54
|
+
"2.11": [
|
55
|
+
["2.7", "3.5", "3.6", "3.7", "3.8", "3.9"],
|
56
|
+
["2.6", "2.7", "3.5", "3.6", "3.7", "3.8", "3.9"],
|
57
|
+
],
|
58
|
+
"2.12": [
|
59
|
+
["3.8", "3.9", "3.10"],
|
60
|
+
["2.6", "2.7", "3.5", "3.6", "3.7", "3.8", "3.9", "3.10"],
|
61
|
+
],
|
62
|
+
"2.13": [
|
63
|
+
["3.8", "3.9", "3.10"],
|
64
|
+
["2.7", "3.5", "3.6", "3.7", "3.8", "3.9", "3.10"],
|
65
|
+
],
|
66
|
+
"2.14": [
|
67
|
+
["3.9", "3.10", "3.11"],
|
68
|
+
["2.7", "3.5", "3.6", "3.7", "3.8", "3.9", "3.10", "3.11"],
|
69
|
+
],
|
70
|
+
"2.15": [
|
71
|
+
["3.9", "3.10", "3.11"],
|
72
|
+
["2.7", "3.5", "3.6", "3.7", "3.8", "3.9", "3.10", "3.11"],
|
73
|
+
],
|
74
|
+
"2.16": [
|
75
|
+
["3.10", "3.11", "3.12"],
|
76
|
+
["2.7", "3.6", "3.7", "3.8", "3.9", "3.10", "3.11", "3.12"],
|
77
|
+
],
|
78
|
+
"2.17": [
|
79
|
+
["3.10", "3.11", "3.12"],
|
80
|
+
["3.7", "3.8", "3.9", "3.10", "3.11", "3.12"],
|
81
|
+
],
|
82
|
+
"2.18": [
|
83
|
+
["3.11", "3.12", "3.13"],
|
84
|
+
["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"],
|
85
|
+
],
|
86
|
+
"2.19": [
|
87
|
+
["3.11", "3.12", "3.13"],
|
88
|
+
["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"],
|
89
|
+
],
|
90
|
+
# The following might need updates. Look for the "``ansible-core`` support matrix" table in:
|
91
|
+
# https://github.com/ansible/ansible-documentation/blob/devel/docs/docsite/rst/reference_appendices/release_and_maintenance.rst?plain=1
|
92
|
+
# It contains commented-out entries for future ansible-core versions.
|
93
|
+
"2.20": [
|
94
|
+
["3.12", "3.13", "3.14"],
|
95
|
+
["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"],
|
96
|
+
],
|
97
|
+
"2.21": [
|
98
|
+
["3.12", "3.13", "3.14"],
|
99
|
+
["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"],
|
100
|
+
],
|
101
|
+
"2.22": [
|
102
|
+
["3.13", "3.14", "3.15"],
|
103
|
+
["3.10", "3.11", "3.12", "3.13", "3.14", "3.15"],
|
104
|
+
],
|
105
|
+
"2.23": [
|
106
|
+
["3.13", "3.14", "3.15"],
|
107
|
+
["3.10", "3.11", "3.12", "3.13", "3.14", "3.15"],
|
108
|
+
],
|
109
|
+
"2.24": [
|
110
|
+
["3.14", "3.15", "3.16"],
|
111
|
+
["3.11", "3.12", "3.13", "3.14", "3.15", "3.16"],
|
112
|
+
],
|
113
|
+
"2.25": [
|
114
|
+
["3.14", "3.15", "3.16"],
|
115
|
+
["3.11", "3.12", "3.13", "3.14", "3.15", "3.16"],
|
116
|
+
],
|
117
|
+
}.items()
|
118
|
+
}
|
119
|
+
|
120
|
+
_MIN_SUPPORTED_VERSION = Version.parse("2.9")
|
121
|
+
_CURRENT_DEVEL_VERSION = Version.parse("2.19")
|
122
|
+
_CURRENT_MILESTONE_VERSION = Version.parse("2.19")
|
123
|
+
|
124
|
+
|
125
|
+
def get_ansible_core_info(
|
126
|
+
core_version: AnsibleCoreVersion,
|
127
|
+
) -> AnsibleCoreInfo:
|
128
|
+
"""
|
129
|
+
Retrieve information on an ansible-core version.
|
130
|
+
"""
|
131
|
+
version: Version
|
132
|
+
if core_version == "devel":
|
133
|
+
version = _CURRENT_DEVEL_VERSION
|
134
|
+
elif core_version == "milestone":
|
135
|
+
version = _CURRENT_MILESTONE_VERSION
|
136
|
+
else:
|
137
|
+
version = core_version
|
138
|
+
if version in _SUPPORTED_CORE_VERSIONS:
|
139
|
+
return _SUPPORTED_CORE_VERSIONS[version]
|
140
|
+
raise ValueError(f"Unknown ansible-core version {version}")
|
141
|
+
|
142
|
+
|
143
|
+
_ANSIBLE_REPO = "ansible/ansible"
|
144
|
+
_ANSIBLE_EOL_REPO = "ansible-community/eol-ansible"
|
145
|
+
_ANSIBLE_EOL_MAX_VERSION = Version(2, 14)
|
146
|
+
|
147
|
+
|
148
|
+
def get_ansible_core_package_name(
|
149
|
+
core_version: AnsibleCoreVersion,
|
150
|
+
*,
|
151
|
+
source: t.Literal["git", "pypi"] = "git",
|
152
|
+
ansible_repo: str | None = None,
|
153
|
+
branch_name: str | None = None,
|
154
|
+
) -> str:
|
155
|
+
"""
|
156
|
+
Return the package name for a specific ansible-core version.
|
157
|
+
|
158
|
+
The result can be passed to pip to install that version of ansible-core.
|
159
|
+
"""
|
160
|
+
if not isinstance(core_version, Version):
|
161
|
+
# milestone and devel are not available from PyPI
|
162
|
+
source = "git"
|
163
|
+
|
164
|
+
if source == "git":
|
165
|
+
if branch_name is None:
|
166
|
+
if isinstance(core_version, str):
|
167
|
+
branch_name = core_version
|
168
|
+
else:
|
169
|
+
branch_name = f"stable-{core_version}"
|
170
|
+
if ansible_repo is None:
|
171
|
+
if (
|
172
|
+
isinstance(core_version, Version)
|
173
|
+
and core_version <= _ANSIBLE_EOL_MAX_VERSION
|
174
|
+
):
|
175
|
+
ansible_repo = _ANSIBLE_EOL_REPO
|
176
|
+
else:
|
177
|
+
ansible_repo = _ANSIBLE_REPO
|
178
|
+
return f"https://github.com/{ansible_repo}/archive/{branch_name}.tar.gz"
|
179
|
+
|
180
|
+
assert isinstance(core_version, Version)
|
181
|
+
next_core_version = core_version.next_minor_version()
|
182
|
+
base = "ansible-core"
|
183
|
+
if core_version == Version(2, 9):
|
184
|
+
base = "ansible"
|
185
|
+
elif core_version == Version(2, 10):
|
186
|
+
base = "ansible-base"
|
187
|
+
return f"{base}>={core_version},<{next_core_version}"
|
188
|
+
|
189
|
+
|
190
|
+
@functools.cache
|
191
|
+
def _read_requires_ansible() -> PckgSpecifierSet:
|
192
|
+
path = "meta/runtime.yml"
|
193
|
+
try:
|
194
|
+
runtime_data = load_yaml_file(path)
|
195
|
+
except FileNotFoundError as exc:
|
196
|
+
raise ValueError(f"Cannot open {path}") from exc
|
197
|
+
except Exception as exc:
|
198
|
+
raise ValueError(f"Cannot parse {path}: {exc}") from exc
|
199
|
+
|
200
|
+
requires_ansible = runtime_data.get("requires_ansible")
|
201
|
+
if not isinstance(requires_ansible, str):
|
202
|
+
raise ValueError(f"{path} does not contain an 'requires_ansible' string")
|
203
|
+
try:
|
204
|
+
return PckgSpecifierSet(requires_ansible)
|
205
|
+
except Exception as exc:
|
206
|
+
raise ValueError(
|
207
|
+
f"{path} contains an invalid 'requires_ansible' string: {exc}"
|
208
|
+
) from exc
|
209
|
+
|
210
|
+
|
211
|
+
@functools.cache
|
212
|
+
def get_supported_core_versions(
|
213
|
+
*,
|
214
|
+
include_devel: bool = False,
|
215
|
+
include_milestone: bool = False,
|
216
|
+
min_version: Version | None = None,
|
217
|
+
max_version: Version | None = None,
|
218
|
+
except_versions: tuple[AnsibleCoreVersion, ...] | None = None,
|
219
|
+
) -> list[AnsibleCoreVersion]:
|
220
|
+
"""
|
221
|
+
Extracts a list of supported ansible-core versions from meta/runtime.yml.
|
222
|
+
|
223
|
+
If ``min_version`` is specified, no version below that version will be returned.
|
224
|
+
If ``max_version`` is specified, no version above that version will be returned.
|
225
|
+
If ``except_versions`` is specified, no version in that tuple will be returned.
|
226
|
+
"""
|
227
|
+
if except_versions is None:
|
228
|
+
except_versions = ()
|
229
|
+
|
230
|
+
ra_specifier = _read_requires_ansible()
|
231
|
+
|
232
|
+
result: list[AnsibleCoreVersion] = []
|
233
|
+
for version in version_range(
|
234
|
+
_MIN_SUPPORTED_VERSION, _CURRENT_DEVEL_VERSION, inclusive=False
|
235
|
+
):
|
236
|
+
if version in except_versions:
|
237
|
+
continue
|
238
|
+
if min_version is not None and version < min_version:
|
239
|
+
continue
|
240
|
+
if max_version is not None and version > max_version:
|
241
|
+
continue
|
242
|
+
# We're using x.y.999 to check whether *some* ansible-core x.y version is supported.
|
243
|
+
# This is not entirely correct, since collections might specfiy that only certain older x.y
|
244
|
+
# versions are OK, but I'd consider such behavior a bug of the collection and something
|
245
|
+
# you really shouldn't do as a collection maintainer.
|
246
|
+
v = PckgVersion(f"{version.major}.{version.minor}.999")
|
247
|
+
if v in ra_specifier:
|
248
|
+
result.append(version)
|
249
|
+
if include_milestone and "milestone" not in except_versions:
|
250
|
+
result.append("milestone")
|
251
|
+
if include_devel and "devel" not in except_versions:
|
252
|
+
result.append("devel")
|
253
|
+
return result
|
254
|
+
|
255
|
+
|
256
|
+
__all__ = [
|
257
|
+
"AnsibleCoreInfo",
|
258
|
+
"get_ansible_core_info",
|
259
|
+
"get_ansible_core_package_name",
|
260
|
+
]
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# Author: Felix Fontein <felix@fontein.de>
|
2
|
+
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or
|
3
|
+
# https://www.gnu.org/licenses/gpl-3.0.txt)
|
4
|
+
# SPDX-License-Identifier: GPL-3.0-or-later
|
5
|
+
# SPDX-FileCopyrightText: 2025, Ansible Project
|
6
|
+
|
7
|
+
"""
|
8
|
+
Handle Ansible collections.
|
9
|
+
"""
|
10
|
+
|
11
|
+
from __future__ import annotations
|
12
|
+
|
13
|
+
from pathlib import Path
|
14
|
+
|
15
|
+
from antsibull_fileutils.yaml import load_yaml_file, store_yaml_file
|
16
|
+
|
17
|
+
from .data import CollectionData, CollectionSource, SetupResult
|
18
|
+
from .install import (
|
19
|
+
Runner,
|
20
|
+
setup_collection_sources,
|
21
|
+
setup_collections,
|
22
|
+
setup_current_tree,
|
23
|
+
)
|
24
|
+
from .search import CollectionList, load_collection_data_from_disk
|
25
|
+
|
26
|
+
|
27
|
+
def force_collection_version(path: Path, *, version: str) -> bool:
|
28
|
+
"""
|
29
|
+
Make sure galaxy.yml contains this version.
|
30
|
+
|
31
|
+
Returns ``True`` if the version was changed, and ``False`` if the version
|
32
|
+
was already set to this value.
|
33
|
+
"""
|
34
|
+
galaxy_yml = path / "galaxy.yml"
|
35
|
+
try:
|
36
|
+
data = load_yaml_file(galaxy_yml)
|
37
|
+
except Exception as exc:
|
38
|
+
raise ValueError(f"Cannot parse {galaxy_yml}: {exc}") from exc
|
39
|
+
if data.get("version") == version:
|
40
|
+
return False
|
41
|
+
data["version"] = version
|
42
|
+
store_yaml_file(galaxy_yml, data)
|
43
|
+
return True
|
44
|
+
|
45
|
+
|
46
|
+
__all__ = [
|
47
|
+
"CollectionData",
|
48
|
+
"CollectionList",
|
49
|
+
"CollectionSource",
|
50
|
+
"SetupResult",
|
51
|
+
"Runner",
|
52
|
+
"load_collection_data_from_disk",
|
53
|
+
"setup_collections",
|
54
|
+
"setup_current_tree",
|
55
|
+
"setup_collection_sources",
|
56
|
+
]
|
@@ -0,0 +1,106 @@
|
|
1
|
+
# Author: Felix Fontein <felix@fontein.de>
|
2
|
+
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or
|
3
|
+
# https://www.gnu.org/licenses/gpl-3.0.txt)
|
4
|
+
# SPDX-License-Identifier: GPL-3.0-or-later
|
5
|
+
# SPDX-FileCopyrightText: 2025, Ansible Project
|
6
|
+
|
7
|
+
"""
|
8
|
+
Data types for collections.
|
9
|
+
"""
|
10
|
+
|
11
|
+
from __future__ import annotations
|
12
|
+
|
13
|
+
from dataclasses import dataclass
|
14
|
+
from pathlib import Path
|
15
|
+
|
16
|
+
|
17
|
+
@dataclass
|
18
|
+
class CollectionData: # pylint: disable=too-many-instance-attributes
|
19
|
+
"""
|
20
|
+
An Ansible collection.
|
21
|
+
"""
|
22
|
+
|
23
|
+
collections_root_path: Path | None
|
24
|
+
path: Path
|
25
|
+
namespace: str
|
26
|
+
name: str
|
27
|
+
full_name: str
|
28
|
+
version: str | None
|
29
|
+
dependencies: dict[str, str]
|
30
|
+
current: bool
|
31
|
+
|
32
|
+
@classmethod
|
33
|
+
def create(
|
34
|
+
cls,
|
35
|
+
*,
|
36
|
+
collections_root_path: Path | None = None,
|
37
|
+
path: Path,
|
38
|
+
full_name: str,
|
39
|
+
version: str | None = None,
|
40
|
+
dependencies: dict[str, str] | None = None,
|
41
|
+
current: bool = False,
|
42
|
+
):
|
43
|
+
"""
|
44
|
+
Create a CollectionData object.
|
45
|
+
"""
|
46
|
+
namespace, name = full_name.split(".", 1)
|
47
|
+
return CollectionData(
|
48
|
+
collections_root_path=collections_root_path,
|
49
|
+
path=path,
|
50
|
+
namespace=namespace,
|
51
|
+
name=name,
|
52
|
+
full_name=full_name,
|
53
|
+
version=version,
|
54
|
+
dependencies=dependencies or {},
|
55
|
+
current=current,
|
56
|
+
)
|
57
|
+
|
58
|
+
|
59
|
+
@dataclass
|
60
|
+
class SetupResult:
|
61
|
+
"""
|
62
|
+
Information on how the collections are set up.
|
63
|
+
"""
|
64
|
+
|
65
|
+
# The path of the ansible_collections directory.
|
66
|
+
root: Path
|
67
|
+
|
68
|
+
# Data on the current collection (as in the repository).
|
69
|
+
current_collection: CollectionData
|
70
|
+
|
71
|
+
# If it was installed, the path of the current collection inside the collection tree below root.
|
72
|
+
current_path: Path | None
|
73
|
+
|
74
|
+
|
75
|
+
@dataclass
|
76
|
+
class CollectionSource:
|
77
|
+
"""
|
78
|
+
Collection installation source.
|
79
|
+
"""
|
80
|
+
|
81
|
+
# The collection's name
|
82
|
+
name: str
|
83
|
+
|
84
|
+
# The collection's installation source (can be passed to 'ansible-galaxy collection install')
|
85
|
+
source: str
|
86
|
+
|
87
|
+
@staticmethod
|
88
|
+
def parse(collection_name: str, source: str | CollectionSource) -> CollectionSource:
|
89
|
+
"""
|
90
|
+
Parse a CollectionSource object.
|
91
|
+
"""
|
92
|
+
if isinstance(source, str):
|
93
|
+
return CollectionSource(name=collection_name, source=source)
|
94
|
+
|
95
|
+
if source.name != collection_name:
|
96
|
+
raise ValueError(
|
97
|
+
f"Collection name should be {collection_name!r}, but is {source.name!r}"
|
98
|
+
)
|
99
|
+
return source
|
100
|
+
|
101
|
+
|
102
|
+
__all__ = [
|
103
|
+
"CollectionData",
|
104
|
+
"SetupResult",
|
105
|
+
"CollectionSource",
|
106
|
+
]
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# Author: Felix Fontein <felix@fontein.de>
|
2
|
+
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or
|
3
|
+
# https://www.gnu.org/licenses/gpl-3.0.txt)
|
4
|
+
# SPDX-License-Identifier: GPL-3.0-or-later
|
5
|
+
# SPDX-FileCopyrightText: 2025, Ansible Project
|
6
|
+
|
7
|
+
"""
|
8
|
+
Extract tarballs.
|
9
|
+
"""
|
10
|
+
|
11
|
+
from __future__ import annotations
|
12
|
+
|
13
|
+
import tarfile
|
14
|
+
from pathlib import Path
|
15
|
+
|
16
|
+
|
17
|
+
def extract_tarball(*, tarball: Path, destination: Path) -> None:
|
18
|
+
"""
|
19
|
+
Extract the contents of the tarball ``tarball`` to the destination directory ``destination``.
|
20
|
+
"""
|
21
|
+
destination.mkdir(exist_ok=True, parents=True)
|
22
|
+
with tarfile.open(tarball) as tar:
|
23
|
+
tar.extractall(path=destination, filter="data")
|