pyinfra 3.0b1__py2.py3-none-any.whl → 3.0b2__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.
Files changed (104) hide show
  1. pyinfra/api/arguments.py +9 -3
  2. pyinfra/api/arguments_typed.py +8 -5
  3. pyinfra/api/command.py +5 -3
  4. pyinfra/api/config.py +115 -13
  5. pyinfra/api/connectors.py +5 -2
  6. pyinfra/api/facts.py +33 -32
  7. pyinfra/api/host.py +5 -5
  8. pyinfra/api/inventory.py +4 -0
  9. pyinfra/api/operation.py +22 -14
  10. pyinfra/api/util.py +24 -16
  11. pyinfra/connectors/base.py +3 -6
  12. pyinfra/connectors/docker.py +2 -9
  13. pyinfra/connectors/local.py +2 -2
  14. pyinfra/connectors/ssh.py +2 -2
  15. pyinfra/connectors/util.py +6 -7
  16. pyinfra/connectors/vagrant.py +5 -5
  17. pyinfra/context.py +1 -0
  18. pyinfra/facts/apk.py +2 -0
  19. pyinfra/facts/apt.py +2 -0
  20. pyinfra/facts/brew.py +2 -0
  21. pyinfra/facts/bsdinit.py +2 -0
  22. pyinfra/facts/cargo.py +2 -0
  23. pyinfra/facts/choco.py +2 -0
  24. pyinfra/facts/deb.py +7 -2
  25. pyinfra/facts/dnf.py +2 -0
  26. pyinfra/facts/docker.py +2 -0
  27. pyinfra/facts/files.py +2 -0
  28. pyinfra/facts/gem.py +2 -0
  29. pyinfra/facts/gpg.py +2 -0
  30. pyinfra/facts/hardware.py +30 -22
  31. pyinfra/facts/launchd.py +2 -0
  32. pyinfra/facts/lxd.py +2 -0
  33. pyinfra/facts/mysql.py +12 -6
  34. pyinfra/facts/npm.py +1 -0
  35. pyinfra/facts/openrc.py +2 -0
  36. pyinfra/facts/pacman.py +6 -2
  37. pyinfra/facts/pip.py +2 -0
  38. pyinfra/facts/pkg.py +2 -0
  39. pyinfra/facts/pkgin.py +2 -0
  40. pyinfra/facts/postgres.py +6 -6
  41. pyinfra/facts/postgresql.py +2 -0
  42. pyinfra/facts/rpm.py +12 -9
  43. pyinfra/facts/server.py +10 -13
  44. pyinfra/facts/snap.py +2 -0
  45. pyinfra/facts/systemd.py +2 -0
  46. pyinfra/facts/upstart.py +2 -0
  47. pyinfra/facts/util/packaging.py +3 -2
  48. pyinfra/facts/vzctl.py +2 -0
  49. pyinfra/facts/xbps.py +2 -0
  50. pyinfra/facts/yum.py +2 -0
  51. pyinfra/facts/zypper.py +2 -0
  52. pyinfra/operations/apk.py +3 -1
  53. pyinfra/operations/apt.py +16 -18
  54. pyinfra/operations/brew.py +10 -8
  55. pyinfra/operations/bsdinit.py +5 -3
  56. pyinfra/operations/cargo.py +3 -1
  57. pyinfra/operations/choco.py +3 -1
  58. pyinfra/operations/dnf.py +15 -19
  59. pyinfra/operations/files.py +81 -66
  60. pyinfra/operations/gem.py +3 -1
  61. pyinfra/operations/git.py +18 -16
  62. pyinfra/operations/iptables.py +27 -25
  63. pyinfra/operations/launchd.py +5 -6
  64. pyinfra/operations/lxd.py +7 -4
  65. pyinfra/operations/mysql.py +57 -53
  66. pyinfra/operations/npm.py +8 -1
  67. pyinfra/operations/openrc.py +5 -3
  68. pyinfra/operations/pacman.py +4 -5
  69. pyinfra/operations/pip.py +11 -9
  70. pyinfra/operations/pkg.py +3 -1
  71. pyinfra/operations/pkgin.py +3 -1
  72. pyinfra/operations/postgres.py +39 -37
  73. pyinfra/operations/postgresql.py +2 -0
  74. pyinfra/operations/puppet.py +3 -1
  75. pyinfra/operations/python.py +7 -3
  76. pyinfra/operations/selinux.py +42 -16
  77. pyinfra/operations/server.py +48 -43
  78. pyinfra/operations/snap.py +3 -1
  79. pyinfra/operations/ssh.py +12 -10
  80. pyinfra/operations/systemd.py +8 -6
  81. pyinfra/operations/sysvinit.py +6 -4
  82. pyinfra/operations/upstart.py +5 -3
  83. pyinfra/operations/util/files.py +24 -16
  84. pyinfra/operations/util/packaging.py +53 -37
  85. pyinfra/operations/util/service.py +18 -13
  86. pyinfra/operations/vzctl.py +12 -10
  87. pyinfra/operations/xbps.py +3 -1
  88. pyinfra/operations/yum.py +14 -18
  89. pyinfra/operations/zypper.py +8 -9
  90. pyinfra/version.py +5 -2
  91. {pyinfra-3.0b1.dist-info → pyinfra-3.0b2.dist-info}/METADATA +28 -26
  92. pyinfra-3.0b2.dist-info/RECORD +163 -0
  93. {pyinfra-3.0b1.dist-info → pyinfra-3.0b2.dist-info}/WHEEL +1 -1
  94. pyinfra_cli/exceptions.py +0 -5
  95. pyinfra_cli/inventory.py +38 -19
  96. pyinfra_cli/prints.py +15 -11
  97. pyinfra_cli/util.py +3 -1
  98. tests/test_api/test_api_operations.py +1 -1
  99. tests/test_connectors/test_ssh.py +66 -13
  100. tests/test_connectors/test_vagrant.py +3 -3
  101. pyinfra-3.0b1.dist-info/RECORD +0 -163
  102. {pyinfra-3.0b1.dist-info → pyinfra-3.0b2.dist-info}/LICENSE.md +0 -0
  103. {pyinfra-3.0b1.dist-info → pyinfra-3.0b2.dist-info}/entry_points.txt +0 -0
  104. {pyinfra-3.0b1.dist-info → pyinfra-3.0b2.dist-info}/top_level.txt +0 -0
