pyinfra 3.4.1__py2.py3-none-any.whl → 3.5__py2.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.
- pyinfra/api/arguments.py +61 -0
- pyinfra/api/config.py +6 -0
- pyinfra/api/connect.py +19 -2
- pyinfra/api/operation.py +54 -1
- pyinfra/api/operations.py +119 -56
- pyinfra/api/state.py +10 -2
- pyinfra/connectors/scp/__init__.py +1 -0
- pyinfra/connectors/scp/client.py +204 -0
- pyinfra/connectors/ssh.py +39 -7
- pyinfra/connectors/util.py +4 -0
- pyinfra/facts/dnf.py +8 -4
- pyinfra/facts/docker.py +28 -8
- pyinfra/facts/files.py +167 -26
- pyinfra/facts/server.py +55 -4
- pyinfra/facts/util/packaging.py +1 -0
- pyinfra/facts/yum.py +8 -4
- pyinfra/facts/zypper.py +3 -3
- pyinfra/operations/crontab.py +1 -1
- pyinfra/operations/docker.py +130 -29
- pyinfra/operations/files.py +162 -7
- pyinfra/operations/git.py +1 -1
- pyinfra/operations/openrc.py +13 -7
- pyinfra/operations/pip.py +6 -7
- pyinfra/operations/pipx.py +19 -7
- pyinfra/operations/util/docker.py +49 -1
- pyinfra/operations/util/files.py +70 -2
- pyinfra/operations/util/packaging.py +98 -55
- {pyinfra-3.4.1.dist-info → pyinfra-3.5.dist-info}/METADATA +3 -3
- {pyinfra-3.4.1.dist-info → pyinfra-3.5.dist-info}/RECORD +37 -35
- pyinfra_cli/main.py +39 -0
- pyinfra_cli/prints.py +4 -0
- tests/test_api/test_api_operations.py +348 -0
- tests/test_cli/test_cli.py +3 -0
- {pyinfra-3.4.1.dist-info → pyinfra-3.5.dist-info}/LICENSE.md +0 -0
- {pyinfra-3.4.1.dist-info → pyinfra-3.5.dist-info}/WHEEL +0 -0
- {pyinfra-3.4.1.dist-info → pyinfra-3.5.dist-info}/entry_points.txt +0 -0
- {pyinfra-3.4.1.dist-info → pyinfra-3.5.dist-info}/top_level.txt +0 -0
|
@@ -165,7 +165,46 @@ def _remove_network(**kwargs):
|
|
|
165
165
|
return "docker network rm {0}".format(kwargs["network"])
|
|
166
166
|
|
|
167
167
|
|
|
168
|
-
def
|
|
168
|
+
def _install_plugin(**kwargs):
|
|
169
|
+
command = ["docker plugin install {0} --grant-all-permissions".format(kwargs["plugin"])]
|
|
170
|
+
|
|
171
|
+
plugin_options = kwargs["plugin_options"] if kwargs["plugin_options"] else {}
|
|
172
|
+
|
|
173
|
+
if kwargs["alias"]:
|
|
174
|
+
command.append("--alias {0}".format(kwargs["alias"]))
|
|
175
|
+
|
|
176
|
+
if not kwargs["enabled"]:
|
|
177
|
+
command.append("--disable")
|
|
178
|
+
|
|
179
|
+
for option, value in plugin_options.items():
|
|
180
|
+
command.append("{0}={1}".format(option, value))
|
|
181
|
+
|
|
182
|
+
return " ".join(command)
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def _remove_plugin(**kwargs):
|
|
186
|
+
return "docker plugin rm -f {0}".format(kwargs["plugin"])
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
def _enable_plugin(**kwargs):
|
|
190
|
+
return "docker plugin enable {0}".format(kwargs["plugin"])
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def _disable_plugin(**kwargs):
|
|
194
|
+
return "docker plugin disable {0}".format(kwargs["plugin"])
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
def _set_plugin_options(**kwargs):
|
|
198
|
+
command = ["docker plugin set {0}".format(kwargs["plugin"])]
|
|
199
|
+
existent_options = kwargs.get("existing_options", {})
|
|
200
|
+
required_options = kwargs.get("required_options", {})
|
|
201
|
+
options_to_set = existent_options | required_options
|
|
202
|
+
for option, value in options_to_set.items():
|
|
203
|
+
command.append("{0}={1}".format(option, value))
|
|
204
|
+
return " ".join(command)
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
def handle_docker(resource: str, command: str, **kwargs):
|
|
169
208
|
container_commands = {
|
|
170
209
|
"create": _create_container,
|
|
171
210
|
"remove": _remove_container,
|
|
@@ -192,12 +231,21 @@ def handle_docker(resource, command, **kwargs):
|
|
|
192
231
|
"prune": _prune_command,
|
|
193
232
|
}
|
|
194
233
|
|
|
234
|
+
plugin_commands = {
|
|
235
|
+
"install": _install_plugin,
|
|
236
|
+
"remove": _remove_plugin,
|
|
237
|
+
"enable": _enable_plugin,
|
|
238
|
+
"disable": _disable_plugin,
|
|
239
|
+
"set": _set_plugin_options,
|
|
240
|
+
}
|
|
241
|
+
|
|
195
242
|
docker_commands = {
|
|
196
243
|
"container": container_commands,
|
|
197
244
|
"image": image_commands,
|
|
198
245
|
"volume": volume_commands,
|
|
199
246
|
"network": network_commands,
|
|
200
247
|
"system": system_commands,
|
|
248
|
+
"plugin": plugin_commands,
|
|
201
249
|
}
|
|
202
250
|
|
|
203
251
|
return docker_commands[resource][command](**kwargs)
|
pyinfra/operations/util/files.py
CHANGED
|
@@ -1,12 +1,21 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import difflib
|
|
3
4
|
import re
|
|
4
|
-
from datetime import datetime
|
|
5
|
-
from
|
|
5
|
+
from datetime import datetime, timezone
|
|
6
|
+
from enum import Enum
|
|
7
|
+
from typing import Callable, Generator
|
|
8
|
+
|
|
9
|
+
import click
|
|
6
10
|
|
|
7
11
|
from pyinfra.api import QuoteString, StringCommand
|
|
8
12
|
|
|
9
13
|
|
|
14
|
+
class MetadataTimeField(Enum):
|
|
15
|
+
ATIME = "atime"
|
|
16
|
+
MTIME = "mtime"
|
|
17
|
+
|
|
18
|
+
|
|
10
19
|
def unix_path_join(*parts) -> str:
|
|
11
20
|
part_list = list(parts)
|
|
12
21
|
part_list[0:-1] = [part.rstrip("/") for part in part_list[0:-1]]
|
|
@@ -156,6 +165,34 @@ def chown(
|
|
|
156
165
|
return StringCommand(" ".join(args), user_group, QuoteString(target))
|
|
157
166
|
|
|
158
167
|
|
|
168
|
+
# like the touch command, but only supports setting one field at a time, and expects any
|
|
169
|
+
# reference times to have been read from the reference file metadata and turned into
|
|
170
|
+
# aware datetimes
|
|
171
|
+
def touch(
|
|
172
|
+
target: str,
|
|
173
|
+
timefield: MetadataTimeField,
|
|
174
|
+
timesrc: datetime,
|
|
175
|
+
dereference=True,
|
|
176
|
+
) -> StringCommand:
|
|
177
|
+
args = ["touch"]
|
|
178
|
+
|
|
179
|
+
if timefield is MetadataTimeField.ATIME:
|
|
180
|
+
args.append("-a")
|
|
181
|
+
else:
|
|
182
|
+
args.append("-m")
|
|
183
|
+
|
|
184
|
+
if not dereference:
|
|
185
|
+
args.append("-h")
|
|
186
|
+
|
|
187
|
+
# don't reinvent the wheel; use isoformat()
|
|
188
|
+
timestr = timesrc.astimezone(timezone.utc).isoformat()
|
|
189
|
+
# but replace the ISO format TZ offset with "Z" for BSD
|
|
190
|
+
timestr = timestr.replace("+00:00", "Z")
|
|
191
|
+
args.extend(["-d", timestr])
|
|
192
|
+
|
|
193
|
+
return StringCommand(" ".join(args), QuoteString(target))
|
|
194
|
+
|
|
195
|
+
|
|
159
196
|
def adjust_regex(line: str, escape_regex_characters: bool) -> str:
|
|
160
197
|
"""
|
|
161
198
|
Ensure the regex starts with '^' and ends with '$' and escape regex characters if requested
|
|
@@ -173,3 +210,34 @@ def adjust_regex(line: str, escape_regex_characters: bool) -> str:
|
|
|
173
210
|
match_line = "{0}.*$".format(match_line)
|
|
174
211
|
|
|
175
212
|
return match_line
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def generate_color_diff(
|
|
216
|
+
current_lines: list[str], desired_lines: list[str]
|
|
217
|
+
) -> Generator[str, None, None]:
|
|
218
|
+
def _format_range_unified(start: int, stop: int) -> str:
|
|
219
|
+
beginning = start + 1 # lines start numbering with one
|
|
220
|
+
length = stop - start
|
|
221
|
+
if length == 1:
|
|
222
|
+
return "{}".format(beginning)
|
|
223
|
+
if not length:
|
|
224
|
+
beginning -= 1 # empty ranges begin at line just before the range
|
|
225
|
+
return "{},{}".format(beginning, length)
|
|
226
|
+
|
|
227
|
+
for group in difflib.SequenceMatcher(None, current_lines, desired_lines).get_grouped_opcodes(2):
|
|
228
|
+
first, last = group[0], group[-1]
|
|
229
|
+
file1_range = _format_range_unified(first[1], last[2])
|
|
230
|
+
file2_range = _format_range_unified(first[3], last[4])
|
|
231
|
+
yield "@@ -{} +{} @@".format(file1_range, file2_range)
|
|
232
|
+
|
|
233
|
+
for tag, i1, i2, j1, j2 in group:
|
|
234
|
+
if tag == "equal":
|
|
235
|
+
for line in current_lines[i1:i2]:
|
|
236
|
+
yield " " + line.rstrip()
|
|
237
|
+
continue
|
|
238
|
+
if tag in {"replace", "delete"}:
|
|
239
|
+
for line in current_lines[i1:i2]:
|
|
240
|
+
yield click.style("- " + line.rstrip(), "red")
|
|
241
|
+
if tag in {"replace", "insert"}:
|
|
242
|
+
for line in desired_lines[j1:j2]:
|
|
243
|
+
yield click.style("+ " + line.rstrip(), "green")
|
|
@@ -3,19 +3,83 @@ from __future__ import annotations
|
|
|
3
3
|
import shlex
|
|
4
4
|
from collections import defaultdict
|
|
5
5
|
from io import StringIO
|
|
6
|
-
from typing import Callable
|
|
6
|
+
from typing import Callable, NamedTuple, cast
|
|
7
7
|
from urllib.parse import urlparse
|
|
8
8
|
|
|
9
|
-
from
|
|
9
|
+
from packaging.requirements import InvalidRequirement, Requirement
|
|
10
|
+
|
|
11
|
+
from pyinfra import logger
|
|
12
|
+
from pyinfra.api import Host, OperationValueError, State
|
|
10
13
|
from pyinfra.facts.files import File
|
|
11
14
|
from pyinfra.facts.rpm import RpmPackage
|
|
12
15
|
from pyinfra.operations import files
|
|
13
16
|
|
|
14
17
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
class PkgInfo(NamedTuple):
|
|
19
|
+
name: str
|
|
20
|
+
version: str
|
|
21
|
+
operator: str
|
|
22
|
+
url: str
|
|
23
|
+
"""
|
|
24
|
+
The key packaging information needed: version, operator and url are optional.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
@property
|
|
28
|
+
def lkup_name(self) -> str | list[str]:
|
|
29
|
+
return self.name if self.version == "" else [self.name, self.version]
|
|
30
|
+
|
|
31
|
+
@property
|
|
32
|
+
def has_version(self) -> bool:
|
|
33
|
+
return self.version != ""
|
|
34
|
+
|
|
35
|
+
@property
|
|
36
|
+
def inst_vers(self) -> str:
|
|
37
|
+
return (
|
|
38
|
+
self.url
|
|
39
|
+
if self.url != ""
|
|
40
|
+
else (
|
|
41
|
+
self.operator.join([self.name, self.version]) if self.version != "" else self.name
|
|
42
|
+
)
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
@classmethod
|
|
46
|
+
def from_possible_pair(cls, s: str, join: str | None) -> PkgInfo:
|
|
47
|
+
if join is not None:
|
|
48
|
+
pieces = s.rsplit(join, 1)
|
|
49
|
+
return cls(pieces[0], pieces[1] if len(pieces) > 1 else "", join, "")
|
|
50
|
+
|
|
51
|
+
return cls(s, "", "", "")
|
|
52
|
+
|
|
53
|
+
@classmethod
|
|
54
|
+
def from_pep508(cls, s: str) -> PkgInfo | None:
|
|
55
|
+
"""
|
|
56
|
+
Separate out the useful parts (name, url, operator, version) of a PEP-508 dependency.
|
|
57
|
+
Note: only one specifier is allowed.
|
|
58
|
+
PEP-0426 states that Python packages should be compared using lowercase; thus
|
|
59
|
+
the name is lower-cased
|
|
60
|
+
For backwards compatibility, invalid requirements are assumed to be package names with a
|
|
61
|
+
warning that this will change in the next major release
|
|
62
|
+
"""
|
|
63
|
+
pep_508 = "PEP 508 non-compliant "
|
|
64
|
+
treatment = "requirement treated as package name"
|
|
65
|
+
will_change = "4.x will make this an error" # pip and pipx already throw away None's
|
|
66
|
+
try:
|
|
67
|
+
reqt = Requirement(s)
|
|
68
|
+
except InvalidRequirement as e:
|
|
69
|
+
logger.warning(f"{pep_508} :{e}\n{will_change}")
|
|
70
|
+
return cls(s, "", "", "")
|
|
71
|
+
else:
|
|
72
|
+
if (len(reqt.specifier) > 0) and (len(reqt.specifier) > 1):
|
|
73
|
+
logger.warning(f"{pep_508}/unsupported specifier ({s}) {treatment}\n{will_change}")
|
|
74
|
+
return cls(s, "", "", "")
|
|
75
|
+
else:
|
|
76
|
+
spec = next(iter(reqt.specifier), None)
|
|
77
|
+
return cls(
|
|
78
|
+
reqt.name.lower(),
|
|
79
|
+
spec.version if spec is not None else "",
|
|
80
|
+
spec.operator if spec is not None else "",
|
|
81
|
+
reqt.url or "",
|
|
82
|
+
)
|
|
19
83
|
|
|
20
84
|
|
|
21
85
|
def _has_package(
|
|
@@ -57,12 +121,12 @@ def _has_package(
|
|
|
57
121
|
|
|
58
122
|
def ensure_packages(
|
|
59
123
|
host: Host,
|
|
60
|
-
packages_to_ensure: str | list[str] | None,
|
|
124
|
+
packages_to_ensure: str | list[str] | list[PkgInfo] | None,
|
|
61
125
|
current_packages: dict[str, set[str]],
|
|
62
126
|
present: bool,
|
|
63
127
|
install_command: str,
|
|
64
128
|
uninstall_command: str,
|
|
65
|
-
latest=False,
|
|
129
|
+
latest: bool = False,
|
|
66
130
|
upgrade_command: str | None = None,
|
|
67
131
|
version_join: str | None = None,
|
|
68
132
|
expand_package_fact: Callable[[str], list[str | list[str]]] | None = None,
|
|
@@ -70,22 +134,22 @@ def ensure_packages(
|
|
|
70
134
|
"""
|
|
71
135
|
Handles this common scenario:
|
|
72
136
|
|
|
73
|
-
+ We have a list of packages(/versions) to ensure
|
|
137
|
+
+ We have a list of packages(/versions/urls) to ensure
|
|
74
138
|
+ We have a map of existing package -> versions
|
|
75
139
|
+ We have the common command bits (install, uninstall, version "joiner")
|
|
76
140
|
+ Outputs commands to ensure our desired packages/versions
|
|
77
141
|
+ Optionally upgrades packages w/o specified version when present
|
|
78
142
|
|
|
79
143
|
Args:
|
|
80
|
-
packages_to_ensure (list): list of packages or package/versions
|
|
81
|
-
current_packages (
|
|
144
|
+
packages_to_ensure (list): list of packages or package/versions or PkgInfo's
|
|
145
|
+
current_packages (dict): dict of package names -> version
|
|
82
146
|
present (bool): whether packages should exist or not
|
|
83
147
|
install_command (str): command to prefix to list of packages to install
|
|
84
148
|
uninstall_command (str): as above for uninstalling packages
|
|
85
149
|
latest (bool): whether to upgrade installed packages when present
|
|
86
150
|
upgrade_command (str): as above for upgrading
|
|
87
151
|
version_join (str): the package manager specific "joiner", ie ``=`` for \
|
|
88
|
-
``<apt_pkg>=<version
|
|
152
|
+
``<apt_pkg>=<version>``. Not allowed if (pkg, ver, url) tuples are provided.
|
|
89
153
|
expand_package_fact: fact returning packages providing a capability \
|
|
90
154
|
(ie ``yum whatprovides``)
|
|
91
155
|
"""
|
|
@@ -95,12 +159,15 @@ def ensure_packages(
|
|
|
95
159
|
if isinstance(packages_to_ensure, str):
|
|
96
160
|
packages_to_ensure = [packages_to_ensure]
|
|
97
161
|
|
|
98
|
-
packages: list[
|
|
99
|
-
|
|
100
|
-
|
|
162
|
+
packages: list[PkgInfo] = []
|
|
163
|
+
if isinstance(packages_to_ensure[0], PkgInfo):
|
|
164
|
+
packages = cast("list[PkgInfo]", packages_to_ensure)
|
|
165
|
+
if version_join is not None:
|
|
166
|
+
raise OperationValueError("cannot specify version_join and provide list[PkgInfo]")
|
|
167
|
+
else:
|
|
101
168
|
packages = [
|
|
102
|
-
package
|
|
103
|
-
for package in [
|
|
169
|
+
PkgInfo.from_possible_pair(package, version_join)
|
|
170
|
+
for package in cast("list[str]", packages_to_ensure)
|
|
104
171
|
]
|
|
105
172
|
|
|
106
173
|
diff_packages = []
|
|
@@ -111,65 +178,41 @@ def ensure_packages(
|
|
|
111
178
|
if present is True:
|
|
112
179
|
for package in packages:
|
|
113
180
|
has_package, expanded_packages = _has_package(
|
|
114
|
-
package,
|
|
115
|
-
current_packages,
|
|
116
|
-
expand_package_fact,
|
|
181
|
+
package.lkup_name, current_packages, expand_package_fact
|
|
117
182
|
)
|
|
118
183
|
|
|
119
184
|
if not has_package:
|
|
120
|
-
diff_packages.append(package)
|
|
121
|
-
diff_expanded_packages[
|
|
185
|
+
diff_packages.append(package.inst_vers)
|
|
186
|
+
diff_expanded_packages[package.name] = expanded_packages
|
|
122
187
|
else:
|
|
123
188
|
# Present packages w/o version specified - for upgrade if latest
|
|
124
|
-
if
|
|
125
|
-
upgrade_packages.append(package)
|
|
189
|
+
if not package.has_version: # don't try to upgrade if a specific version requested
|
|
190
|
+
upgrade_packages.append(package.inst_vers)
|
|
126
191
|
|
|
127
192
|
if not latest:
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
host.noop(
|
|
131
|
-
"package {0} is installed ({1})".format(
|
|
132
|
-
package,
|
|
133
|
-
", ".join(current_packages[pkg_name]),
|
|
134
|
-
),
|
|
135
|
-
)
|
|
193
|
+
if (pkg := package.name) in current_packages:
|
|
194
|
+
host.noop(f"package {pkg} is installed ({','.join(current_packages[pkg])})")
|
|
136
195
|
else:
|
|
137
|
-
host.noop("package {
|
|
196
|
+
host.noop(f"package {package.name} is installed")
|
|
138
197
|
|
|
139
198
|
if present is False:
|
|
140
199
|
for package in packages:
|
|
141
|
-
# String version, just check if existing
|
|
142
200
|
has_package, expanded_packages = _has_package(
|
|
143
|
-
package,
|
|
144
|
-
current_packages,
|
|
145
|
-
expand_package_fact,
|
|
146
|
-
match_any=True,
|
|
201
|
+
package.lkup_name, current_packages, expand_package_fact, match_any=True
|
|
147
202
|
)
|
|
148
203
|
|
|
149
204
|
if has_package:
|
|
150
|
-
diff_packages.append(package)
|
|
151
|
-
diff_expanded_packages[
|
|
205
|
+
diff_packages.append(package.inst_vers)
|
|
206
|
+
diff_expanded_packages[package.name] = expanded_packages
|
|
152
207
|
else:
|
|
153
|
-
host.noop("package {
|
|
208
|
+
host.noop(f"package {package.name} is not installed")
|
|
154
209
|
|
|
155
210
|
if diff_packages:
|
|
156
211
|
command = install_command if present else uninstall_command
|
|
157
|
-
|
|
158
|
-
joined_packages = [
|
|
159
|
-
version_join.join(package) if isinstance(package, list) else package # type: ignore[union-attr] # noqa
|
|
160
|
-
for package in diff_packages
|
|
161
|
-
]
|
|
162
|
-
|
|
163
|
-
yield "{0} {1}".format(
|
|
164
|
-
command,
|
|
165
|
-
" ".join([shlex.quote(pkg) for pkg in joined_packages]),
|
|
166
|
-
)
|
|
212
|
+
yield f"{command} {' '.join([shlex.quote(pkg) for pkg in diff_packages])}"
|
|
167
213
|
|
|
168
214
|
if latest and upgrade_command and upgrade_packages:
|
|
169
|
-
yield "{
|
|
170
|
-
upgrade_command,
|
|
171
|
-
" ".join([shlex.quote(pkg) for pkg in upgrade_packages]),
|
|
172
|
-
)
|
|
215
|
+
yield f"{upgrade_command} {' '.join([shlex.quote(pkg) for pkg in upgrade_packages])}"
|
|
173
216
|
|
|
174
217
|
|
|
175
218
|
def ensure_rpm(state: State, host: Host, source: str, present: bool, package_manager_command: str):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pyinfra
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.5
|
|
4
4
|
Summary: pyinfra automates/provisions/manages/deploys infrastructure.
|
|
5
5
|
Home-page: https://pyinfra.com
|
|
6
6
|
Author: Nick / Fizzadar
|
|
@@ -52,7 +52,7 @@ Requires-Dist: flake8-isort ==6.1.2 ; extra == 'dev'
|
|
|
52
52
|
Requires-Dist: pyyaml ==6.0.2 ; extra == 'dev'
|
|
53
53
|
Requires-Dist: mypy ; extra == 'dev'
|
|
54
54
|
Requires-Dist: types-cryptography ; extra == 'dev'
|
|
55
|
-
Requires-Dist: types-paramiko ; extra == 'dev'
|
|
55
|
+
Requires-Dist: types-paramiko <4 ; extra == 'dev'
|
|
56
56
|
Requires-Dist: types-python-dateutil ; extra == 'dev'
|
|
57
57
|
Requires-Dist: types-PyYAML ; extra == 'dev'
|
|
58
58
|
Requires-Dist: pyinfra-guzzle-sphinx-theme ==0.17 ; extra == 'dev'
|
|
@@ -83,7 +83,7 @@ Requires-Dist: flake8-isort ==6.1.2 ; extra == 'test'
|
|
|
83
83
|
Requires-Dist: pyyaml ==6.0.2 ; extra == 'test'
|
|
84
84
|
Requires-Dist: mypy ; extra == 'test'
|
|
85
85
|
Requires-Dist: types-cryptography ; extra == 'test'
|
|
86
|
-
Requires-Dist: types-paramiko ; extra == 'test'
|
|
86
|
+
Requires-Dist: types-paramiko <4 ; extra == 'test'
|
|
87
87
|
Requires-Dist: types-python-dateutil ; extra == 'test'
|
|
88
88
|
Requires-Dist: types-PyYAML ; extra == 'test'
|
|
89
89
|
|
|
@@ -6,20 +6,20 @@ pyinfra/progress.py,sha256=X3hXZ4Flh_L9FE4ZEWxWoG0R4dA5UPd1FCO-Exd5Xtc,4193
|
|
|
6
6
|
pyinfra/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
7
|
pyinfra/version.py,sha256=LZf50PHDzEZv65w0G-iMICoQ9US0U5LWHAOEmNtkF3I,216
|
|
8
8
|
pyinfra/api/__init__.py,sha256=suGbKKM-qCduuXFYBEcyswlTqozewtYpdLRhK63PVn0,942
|
|
9
|
-
pyinfra/api/arguments.py,sha256=
|
|
9
|
+
pyinfra/api/arguments.py,sha256=pxfizvECzEahbIyPfmVnk9FsQFnOnDIFPhBZvFLEhFg,12231
|
|
10
10
|
pyinfra/api/arguments_typed.py,sha256=IZuhpmDfW9CP6ASS5Ie-3Wcnxl6bDNR3egU4Mfhbsb4,2303
|
|
11
11
|
pyinfra/api/command.py,sha256=NwF2syxV3zxCbBdHzvJ6ve5G-xwdNTjPHFPwguKVcYs,7741
|
|
12
|
-
pyinfra/api/config.py,sha256=
|
|
13
|
-
pyinfra/api/connect.py,sha256=
|
|
12
|
+
pyinfra/api/config.py,sha256=gVDV-aGh6LYOnHtBaivICrd3RBfjFRWy3-K9sG__eP8,9321
|
|
13
|
+
pyinfra/api/connect.py,sha256=jkx07iUL29u9pHHKH4WcNtvxwOA4DIbF7ixguFyuFjo,1984
|
|
14
14
|
pyinfra/api/connectors.py,sha256=nie7JuLxMSC6gqPjmjuCisQ11R-eAQDtMMWF6YbSQ48,659
|
|
15
15
|
pyinfra/api/deploy.py,sha256=Upd92oThQN0zhKbKW8vyPvBuoYiEGStuiEy7kNhZ00Y,3167
|
|
16
16
|
pyinfra/api/exceptions.py,sha256=cCbUp1qN1QO0d9aAvOAbRgYpLi0vUI5j7ZqSjcD1_P8,1861
|
|
17
17
|
pyinfra/api/facts.py,sha256=Hh9YCrqOppHdeUegOzmg6qbik5X6EyHPzhg8O_oF_Sg,9146
|
|
18
18
|
pyinfra/api/host.py,sha256=4a1bFR8vX8mUuXRZttXlzp2_ARzrg-xsH7n8uOxaaqQ,14098
|
|
19
19
|
pyinfra/api/inventory.py,sha256=i_LBI-Gn5FF-9SVDBH6xefTtvFzjuz12QQiFPGK2TrQ,7864
|
|
20
|
-
pyinfra/api/operation.py,sha256=
|
|
21
|
-
pyinfra/api/operations.py,sha256=
|
|
22
|
-
pyinfra/api/state.py,sha256=
|
|
20
|
+
pyinfra/api/operation.py,sha256=37lV_87G7KGCtPGsFSwHW-OQRGzBy-IsQpslRL0s9Hg,16870
|
|
21
|
+
pyinfra/api/operations.py,sha256=MedR-5W4BF23p_FMI7o62K72pgE7G1z2scKeC-b3JF0,13677
|
|
22
|
+
pyinfra/api/state.py,sha256=cj-JvxOljeDshWvRpq8AMQxdGaUaht8KyuyR3mEsI-Y,12859
|
|
23
23
|
pyinfra/api/util.py,sha256=62l3eLUhbcHm5N-Y58i7g8-NtAxuXakeOymDBptTjQ4,12838
|
|
24
24
|
pyinfra/connectors/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
25
25
|
pyinfra/connectors/base.py,sha256=0-BKInwTpjbnTakJhMTn_8LUOl81vUmC-q-HzVrwhkw,4703
|
|
@@ -27,11 +27,13 @@ pyinfra/connectors/chroot.py,sha256=sQIM1nOLzyIvv7FsqgAZsZ71jJtWLAQB_uaeB4m4GqE,
|
|
|
27
27
|
pyinfra/connectors/docker.py,sha256=At68g9Fx62Wm9dum0GLmQRkk0sr5NCYHWM6Zlfxx1Gc,11960
|
|
28
28
|
pyinfra/connectors/dockerssh.py,sha256=NGG6hSZ3z66RRKt6T0hnG2jiXFLR4P5uudi1COcGnY0,9021
|
|
29
29
|
pyinfra/connectors/local.py,sha256=DJMmZiPgeYvZyW0ANvWjCxF3elmDlmolkY0ktTW3rcg,6990
|
|
30
|
-
pyinfra/connectors/ssh.py,sha256=
|
|
30
|
+
pyinfra/connectors/ssh.py,sha256=Wxw23KKKLKU_DVq1lLdsHHwDzXR4_He99-ikg9CCxps,22576
|
|
31
31
|
pyinfra/connectors/ssh_util.py,sha256=CN_5AdTA3RpiWCnXTrRBjez1NsN59hITDzQmXIkZvoE,3683
|
|
32
32
|
pyinfra/connectors/terraform.py,sha256=j-a2yStBLdw1QLZRVnl_9TanDtdyujyCxBO2Oa00rPM,4289
|
|
33
|
-
pyinfra/connectors/util.py,sha256
|
|
33
|
+
pyinfra/connectors/util.py,sha256=-Ei6FMIzbVHD7G1R834Tg7RLoNzo-62wUYIkj043MRQ,11780
|
|
34
34
|
pyinfra/connectors/vagrant.py,sha256=0TT73ks64I4Yl-JSZjMBbpWA3VYBkqqLB-fUS8pS8GY,4813
|
|
35
|
+
pyinfra/connectors/scp/__init__.py,sha256=jnO-_8GfkKWhsFcDjAxjOkuUT2RbS22b8P_xPrX889U,44
|
|
36
|
+
pyinfra/connectors/scp/client.py,sha256=l_fPsbgz-7U6Y50ssuKKPFxD_cFoIPtaVXMCYDotbDI,6399
|
|
35
37
|
pyinfra/connectors/sshuserclient/__init__.py,sha256=Qc4RO2wknSWIiNTwOeQ0y2TeiuKHmyWDW2Dz4MOo9CE,44
|
|
36
38
|
pyinfra/connectors/sshuserclient/client.py,sha256=Ei2_mzCMNJopbpvpeLsdSiNb98rxEEy7uCOmpJbfd2o,10506
|
|
37
39
|
pyinfra/connectors/sshuserclient/config.py,sha256=FZkPrUYXkURZcFUHBGWw9lLC9uiH3DJ0rBYXJePchxw,2774
|
|
@@ -44,10 +46,10 @@ pyinfra/facts/cargo.py,sha256=qgOClhwZm4COcncDzOZccCzs67nPBi_x6VGiF2UA0sA,687
|
|
|
44
46
|
pyinfra/facts/choco.py,sha256=mpLleSqNqiaGRgyrhgceno2iPB1_1yjn8UJ90pvOZCs,886
|
|
45
47
|
pyinfra/facts/crontab.py,sha256=yCpBzBqgXt2BjAGCIttuQ2xKKtuhzg0VQ9WCDV46eV8,5754
|
|
46
48
|
pyinfra/facts/deb.py,sha256=1dR1puwY5wyyhhYYwaEBLjKU9sIyaNBNBlamVZ2KQg0,2074
|
|
47
|
-
pyinfra/facts/dnf.py,sha256=
|
|
48
|
-
pyinfra/facts/docker.py,sha256=
|
|
49
|
+
pyinfra/facts/dnf.py,sha256=wXatfZWVrrdLY7LM-vHKMg8Md1FiwkqHxmgRYbQqw90,1208
|
|
50
|
+
pyinfra/facts/docker.py,sha256=fqIqMR6HwSYpTUAjhCX8Hk57pcyL6ShIl98H32Ly6HM,3233
|
|
49
51
|
pyinfra/facts/efibootmgr.py,sha256=JPJSokE_RV9JstEPJRECnqSU-B0JCxmrocY8zBOva7M,3555
|
|
50
|
-
pyinfra/facts/files.py,sha256=
|
|
52
|
+
pyinfra/facts/files.py,sha256=bDj3QOk149J9PjFPpyH4uynLhUl1nd8VQFwxclsgIuE,19459
|
|
51
53
|
pyinfra/facts/flatpak.py,sha256=ovi3duwTqqwvt5GoDRN7R-PpkvR6sQ1SmgEADcSnkUE,1646
|
|
52
54
|
pyinfra/facts/freebsd.py,sha256=z7ZJRK8NV5HL-BfAdQs6pQKLEdrfdv7dVUmmOtVKUbA,2248
|
|
53
55
|
pyinfra/facts/gem.py,sha256=aX2-vcEqkxUIP0UJ_SVp9bf4B944oyDjsuujjs5q_9w,654
|
|
@@ -72,19 +74,19 @@ pyinfra/facts/postgresql.py,sha256=4nusMVvGhtku86KX4O4vjSxh_MamxZy_kmTQvvy0GhE,2
|
|
|
72
74
|
pyinfra/facts/rpm.py,sha256=ikuKYiUmjgvPA84qfE-gbq4Iv4AB5cvor1uKU6uHbXQ,2391
|
|
73
75
|
pyinfra/facts/runit.py,sha256=qok1FTSshiNrN603vjYTKOeM-NIlxwLbwOp-vPbPySo,2131
|
|
74
76
|
pyinfra/facts/selinux.py,sha256=8OylQ3H-huktRS34g5FYwivlp1wb4mKP0EFVf1LtMEE,4679
|
|
75
|
-
pyinfra/facts/server.py,sha256=
|
|
77
|
+
pyinfra/facts/server.py,sha256=W_ICGPvlCcaG-Majm5tTM2fZDho6wYCR4xUt19iOX1A,23444
|
|
76
78
|
pyinfra/facts/snap.py,sha256=2-c3z1qpOG7prmKJssLpOXmKo_wwdfROryro6gif2vo,2137
|
|
77
79
|
pyinfra/facts/systemd.py,sha256=meHXURtnoxeJbmPzWFTwvhjQBZ2NlQCY8Tj-oHTG_dI,4320
|
|
78
80
|
pyinfra/facts/sysvinit.py,sha256=q1OpHATFJxjLwatcnYRfpTR7_K2c29b4ppmZu-wgC-4,1589
|
|
79
81
|
pyinfra/facts/upstart.py,sha256=GcreN0mIM6_qRgqzFaA7PnX45RtbBpvVC00J6bKujyA,717
|
|
80
82
|
pyinfra/facts/vzctl.py,sha256=lUacmyakn2sJ2tD2FDAh1eeX3sxEVq7aRRwWM4QTguQ,760
|
|
81
83
|
pyinfra/facts/xbps.py,sha256=pNpgeITdHoJWhnJ_XFjySJ7H35d9h_v2F7GKqIrxgt0,663
|
|
82
|
-
pyinfra/facts/yum.py,sha256=
|
|
84
|
+
pyinfra/facts/yum.py,sha256=KM0ogmT2JPPuSZKV7HaUFxIA1IXhcXRmykRk9wloKag,1169
|
|
83
85
|
pyinfra/facts/zfs.py,sha256=4cWfTu2_V3Rkku8LfWzwruP_Tu4gJV2ZOrtW3otbP2w,1805
|
|
84
|
-
pyinfra/facts/zypper.py,sha256=
|
|
86
|
+
pyinfra/facts/zypper.py,sha256=OQ8VXA-aRpsleiXVaRotjOewSOknux_VQ1Xv3qlfy7k,958
|
|
85
87
|
pyinfra/facts/util/__init__.py,sha256=FNqUZjHPzJplb6ctHdZCVvmxAeVDQfFYmghC6B5edWQ,573
|
|
86
88
|
pyinfra/facts/util/databases.py,sha256=EphGQApzRBXI2nG1FL9h8bozY-o4SgdQgpv9YcnCkxs,730
|
|
87
|
-
pyinfra/facts/util/packaging.py,sha256=
|
|
89
|
+
pyinfra/facts/util/packaging.py,sha256=Bo7QxYO0Eyj4_i8G27aOWUD_Rfw741RhkEBm3dF5OMI,1229
|
|
88
90
|
pyinfra/facts/util/units.py,sha256=SNHCisxGwZedCOqO9tfOWJpZ5Stc0Wcg9mZcXoKBY0A,714
|
|
89
91
|
pyinfra/facts/util/win_files.py,sha256=S_IQ5kJD6ZgkEcVHajgh7BIMolLV-1q1ghIcwAS-E1Q,2561
|
|
90
92
|
pyinfra/operations/__init__.py,sha256=SOcW337KXIzD_LH-iJJfq14BQcCs5JzwswJ0PIzDgF4,357
|
|
@@ -94,23 +96,23 @@ pyinfra/operations/brew.py,sha256=aghLE4qyuhhRbt6fgSPV6_5fyWgTohA77Dc0gol19UU,51
|
|
|
94
96
|
pyinfra/operations/bsdinit.py,sha256=okQUQDr2H8Z-cAdfdbPJiuGujsHLuV5gpuMZ1UlICEM,1648
|
|
95
97
|
pyinfra/operations/cargo.py,sha256=mXWd6pb0IR6kzJMmPHwXZN-VJ-B_y8AdOFlrRzDQOZI,1104
|
|
96
98
|
pyinfra/operations/choco.py,sha256=8nG0wc1tZEA0L0HTIjgR00IDiONARokyzHyKj-R3xmo,1515
|
|
97
|
-
pyinfra/operations/crontab.py,sha256=
|
|
99
|
+
pyinfra/operations/crontab.py,sha256=4jxNsgmJED7w9w2Rq6Irsa4wMXxH_yPDIjkFlcpXj7E,6552
|
|
98
100
|
pyinfra/operations/dnf.py,sha256=3154Rer6dejVB1AK-CqyJhpMVn_djaSDJrVMs62GNcE,5599
|
|
99
|
-
pyinfra/operations/docker.py,sha256=
|
|
100
|
-
pyinfra/operations/files.py,sha256=
|
|
101
|
+
pyinfra/operations/docker.py,sha256=a-RlZ2_jzIXGEITDax9r_fKXBuGzpk-X_dP7pOto3lM,12272
|
|
102
|
+
pyinfra/operations/files.py,sha256=XfOG6rAqGQOJ9Ow1F8lrL2zTPFCbQjv0V9zqPwXYbVw,64620
|
|
101
103
|
pyinfra/operations/flatpak.py,sha256=QEJpzSXLyMQFk1XPAPHAfJVWcYWHnKA-tQr2hX6sB9o,2319
|
|
102
104
|
pyinfra/operations/gem.py,sha256=2C85sOwIRMHGvmPg4uAlUVf6MokhiA7LLPqzdJRHsBg,1132
|
|
103
|
-
pyinfra/operations/git.py,sha256=
|
|
105
|
+
pyinfra/operations/git.py,sha256=BqYQbG1VRw_XPtagbZHXitzss-U_LNGXRTwHE7L8P6M,13244
|
|
104
106
|
pyinfra/operations/iptables.py,sha256=brYa4kMhZKFTu24BNds_1b6sOaG94EfqWEoWrScx-Ck,9341
|
|
105
107
|
pyinfra/operations/launchd.py,sha256=6HWvqoQ74idV_NStOEmFXwu0dmTv7YDvFtsK8An2Lu4,1177
|
|
106
108
|
pyinfra/operations/lxd.py,sha256=bKm9gsgZaruKYSL7OYFMiou-wGP4BzwIMWzjW4AZYrk,1742
|
|
107
109
|
pyinfra/operations/mysql.py,sha256=ctm2Z6MaB0mOArCNU4TsJzaXiKXQaa_ahmsC5Vvyi10,19857
|
|
108
110
|
pyinfra/operations/npm.py,sha256=bUmfQsClZ2YcHiihiC7k5widIXIi6lbfx_32iyaAKfo,1499
|
|
109
|
-
pyinfra/operations/openrc.py,sha256=
|
|
111
|
+
pyinfra/operations/openrc.py,sha256=AThQQO7u_pO0M-rQbxkX7EWDuR569smkoPVaQoRoFeE,1834
|
|
110
112
|
pyinfra/operations/opkg.py,sha256=xBdmU07MWr-YBKX0EV0GuVrwMy6MOOf7wzYvD42sF_I,2607
|
|
111
113
|
pyinfra/operations/pacman.py,sha256=QMjmsBiiw362nhZY0rEDVQL5A32MG3u7GcmX4q4PzfI,1702
|
|
112
|
-
pyinfra/operations/pip.py,sha256=
|
|
113
|
-
pyinfra/operations/pipx.py,sha256=
|
|
114
|
+
pyinfra/operations/pip.py,sha256=Gh1vmrkCNktYXO8bh0IMEqjqhV07J8FYJcLHETZhjcQ,5995
|
|
115
|
+
pyinfra/operations/pipx.py,sha256=05AUm3nkkCfoxl0o4V5o9P_qb__0Yfv495dTBq7zkE4,2800
|
|
114
116
|
pyinfra/operations/pkg.py,sha256=rORQBbKeb-6gS0LYu0a0VdiWcDZoovcUONCaf6KMdeQ,2298
|
|
115
117
|
pyinfra/operations/pkgin.py,sha256=zhUyGzKjnUfGoyHbMoYMbeeMzcsiOUpBz1zIzppigJ0,1992
|
|
116
118
|
pyinfra/operations/postgres.py,sha256=hD65hRb8s3h6zlG-9WwT4JsNEXuxJUCY8ZRX61qlvlI,13367
|
|
@@ -136,9 +138,9 @@ pyinfra/operations/freebsd/pkg.py,sha256=3AyfI0-_9F4ho47KqZsOMQocwNtTF2q9g0i6Tff
|
|
|
136
138
|
pyinfra/operations/freebsd/service.py,sha256=1f7nTHELnhs3HBSrMFsmopVgYFMIwB8Se88yneRQ8Rw,3198
|
|
137
139
|
pyinfra/operations/freebsd/sysrc.py,sha256=eg7u_JsCge_uKq3Ysc_mohUc6qgJrOZStp_B_l2Hav4,2330
|
|
138
140
|
pyinfra/operations/util/__init__.py,sha256=ZAHjeCXtLo0TIOSfZ9h0Sh5IXXRCspfHs3RR1l8tQCE,366
|
|
139
|
-
pyinfra/operations/util/docker.py,sha256=
|
|
140
|
-
pyinfra/operations/util/files.py,sha256=
|
|
141
|
-
pyinfra/operations/util/packaging.py,sha256=
|
|
141
|
+
pyinfra/operations/util/docker.py,sha256=F7YmWIRSDyFaosf9q81nnwHhhIG7ktXOkM4VVOiUXTs,6931
|
|
142
|
+
pyinfra/operations/util/files.py,sha256=uW9CKQMwfBrG0iEArI5ubnkBNWJEYRJAyq26A7Gcafc,7118
|
|
143
|
+
pyinfra/operations/util/packaging.py,sha256=EHbjWiG6x5ekBtS09bQirqGrQNjJiqv5H7lYkNNj2bA,11410
|
|
142
144
|
pyinfra/operations/util/service.py,sha256=kJd1zj4-sAaGIp5Ts7yAJznogWaGr8oQTztwenLAr7Y,1309
|
|
143
145
|
pyinfra_cli/__init__.py,sha256=G0X7tNdqT45uWuK3aHIKxMdDeCgJ7zHo6vbxoG6zy_8,284
|
|
144
146
|
pyinfra_cli/__main__.py,sha256=WlW7eP0rrL06eguuD_q2RAqgUjg3SW-QnmrayAh2mBQ,887
|
|
@@ -146,8 +148,8 @@ pyinfra_cli/commands.py,sha256=J-mCJYvDebJ8M7o3HreB2zToa871-xO6_KjVhPLeHho,1832
|
|
|
146
148
|
pyinfra_cli/exceptions.py,sha256=RRaOprL7SmVv--FLy4x7fxeTitx9wYI0Y3_h01LfhJA,4901
|
|
147
149
|
pyinfra_cli/inventory.py,sha256=JYSixJZKY8GNWlOxh-nGDsAknCdaAktlWAmdg13kvNk,11771
|
|
148
150
|
pyinfra_cli/log.py,sha256=mD96MH2owQQ5AsYRw7osCKENdp-E3Wum5IDr6qhSIa4,2268
|
|
149
|
-
pyinfra_cli/main.py,sha256=
|
|
150
|
-
pyinfra_cli/prints.py,sha256=
|
|
151
|
+
pyinfra_cli/main.py,sha256=XUAwv-SrmZYiyW73DrC2ZmWYnVNp-aIp05WIO4xbSKo,20939
|
|
152
|
+
pyinfra_cli/prints.py,sha256=1h6vgKVRKUxcGz_HdyEEDUvkp-lgiiVGwx3hc9rw24A,10434
|
|
151
153
|
pyinfra_cli/util.py,sha256=9ehdJQ8pDNBLHXoFst9p696VDT-b_qo8UFMJrqdE1rE,6424
|
|
152
154
|
pyinfra_cli/virtualenv.py,sha256=wRNxOPcUkbD_Pzuj-Lnrz1KxGmsLlb2ObmCTFrdD-S8,2474
|
|
153
155
|
tests/test_api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -159,10 +161,10 @@ tests/test_api/test_api_deploys.py,sha256=h_zbI6CK4K8SdzEr3LEAMPxOf9hnQBdi_suqiN
|
|
|
159
161
|
tests/test_api/test_api_facts.py,sha256=_Z3g5mN3PJdqVGHYxwNUBqPoe6FZBiJEjBEJ0zS9EtY,11047
|
|
160
162
|
tests/test_api/test_api_host.py,sha256=U_VW2vTl35vR8EdyIGMKr4y0ydsDLbvHSjZDa99CyNE,1119
|
|
161
163
|
tests/test_api/test_api_inventory.py,sha256=rqXd3e_Wwc-SxCzxgR5eLd7ZOdrF8CcHbcTZndLy5gE,2744
|
|
162
|
-
tests/test_api/test_api_operations.py,sha256=
|
|
164
|
+
tests/test_api/test_api_operations.py,sha256=GLfTUjMSZAq9uvQdAjIf_0BJhSoLaypBJbrF0R_eAPw,32627
|
|
163
165
|
tests/test_api/test_api_util.py,sha256=uHv4oLpoy1_tzOoqFA1zpdvC74SvjitZbxQwp0dmjTs,1716
|
|
164
166
|
tests/test_cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
165
|
-
tests/test_cli/test_cli.py,sha256=
|
|
167
|
+
tests/test_cli/test_cli.py,sha256=Srg7j3sdYlbQshO2BgwDEakKCjG2XZUu2lV-SgGWcCI,6099
|
|
166
168
|
tests/test_cli/test_cli_deploy.py,sha256=vZC7twj8sPCy05loO50P-D_Xf73r6XN4m7yVj7TIFmo,5243
|
|
167
169
|
tests/test_cli/test_cli_exceptions.py,sha256=QaUv40q6Tp0HdcVEvPggFF4dsP2qdy57y9VAcGcR1So,3060
|
|
168
170
|
tests/test_cli/test_cli_inventory.py,sha256=FD4Hc4MzOfnrZTugVeNPOBf7bvE1degpDWQf5s6LZAg,4036
|
|
@@ -179,9 +181,9 @@ tests/test_connectors/test_sshuserclient.py,sha256=_anSd1cVQGIQkn08RdRbWjnSEkSS5
|
|
|
179
181
|
tests/test_connectors/test_terraform.py,sha256=RZInSjes394eR5CrGGEjzZEFY-UpQj47n4MZH0_ExyY,3779
|
|
180
182
|
tests/test_connectors/test_util.py,sha256=hQir0WyjH0LEF6xvIyHNyqdI5pkJX6qUR9287MgO2bY,4647
|
|
181
183
|
tests/test_connectors/test_vagrant.py,sha256=27qRB7ftjEPaj4ejBNZ-rR4Ou1AD1VyVcf2XjwZPG3M,3640
|
|
182
|
-
pyinfra-3.
|
|
183
|
-
pyinfra-3.
|
|
184
|
-
pyinfra-3.
|
|
185
|
-
pyinfra-3.
|
|
186
|
-
pyinfra-3.
|
|
187
|
-
pyinfra-3.
|
|
184
|
+
pyinfra-3.5.dist-info/LICENSE.md,sha256=BzCnRYLJv0yb-FJuEd_XOrrQSOEQKzIVo0yHT8taNnM,1076
|
|
185
|
+
pyinfra-3.5.dist-info/METADATA,sha256=pHq25twR3t_qYHepFbZFFNO4zF7PYYG4jymQbvkgEts,8141
|
|
186
|
+
pyinfra-3.5.dist-info/WHEEL,sha256=DZajD4pwLWue70CAfc7YaxT1wLUciNBvN_TTcvXpltE,110
|
|
187
|
+
pyinfra-3.5.dist-info/entry_points.txt,sha256=MT4cxTreOa_MzKgyPXk2BkeQ-KKcF1P8PJQe4vLQDaw,522
|
|
188
|
+
pyinfra-3.5.dist-info/top_level.txt,sha256=2K6D1mK35JTSEBgOfEPV-N-uA2SDErxGiE0J-HUMMVI,26
|
|
189
|
+
pyinfra-3.5.dist-info/RECORD,,
|