antsibull-nox 0.0.1__py3-none-any.whl → 0.1.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 +19 -3
- antsibull_nox/collection.py +545 -0
- antsibull_nox/data/action-groups.py +199 -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 +119 -0
- antsibull_nox/data_util.py +115 -0
- antsibull_nox/paths.py +201 -0
- antsibull_nox/sessions.py +507 -158
- {antsibull_nox-0.0.1.dist-info → antsibull_nox-0.1.0.dist-info}/METADATA +12 -4
- antsibull_nox-0.1.0.dist-info/RECORD +14 -0
- antsibull_nox-0.0.1.dist-info/RECORD +0 -7
- {antsibull_nox-0.0.1.dist-info → antsibull_nox-0.1.0.dist-info}/WHEEL +0 -0
- {antsibull_nox-0.0.1.dist-info → antsibull_nox-0.1.0.dist-info}/licenses/LICENSES/GPL-3.0-or-later.txt +0 -0
antsibull_nox/paths.py
ADDED
@@ -0,0 +1,201 @@
|
|
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
|
+
Path utilities.
|
9
|
+
"""
|
10
|
+
|
11
|
+
from __future__ import annotations
|
12
|
+
|
13
|
+
import atexit
|
14
|
+
import functools
|
15
|
+
import os
|
16
|
+
import shutil
|
17
|
+
import tempfile
|
18
|
+
from pathlib import Path
|
19
|
+
|
20
|
+
from antsibull_fileutils.copier import Copier, GitCopier
|
21
|
+
from antsibull_fileutils.vcs import detect_vcs, list_git_files
|
22
|
+
|
23
|
+
|
24
|
+
def find_data_directory() -> Path:
|
25
|
+
"""
|
26
|
+
Retrieve the directory for antsibull_nox.data on disk.
|
27
|
+
"""
|
28
|
+
return Path(__file__).parent / "data"
|
29
|
+
|
30
|
+
|
31
|
+
def match_path(path: str, is_file: bool, paths: list[str]) -> bool:
|
32
|
+
"""
|
33
|
+
Check whether a path (that is a file or not) matches a given list of paths.
|
34
|
+
"""
|
35
|
+
for check in paths:
|
36
|
+
if check == path:
|
37
|
+
return True
|
38
|
+
if not is_file:
|
39
|
+
if not check.endswith("/"):
|
40
|
+
check += "/"
|
41
|
+
if path.startswith(check):
|
42
|
+
return True
|
43
|
+
return False
|
44
|
+
|
45
|
+
|
46
|
+
def restrict_paths(paths: list[str], restrict: list[str]) -> list[str]:
|
47
|
+
"""
|
48
|
+
Restrict a list of paths with a given set of restrictions.
|
49
|
+
"""
|
50
|
+
result = []
|
51
|
+
for path in paths:
|
52
|
+
is_file = os.path.isfile(path)
|
53
|
+
if not is_file and not path.endswith("/"):
|
54
|
+
path += "/"
|
55
|
+
if not match_path(path, is_file, restrict):
|
56
|
+
if not is_file:
|
57
|
+
for check in restrict:
|
58
|
+
if check.startswith(path) and os.path.exists(check):
|
59
|
+
result.append(check)
|
60
|
+
continue
|
61
|
+
result.append(path)
|
62
|
+
return result
|
63
|
+
|
64
|
+
|
65
|
+
def _scan_remove_paths(
|
66
|
+
path: str, remove: list[str], extensions: list[str] | None
|
67
|
+
) -> list[str]:
|
68
|
+
result = []
|
69
|
+
for root, dirs, files in os.walk(path, topdown=True):
|
70
|
+
if not root.endswith("/"):
|
71
|
+
root += "/"
|
72
|
+
if match_path(root, False, remove):
|
73
|
+
continue
|
74
|
+
if all(not check.startswith(root) for check in remove):
|
75
|
+
dirs[:] = []
|
76
|
+
result.append(root)
|
77
|
+
continue
|
78
|
+
for file in files:
|
79
|
+
if extensions and os.path.splitext(file)[1] not in extensions:
|
80
|
+
continue
|
81
|
+
filepath = os.path.normpath(os.path.join(root, file))
|
82
|
+
if not match_path(filepath, True, remove):
|
83
|
+
result.append(filepath)
|
84
|
+
for directory in list(dirs):
|
85
|
+
if directory == "__pycache__":
|
86
|
+
continue
|
87
|
+
dirpath = os.path.normpath(os.path.join(root, directory))
|
88
|
+
if match_path(dirpath, False, remove):
|
89
|
+
dirs.remove(directory)
|
90
|
+
continue
|
91
|
+
return result
|
92
|
+
|
93
|
+
|
94
|
+
def remove_paths(
|
95
|
+
paths: list[str], remove: list[str], extensions: list[str] | None
|
96
|
+
) -> list[str]:
|
97
|
+
"""
|
98
|
+
Restrict a list of paths by removing paths.
|
99
|
+
|
100
|
+
If ``extensions`` is specified, only files matching this extension
|
101
|
+
will be considered when files need to be explicitly enumerated.
|
102
|
+
"""
|
103
|
+
result = []
|
104
|
+
for path in paths:
|
105
|
+
is_file = os.path.isfile(path)
|
106
|
+
if not is_file and not path.endswith("/"):
|
107
|
+
path += "/"
|
108
|
+
if match_path(path, is_file, remove):
|
109
|
+
continue
|
110
|
+
if not is_file and any(check.startswith(path) for check in remove):
|
111
|
+
result.extend(_scan_remove_paths(path, remove, extensions))
|
112
|
+
continue
|
113
|
+
result.append(path)
|
114
|
+
return result
|
115
|
+
|
116
|
+
|
117
|
+
def filter_paths(
|
118
|
+
paths: list[str],
|
119
|
+
/,
|
120
|
+
remove: list[str] | None = None,
|
121
|
+
restrict: list[str] | None = None,
|
122
|
+
extensions: list[str] | None = None,
|
123
|
+
) -> list[str]:
|
124
|
+
"""
|
125
|
+
Modifies a list of paths by restricting to and/or removing paths.
|
126
|
+
"""
|
127
|
+
if restrict:
|
128
|
+
paths = restrict_paths(paths, restrict)
|
129
|
+
if remove:
|
130
|
+
paths = remove_paths(paths, remove, extensions)
|
131
|
+
return [path for path in paths if os.path.exists(path)]
|
132
|
+
|
133
|
+
|
134
|
+
@functools.cache
|
135
|
+
def list_all_files() -> list[Path]:
|
136
|
+
"""
|
137
|
+
List all files of interest in the repository.
|
138
|
+
"""
|
139
|
+
directory = Path.cwd()
|
140
|
+
vcs = detect_vcs(directory)
|
141
|
+
if vcs == "git":
|
142
|
+
return [directory / path.decode("utf-8") for path in list_git_files(directory)]
|
143
|
+
result = []
|
144
|
+
for root, dirs, files in os.walk(directory, topdown=True):
|
145
|
+
root_path = Path(root)
|
146
|
+
for file in files:
|
147
|
+
result.append(root_path / file)
|
148
|
+
if root_path == directory and ".nox" in dirs:
|
149
|
+
dirs.remove(".nox")
|
150
|
+
return result
|
151
|
+
|
152
|
+
|
153
|
+
def remove_path(path: Path) -> None:
|
154
|
+
"""
|
155
|
+
Delete a path.
|
156
|
+
"""
|
157
|
+
if not path.is_symlink() and path.is_dir():
|
158
|
+
shutil.rmtree(path)
|
159
|
+
elif path.exists():
|
160
|
+
path.unlink()
|
161
|
+
|
162
|
+
|
163
|
+
def copy_collection(source: Path, destination: Path) -> None:
|
164
|
+
"""
|
165
|
+
Copy a collection from source to destination.
|
166
|
+
|
167
|
+
Automatically detect supported VCSs and use their information to avoid
|
168
|
+
copying ignored files.
|
169
|
+
"""
|
170
|
+
if destination.exists():
|
171
|
+
remove_path(destination)
|
172
|
+
vcs = detect_vcs(source)
|
173
|
+
copier = {
|
174
|
+
"none": Copier,
|
175
|
+
"git": GitCopier,
|
176
|
+
}.get(vcs, Copier)()
|
177
|
+
copier.copy(source, destination, exclude_root=[".nox", ".tox"])
|
178
|
+
|
179
|
+
|
180
|
+
def create_temp_directory(basename: str) -> Path:
|
181
|
+
"""
|
182
|
+
Create a temporary directory outside the nox tree.
|
183
|
+
"""
|
184
|
+
directory = tempfile.mkdtemp(prefix=basename)
|
185
|
+
path = Path(directory)
|
186
|
+
|
187
|
+
def cleanup() -> None:
|
188
|
+
remove_path(path)
|
189
|
+
|
190
|
+
atexit.register(cleanup)
|
191
|
+
return path
|
192
|
+
|
193
|
+
|
194
|
+
__all__ = [
|
195
|
+
"copy_collection",
|
196
|
+
"create_temp_directory",
|
197
|
+
"filter_paths",
|
198
|
+
"find_data_directory",
|
199
|
+
"list_all_files",
|
200
|
+
"remove_path",
|
201
|
+
]
|