@@ -1,19 +1,29 @@
1
+ from __future__ import annotations
2
+
1
3
  import shlex
2
4
  from collections import defaultdict
3
5
  from io import StringIO
6
+ from typing import Callable
4
7
  from urllib.parse import urlparse
5
8
 
9
+ from pyinfra.api import Host, State
6
10
  from pyinfra.facts.files import File
7
11
  from pyinfra.facts.rpm import RpmPackage
12
+ from pyinfra.operations import files
8
13
 
9
14
 
10
- def _package_name(package):
15
+ def _package_name(package: list[str] | str) -> str:
11
16
  if isinstance(package, list):
12
17
  return package[0]
13
18
  return package
14
19
 
15
20
 
16
- def _has_package(package, packages, expand_package_fact=None, match_any=False):
21
+ def _has_package(
22
+ package: str | list[str],
23
+ packages: dict[str, set[str]],
24
+ expand_package_fact: Callable[[str], list[str | list[str]]] | None = None,
25
+ match_any=False,
26
+ ) -> tuple[bool, dict]:
17
27
  def in_packages(pkg_name, pkg_versions):
18
28
  if not pkg_versions:
19
29
  return pkg_name in packages
@@ -21,9 +31,12 @@ def _has_package(package, packages, expand_package_fact=None, match_any=False):
21
31
  version in packages[pkg_name] for version in pkg_versions
22
32
  )
23
33
 
24
- packages_to_check = [package]
34
+ packages_to_check: list[str | list[str]] = [package]
25
35
  if expand_package_fact:
26
- packages_to_check = expand_package_fact(package) or packages_to_check
36
+ if isinstance(package, list):
37
+ packages_to_check = expand_package_fact(package[0]) or packages_to_check
38
+ else:
39
+ packages_to_check = expand_package_fact(package) or packages_to_check
27
40
 
28
41
  package_name_to_versions = defaultdict(set)
29
42
  for pkg in packages_to_check:
@@ -43,16 +56,16 @@ def _has_package(package, packages, expand_package_fact=None, match_any=False):
43
56
 
44
57
 
45
58
  def ensure_packages(
46
- host,
47
- packages,
48
- current_packages,
49
- present,
50
- install_command,
51
- uninstall_command,
59
+ host: Host,
60
+ packages_to_ensure: str | list[str] | None,
61
+ current_packages: dict[str, set[str]],
62
+ present: bool,
63
+ install_command: str,
64
+ uninstall_command: str,
52
65
  latest=False,
53
- upgrade_command=None,
54
- version_join=None,
55
- expand_package_fact=None,
66
+ upgrade_command: str | None = None,
67
+ version_join: str | None = None,
68
+ expand_package_fact: Callable[[str], list[str | list[str]]] | None = None,
56
69
  ):
57
70
  """
58
71
  Handles this common scenario:
@@ -64,7 +77,7 @@ def ensure_packages(
64
77
  + Optionally upgrades packages w/o specified version when present
65
78
 
66
79
  Args:
67
- packages (list): list of packages or package/versions
80
+ packages_to_ensure (list): list of packages or package/versions
68
81
  current_packages (fact): fact returning dict of package names -> version
69
82
  present (bool): whether packages should exist or not
70
83
  install_command (str): command to prefix to list of packages to install
@@ -73,18 +86,21 @@ def ensure_packages(
73
86
  upgrade_command (str): as above for upgrading
74
87
  version_join (str): the package manager specific "joiner", ie ``=`` for \
75
88
  ``<apt_pkg>=<version>``
89
+ expand_package_fact: fact returning packages providing a capability \
90
+ (ie ``yum whatprovides``)
76
91
  """
77
92
 
78
- if packages is None:
93
+ if packages_to_ensure is None:
79
94
  return
95
+ if isinstance(packages_to_ensure, str):
96
+ packages_to_ensure = [packages_to_ensure]
80
97
 
81
- if isinstance(packages, str):
82
- packages = [packages]
98
+ packages: list[str | list[str]] = packages_to_ensure # type: ignore[assignment]
83
99
 
84
100
  if version_join:
85
101
  packages = [
86
102
  package[0] if len(package) == 1 else package
87
- for package in [package.rsplit(version_join, 1) for package in packages]
103
+ for package in [package.rsplit(version_join, 1) for package in packages] # type: ignore[union-attr] # noqa
88
104
  ]
89
105
 
90
106
  diff_packages = []
@@ -140,7 +156,7 @@ def ensure_packages(
140
156
  command = install_command if present else uninstall_command
141
157
 
142
158
  joined_packages = [
143
- version_join.join(package) if isinstance(package, list) else package
159
+ version_join.join(package) if isinstance(package, list) else package # type: ignore[union-attr] # noqa
144
160
  for package in diff_packages
145
161
  ]
146
162
 
@@ -156,7 +172,7 @@ def ensure_packages(
156
172
  )
157
173
 
158
174
 
159
- def ensure_rpm(state, host, files, source, present, package_manager_command):
175
+ def ensure_rpm(state: State, host: Host, source: str, present: bool, package_manager_command: str):
160
176
  original_source = source
161
177
 
162
178
  # If source is a url
@@ -165,18 +181,18 @@ def ensure_rpm(state, host, files, source, present, package_manager_command):
165
181
  temp_filename = "{0}.rpm".format(host.get_temp_filename(source))
166
182
 
167
183
  # Ensure it's downloaded
168
- yield from files.download._inner(source, temp_filename)
184
+ yield from files.download._inner(src=source, dest=temp_filename)
169
185
 
170
186
  # Override the source with the downloaded file
171
187
  source = temp_filename
172
188
 
173
189
  # Check for file .rpm information
174
- info = host.get_fact(RpmPackage, name=source)
190
+ info = host.get_fact(RpmPackage, package=source)
175
191
  exists = False
176
192
 
177
193
  # We have info!
178
194
  if info:
179
- current_package = host.get_fact(RpmPackage, name=info["name"])
195
+ current_package = host.get_fact(RpmPackage, package=info["name"])
180
196
  if current_package and current_package["version"] == info["version"]:
181
197
  exists = True
182
198
 
@@ -204,18 +220,16 @@ def ensure_rpm(state, host, files, source, present, package_manager_command):
204
220
 
205
221
 
206
222
  def ensure_yum_repo(
207
- state,
208
- host,
209
- files,
210
- name_or_url,
211
- baseurl,
212
- present,
213
- description,
214
- enabled,
215
- gpgcheck,
216
- gpgkey,
223
+ host: Host,
224
+ name_or_url: str,
225
+ baseurl: str | None,
226
+ present: bool,
227
+ description: str | None,
228
+ enabled: bool,
229
+ gpgcheck: bool,
230
+ gpgkey: str | None,
217
231
  repo_directory="/etc/yum.repos.d/",
218
- type_=None,
232
+ type_: str | None = None,
219
233
  ):
220
234
  url = None
221
235
  url_parts = urlparse(name_or_url)
@@ -229,15 +243,17 @@ def ensure_yum_repo(
229
243
 
230
244
  # If we don't want the repo, just remove any existing file
231
245
  if not present:
232
- yield from files.file._inner(filename, present=False)
246
+ yield from files.file._inner(path=filename, present=False)
233
247
  return
234
248
 
235
249
  # If we're a URL, download the repo if it doesn't exist
236
250
  if url:
237
251
  if not host.get_fact(File, path=filename):
238
- yield from files.download._inner(url, filename)
252
+ yield from files.download._inner(src=url, dest=filename)
239
253
  return
240
254
 
255
+ assert isinstance(baseurl, str)
256
+
241
257
  # Description defaults to name
242
258
  description = description or name_or_url
243
259
 
@@ -261,4 +277,4 @@ def ensure_yum_repo(
261
277
  repo_file = StringIO(repo)
262
278
 
263
279
  # Ensure this is the file on the server
264
- yield from files.put._inner(repo_file, filename)
280
+ yield from files.put._inner(src=repo_file, dest=filename)
@@ -1,36 +1,41 @@
1
+ from __future__ import annotations
2
+
3
+ from pyinfra.api import Host
4
+
5
+
1
6
  def handle_service_control(
2
- host,
3
- name,
4
- statuses,
5
- formatter,
6
- running,
7
- restarted,
8
- reloaded,
9
- command,
7
+ host: Host,
8
+ name: str,
9
+ statuses: dict[str, bool],
10
+ formatter: str,
11
+ running: bool | None = None,
12
+ restarted: bool | None = None,
13
+ reloaded: bool | None = None,
14
+ command: str | None = None,
10
15
  status_argument="status",
11
16
  ):
12
- status = statuses.get(name, None)
17
+ is_running = statuses.get(name, None)
13
18
 
14
19
  # Need down but running
15
20
  if running is False:
16
- if status:
21
+ if is_running:
17
22
  yield formatter.format(name, "stop")
18
23
  else:
19
24
  host.noop("service {0} is stopped".format(name))
20
25
 
21
26
  # Need running but down
22
27
  if running is True:
23
- if not status:
28
+ if not is_running:
24
29
  yield formatter.format(name, "start")
25
30
  else:
26
31
  host.noop("service {0} is running".format(name))
27
32
 
28
33
  # Only restart if the service is already running
29
- if restarted and status:
34
+ if restarted and is_running:
30
35
  yield formatter.format(name, "restart")
31
36
 
32
37
  # Only reload if the service is already reloaded
33
- if reloaded and status:
38
+ if reloaded and is_running:
34
39
  yield formatter.format(name, "reload")
35
40
 
36
41
  # Always execute arbitrary commands as these may or may not rely on the service
@@ -2,13 +2,15 @@
2
2
  Manage OpenVZ containers with ``vzctl``.
3
3
  """
4
4
 
5
+ from __future__ import annotations
6
+
5
7
  from pyinfra import host
6
8
  from pyinfra.api import OperationError, operation
7
9
  from pyinfra.facts.vzctl import OpenvzContainers
8
10
 
9
11
 
10
12
  @operation(is_idempotent=False)
11
- def start(ctid, force=False):
13
+ def start(ctid: str, force=False):
12
14
  """
13
15
  Start OpenVZ containers.
14
16
 
@@ -25,7 +27,7 @@ def start(ctid, force=False):
25
27
 
26
28
 
27
29
  @operation(is_idempotent=False)
28
- def stop(ctid):
30
+ def stop(ctid: str):
29
31
  """
30
32
  Stop OpenVZ containers.
31
33
 
@@ -38,7 +40,7 @@ def stop(ctid):
38
40
 
39
41
 
40
42
  @operation(is_idempotent=False)
41
- def restart(ctid, force=False):
43
+ def restart(ctid: str, force=False):
42
44
  """
43
45
  Restart OpenVZ containers.
44
46
 
@@ -46,12 +48,12 @@ def restart(ctid, force=False):
46
48
  + force: whether to force container start
47
49
  """
48
50
 
49
- yield from stop._inner(ctid)
50
- yield from start._inner(ctid, force=force)
51
+ yield from stop._inner(ctid=ctid)
52
+ yield from start._inner(ctid=ctid, force=force)
51
53
 
52
54
 
53
55
  @operation(is_idempotent=False)
54
- def mount(ctid):
56
+ def mount(ctid: str):
55
57
  """
56
58
  Mount OpenVZ container filesystems.
57
59
 
@@ -62,7 +64,7 @@ def mount(ctid):
62
64
 
63
65
 
64
66
  @operation(is_idempotent=False)
65
- def unmount(ctid):
67
+ def unmount(ctid: str):
66
68
  """
67
69
  Unmount OpenVZ container filesystems.
68
70
 
@@ -73,7 +75,7 @@ def unmount(ctid):
73
75
 
74
76
 
75
77
  @operation(is_idempotent=False)
76
- def delete(ctid):
78
+ def delete(ctid: str):
77
79
  """
78
80
  Delete OpenVZ containers.
79
81
 
@@ -84,7 +86,7 @@ def delete(ctid):
84
86
 
85
87
 
86
88
  @operation(is_idempotent=False)
87
- def create(ctid, template=None):
89
+ def create(ctid: str, template: str | None = None):
88
90
  """
89
91
  Create OpenVZ containers.
90
92
 
@@ -107,7 +109,7 @@ def create(ctid, template=None):
107
109
 
108
110
 
109
111
  @operation(is_idempotent=False)
110
- def set(ctid, save=True, **settings):
112
+ def set(ctid: str, save=True, **settings):
111
113
  """
112
114
  Set OpenVZ container details.
113
115
 
@@ -2,6 +2,8 @@
2
2
  Manage XBPS packages and repositories. Note that XBPS package names are case-sensitive.
3
3
  """
4
4
 
5
+ from __future__ import annotations
6
+
5
7
  from pyinfra import host
6
8
  from pyinfra.api import operation
7
9
  from pyinfra.facts.xbps import XbpsPackages
@@ -35,7 +37,7 @@ _update = update._inner # noqa: E305
35
37
 
36
38
  @operation()
37
39
  def packages(
38
- packages=None,
40
+ packages: str | list[str] | None = None,
39
41
  present=True,
40
42
  update=False,
41
43
  upgrade=False,
pyinfra/operations/yum.py CHANGED
@@ -2,16 +2,17 @@
2
2
  Manage yum packages and repositories. Note that yum package names are case-sensitive.
3
3
  """
4
4
 
5
+ from __future__ import annotations
6
+
5
7
  from pyinfra import host, state
6
8
  from pyinfra.api import operation
7
9
  from pyinfra.facts.rpm import RpmPackageProvides, RpmPackages
8
10
 
9
- from . import files
10
11
  from .util.packaging import ensure_packages, ensure_rpm, ensure_yum_repo
11
12
 
12
13
 
13
14
  @operation(is_idempotent=False)
14
- def key(src):
15
+ def key(src: str):
15
16
  """
16
17
  Add yum gpg keys with ``rpm``.
17
18
 
@@ -37,13 +38,13 @@ def key(src):
37
38
 
38
39
  @operation()
39
40
  def repo(
40
- src,
41
+ src: str,
41
42
  present=True,
42
- baseurl=None,
43
- description=None,
43
+ baseurl: str | None = None,
44
+ description: str | None = None,
44
45
  enabled=True,
45
46
  gpgcheck=True,
46
- gpgkey=None,
47
+ gpgkey: str | None = None,
47
48
  ):
48
49
  # NOTE: if updating this docstring also update `dnf.repo`
49
50
  """
@@ -51,7 +52,7 @@ def repo(
51
52
 
52
53
  + src: URL or name for the ``.repo`` file
53
54
  + present: whether the ``.repo`` file should be present
54
- + baseurl: the baseurl of the repo (if ``name`` is not a URL)
55
+ + baseurl: the baseurl of the repo (if ``src`` is not a URL)
55
56
  + description: optional verbose description
56
57
  + enabled: whether this repo is enabled
57
58
  + gpgcheck: whether set ``gpgcheck=1``
@@ -81,9 +82,7 @@ def repo(
81
82
  """
82
83
 
83
84
  yield from ensure_yum_repo(
84
- state,
85
85
  host,
86
- files,
87
86
  src,
88
87
  baseurl,
89
88
  present,
@@ -95,7 +94,7 @@ def repo(
95
94
 
96
95
 
97
96
  @operation()
98
- def rpm(src, present=True):
97
+ def rpm(src: str, present=True):
99
98
  # NOTE: if updating this docstring also update `dnf.rpm`
100
99
  """
101
100
  Add/remove ``.rpm`` file packages.
@@ -118,7 +117,7 @@ def rpm(src, present=True):
118
117
  )
119
118
  """
120
119
 
121
- yield from ensure_rpm(state, host, files, src, present, "yum")
120
+ yield from ensure_rpm(state, host, src, present, "yum")
122
121
 
123
122
 
124
123
  @operation(is_idempotent=False)
@@ -135,14 +134,14 @@ _update = update._inner # noqa: E305 (for use below where update is a kwarg)
135
134
 
136
135
  @operation()
137
136
  def packages(
138
- packages=None,
137
+ packages: str | list[str] | None = None,
139
138
  present=True,
140
139
  latest=False,
141
140
  update=False,
142
141
  clean=False,
143
142
  nobest=False,
144
- extra_install_args=None,
145
- extra_uninstall_args=None,
143
+ extra_install_args: str | None = None,
144
+ extra_uninstall_args: str | None = None,
146
145
  ):
147
146
  """
148
147
  Install/remove/update yum packages & updates.
@@ -207,8 +206,5 @@ def packages(
207
206
  upgrade_command="yum update -y",
208
207
  version_join="=",
209
208
  latest=latest,
210
- expand_package_fact=lambda package: host.get_fact(
211
- RpmPackageProvides,
212
- name=package,
213
- ),
209
+ expand_package_fact=lambda package: host.get_fact(RpmPackageProvides, package=package),
214
210
  )
@@ -1,8 +1,9 @@
1
+ from __future__ import annotations
2
+
1
3
  from pyinfra import host, state
2
4
  from pyinfra.api import operation
3
5
  from pyinfra.facts.rpm import RpmPackages
4
6
 
5
- from . import files
6
7
  from .util.packaging import ensure_packages, ensure_rpm, ensure_yum_repo
7
8
  from .yum import key as yum_key
8
9
 
@@ -56,9 +57,7 @@ def repo(
56
57
  """
57
58
 
58
59
  yield from ensure_yum_repo(
59
- state,
60
60
  host,
61
- files,
62
61
  src,
63
62
  baseurl,
64
63
  present,
@@ -94,7 +93,7 @@ def rpm(src, present=True):
94
93
  )
95
94
  """
96
95
 
97
- yield from ensure_rpm(state, host, files, src, present, "zypper --non-interactive")
96
+ yield from ensure_rpm(state, host, src, present, "zypper --non-interactive")
98
97
 
99
98
 
100
99
  @operation(is_idempotent=False)
@@ -111,15 +110,15 @@ _update = update._inner # noqa: E305 (for use below where update is a kwarg)
111
110
 
112
111
  @operation()
113
112
  def packages(
114
- packages=None,
113
+ packages: str | list[str] | None = None,
115
114
  present=True,
116
115
  latest=False,
117
116
  update=False,
118
117
  clean=False,
119
- extra_global_install_args=None,
120
- extra_install_args=None,
121
- extra_global_uninstall_args=None,
122
- extra_uninstall_args=None,
118
+ extra_global_install_args: str | None = None,
119
+ extra_install_args: str | None = None,
120
+ extra_global_uninstall_args: str | None = None,
121
+ extra_uninstall_args: str | None = None,
123
122
  ):
124
123
  """
125
124
  Install/remove/update zypper packages & updates.
pyinfra/version.py CHANGED
@@ -1,6 +1,9 @@
1
1
  try:
2
- from pkg_resources import get_distribution
2
+ try:
3
+ from importlib_metadata import version
4
+ except ImportError:
5
+ from importlib.metadata import version
3
6
 
4
- __version__ = get_distribution("pyinfra").version
7
+ __version__ = version("pyinfra")
5
8
  except Exception:
6
9
  __version__ = "unknown"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pyinfra
3
- Version: 3.0b1
3
+ Version: 3.0b2
4
4
  Summary: pyinfra automates/provisions/manages/deploys infrastructure.
5
5
  Home-page: https://pyinfra.com
6
6
  Author: Nick / Fizzadar
@@ -16,13 +16,15 @@ Classifier: Intended Audience :: Information Technology
16
16
  Classifier: License :: OSI Approved :: MIT License
17
17
  Classifier: Operating System :: OS Independent
18
18
  Classifier: Programming Language :: Python :: 3
19
- Classifier: Programming Language :: Python :: 3.7
20
19
  Classifier: Programming Language :: Python :: 3.8
21
20
  Classifier: Programming Language :: Python :: 3.9
22
21
  Classifier: Programming Language :: Python :: 3.10
22
+ Classifier: Programming Language :: Python :: 3.11
23
+ Classifier: Programming Language :: Python :: 3.12
23
24
  Classifier: Topic :: System :: Systems Administration
24
25
  Classifier: Topic :: System :: Installation/Setup
25
26
  Classifier: Topic :: Utilities
27
+ Requires-Python: >=3.8
26
28
  Description-Content-Type: text/markdown
27
29
  License-File: LICENSE.md
28
30
  Requires-Dist: gevent >=1.5
@@ -35,17 +37,19 @@ Requires-Dist: configparser
35
37
  Requires-Dist: pywinrm
36
38
  Requires-Dist: typeguard
37
39
  Requires-Dist: distro <2,>=1.6
40
+ Requires-Dist: packaging >=16.1
41
+ Requires-Dist: importlib-metadata >=3.6 ; python_version < "3.10"
38
42
  Requires-Dist: typing-extensions ; python_version < "3.11"
39
43
  Requires-Dist: graphlib-backport ; python_version < "3.9"
40
44
  Provides-Extra: dev
41
- Requires-Dist: pytest ==7.2.0 ; extra == 'dev'
42
- Requires-Dist: coverage ==6.5 ; extra == 'dev'
43
- Requires-Dist: pytest-cov ==4.0.0 ; extra == 'dev'
44
- Requires-Dist: black ==22.3.0 ; extra == 'dev'
45
- Requires-Dist: isort ==5.10.1 ; extra == 'dev'
46
- Requires-Dist: flake8 ==4.0.1 ; extra == 'dev'
47
- Requires-Dist: flake8-black ==0.3.0 ; extra == 'dev'
48
- Requires-Dist: flake8-isort ==4.1.1 ; extra == 'dev'
45
+ Requires-Dist: pytest ==8.2.1 ; extra == 'dev'
46
+ Requires-Dist: coverage ==7.5.1 ; extra == 'dev'
47
+ Requires-Dist: pytest-cov ==5.0.0 ; extra == 'dev'
48
+ Requires-Dist: black ==24.4.2 ; extra == 'dev'
49
+ Requires-Dist: isort ==5.13.2 ; extra == 'dev'
50
+ Requires-Dist: flake8 ==7.0.0 ; extra == 'dev'
51
+ Requires-Dist: flake8-black ==0.3.6 ; extra == 'dev'
52
+ Requires-Dist: flake8-isort ==6.1.1 ; extra == 'dev'
49
53
  Requires-Dist: mypy ; extra == 'dev'
50
54
  Requires-Dist: types-cryptography ; extra == 'dev'
51
55
  Requires-Dist: types-paramiko ; extra == 'dev'
@@ -67,14 +71,14 @@ Requires-Dist: pyinfra-guzzle-sphinx-theme ==0.15 ; extra == 'docs'
67
71
  Requires-Dist: myst-parser ==2.0.0 ; extra == 'docs'
68
72
  Requires-Dist: sphinx ==6.2.1 ; extra == 'docs'
69
73
  Provides-Extra: test
70
- Requires-Dist: pytest ==7.2.0 ; extra == 'test'
71
- Requires-Dist: coverage ==6.5 ; extra == 'test'
72
- Requires-Dist: pytest-cov ==4.0.0 ; extra == 'test'
73
- Requires-Dist: black ==22.3.0 ; extra == 'test'
74
- Requires-Dist: isort ==5.10.1 ; extra == 'test'
75
- Requires-Dist: flake8 ==4.0.1 ; extra == 'test'
76
- Requires-Dist: flake8-black ==0.3.0 ; extra == 'test'
77
- Requires-Dist: flake8-isort ==4.1.1 ; extra == 'test'
74
+ Requires-Dist: pytest ==8.2.1 ; extra == 'test'
75
+ Requires-Dist: coverage ==7.5.1 ; extra == 'test'
76
+ Requires-Dist: pytest-cov ==5.0.0 ; extra == 'test'
77
+ Requires-Dist: black ==24.4.2 ; extra == 'test'
78
+ Requires-Dist: isort ==5.13.2 ; extra == 'test'
79
+ Requires-Dist: flake8 ==7.0.0 ; extra == 'test'
80
+ Requires-Dist: flake8-black ==0.3.6 ; extra == 'test'
81
+ Requires-Dist: flake8-isort ==6.1.1 ; extra == 'test'
78
82
  Requires-Dist: mypy ; extra == 'test'
79
83
  Requires-Dist: types-cryptography ; extra == 'test'
80
84
  Requires-Dist: types-paramiko ; extra == 'test'
@@ -98,19 +102,17 @@ Requires-Dist: types-setuptools ; extra == 'test'
98
102
 
99
103
  ---
100
104
 
101
- <p>
102
- <a href="https://docs.pyinfra.com"><strong>Documentation</strong></a> &rArr;
105
+ <h3>
103
106
  <a href="https://docs.pyinfra.com/page/getting-started.html"><strong>Getting Started</strong></a> &bull;
104
- <a href="https://docs.pyinfra.com/page/examples.html"><strong>Examples</strong></a> &bull;
107
+ <a href="https://github.com/pyinfra-dev/pyinfra-examples"><strong>Examples Repo</strong></a> &bull;
108
+ <a href="https://matrix.to/#/#pyinfra:matrix.org"><strong>Chat on Matrix</strong></a>
109
+ </h3>
110
+ <p>
111
+ <a href="https://docs.pyinfra.com"><strong>Documentation</strong></a> &bull;
105
112
  <a href="https://docs.pyinfra.com/page/support.html"><strong>Help & Support</strong></a> &bull;
106
113
  <a href="https://docs.pyinfra.com/page/contributing.html"><strong>Contributing</strong></a>
107
114
  </p>
108
115
 
109
- <p>
110
- Chat &rArr;
111
- <a href="https://matrix.to/#/#pyinfra:matrix.org"><strong><code>#pyinfra</code> on Matrix</strong></a>
112
- </p>
113
-
114
116
  ---
115
117
 
116
118
  Why pyinfra? Design features include: