pyinfra 3.0b1__py2.py3-none-any.whl → 3.0b3__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 (108) 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 +18 -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/runit.py +68 -0
  44. pyinfra/facts/server.py +10 -13
  45. pyinfra/facts/snap.py +2 -0
  46. pyinfra/facts/systemd.py +2 -0
  47. pyinfra/facts/upstart.py +2 -0
  48. pyinfra/facts/util/packaging.py +3 -2
  49. pyinfra/facts/vzctl.py +2 -0
  50. pyinfra/facts/xbps.py +2 -0
  51. pyinfra/facts/yum.py +2 -0
  52. pyinfra/facts/zypper.py +2 -0
  53. pyinfra/operations/apk.py +3 -1
  54. pyinfra/operations/apt.py +16 -18
  55. pyinfra/operations/brew.py +10 -8
  56. pyinfra/operations/bsdinit.py +5 -3
  57. pyinfra/operations/cargo.py +3 -1
  58. pyinfra/operations/choco.py +3 -1
  59. pyinfra/operations/dnf.py +15 -19
  60. pyinfra/operations/docker.py +339 -0
  61. pyinfra/operations/files.py +81 -66
  62. pyinfra/operations/gem.py +3 -1
  63. pyinfra/operations/git.py +18 -16
  64. pyinfra/operations/iptables.py +27 -25
  65. pyinfra/operations/launchd.py +5 -6
  66. pyinfra/operations/lxd.py +7 -4
  67. pyinfra/operations/mysql.py +57 -53
  68. pyinfra/operations/npm.py +8 -1
  69. pyinfra/operations/openrc.py +5 -3
  70. pyinfra/operations/pacman.py +4 -5
  71. pyinfra/operations/pip.py +11 -9
  72. pyinfra/operations/pkg.py +3 -1
  73. pyinfra/operations/pkgin.py +3 -1
  74. pyinfra/operations/postgres.py +39 -37
  75. pyinfra/operations/postgresql.py +2 -0
  76. pyinfra/operations/puppet.py +3 -1
  77. pyinfra/operations/python.py +7 -3
  78. pyinfra/operations/runit.py +182 -0
  79. pyinfra/operations/selinux.py +42 -16
  80. pyinfra/operations/server.py +52 -43
  81. pyinfra/operations/snap.py +3 -1
  82. pyinfra/operations/ssh.py +12 -10
  83. pyinfra/operations/systemd.py +12 -8
  84. pyinfra/operations/sysvinit.py +6 -4
  85. pyinfra/operations/upstart.py +5 -3
  86. pyinfra/operations/util/docker.py +177 -0
  87. pyinfra/operations/util/files.py +24 -16
  88. pyinfra/operations/util/packaging.py +53 -37
  89. pyinfra/operations/util/service.py +25 -18
  90. pyinfra/operations/vzctl.py +12 -10
  91. pyinfra/operations/xbps.py +3 -1
  92. pyinfra/operations/yum.py +14 -18
  93. pyinfra/operations/zypper.py +8 -9
  94. pyinfra/version.py +5 -2
  95. {pyinfra-3.0b1.dist-info → pyinfra-3.0b3.dist-info}/METADATA +30 -28
  96. pyinfra-3.0b3.dist-info/RECORD +167 -0
  97. {pyinfra-3.0b1.dist-info → pyinfra-3.0b3.dist-info}/WHEEL +1 -1
  98. pyinfra_cli/exceptions.py +0 -5
  99. pyinfra_cli/inventory.py +38 -19
  100. pyinfra_cli/prints.py +15 -11
  101. pyinfra_cli/util.py +3 -1
  102. tests/test_api/test_api_operations.py +1 -1
  103. tests/test_connectors/test_ssh.py +66 -13
  104. tests/test_connectors/test_vagrant.py +3 -3
  105. pyinfra-3.0b1.dist-info/RECORD +0 -163
  106. {pyinfra-3.0b1.dist-info → pyinfra-3.0b3.dist-info}/LICENSE.md +0 -0
  107. {pyinfra-3.0b1.dist-info → pyinfra-3.0b3.dist-info}/entry_points.txt +0 -0
  108. {pyinfra-3.0b1.dist-info → pyinfra-3.0b3.dist-info}/top_level.txt +0 -0
@@ -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.0b3
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,24 +37,26 @@ 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'
52
56
  Requires-Dist: types-python-dateutil ; extra == 'dev'
53
57
  Requires-Dist: types-PyYAML ; extra == 'dev'
54
58
  Requires-Dist: types-setuptools ; extra == 'dev'
55
- Requires-Dist: pyinfra-guzzle-sphinx-theme ==0.15 ; extra == 'dev'
59
+ Requires-Dist: pyinfra-guzzle-sphinx-theme ==0.16 ; extra == 'dev'
56
60
  Requires-Dist: myst-parser ==2.0.0 ; extra == 'dev'
57
61
  Requires-Dist: sphinx ==6.2.1 ; extra == 'dev'
58
62
  Requires-Dist: wheel ; extra == 'dev'
@@ -63,18 +67,18 @@ Requires-Dist: ipdbplugin ; extra == 'dev'
63
67
  Requires-Dist: flake8-spellcheck ==0.12.1 ; extra == 'dev'
64
68
  Requires-Dist: redbaron ; extra == 'dev'
65
69
  Provides-Extra: docs
66
- Requires-Dist: pyinfra-guzzle-sphinx-theme ==0.15 ; extra == 'docs'
70
+ Requires-Dist: pyinfra-guzzle-sphinx-theme ==0.16 ; 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:
@@ -0,0 +1,167 @@
1
+ pyinfra/__init__.py,sha256=7ZcKHGWk7_nYxsYrbFBB_vJr-J-Ddbc56ZS4sk5ArVw,535
2
+ pyinfra/__main__.py,sha256=aVd00glLz5CMJGXgt1XxbOvC2HluqaowoTOjxgIpBaA,47
3
+ pyinfra/context.py,sha256=S6DvGjjTEjM4u2m9oIAmAaV7kXIJzVwYf725P1muIuY,3395
4
+ pyinfra/local.py,sha256=0bpIRCyDKM6i_jA1i8Ej2qr_iWIF9cUYWutXNdLj8po,2751
5
+ pyinfra/progress.py,sha256=X3hXZ4Flh_L9FE4ZEWxWoG0R4dA5UPd1FCO-Exd5Xtc,4193
6
+ pyinfra/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
+ pyinfra/version.py,sha256=LZf50PHDzEZv65w0G-iMICoQ9US0U5LWHAOEmNtkF3I,216
8
+ pyinfra/api/__init__.py,sha256=suGbKKM-qCduuXFYBEcyswlTqozewtYpdLRhK63PVn0,942
9
+ pyinfra/api/arguments.py,sha256=8BhuJiljFJzaCi9lM8HoEBB9mcnCBilv4Zwdx_349g8,9941
10
+ pyinfra/api/arguments_typed.py,sha256=WQKr0wDtlgJGq-Vkv_oPAz7f-LxjqQv3wJCdvVrePWk,2331
11
+ pyinfra/api/command.py,sha256=SyUlxvhYlXpgFpg0jua8bzQ2KPtVYQXHcvD6AUL2SCI,7226
12
+ pyinfra/api/config.py,sha256=wS6Pi4T4DxNkzO4llNY-ghLxyI5VBJ26uGvgMPZxIKY,9043
13
+ pyinfra/api/connect.py,sha256=Z9wusMLR_jBkKKk5D4AUOj8LHl3H5MsNO5FxAeR4jac,1416
14
+ pyinfra/api/connectors.py,sha256=nie7JuLxMSC6gqPjmjuCisQ11R-eAQDtMMWF6YbSQ48,659
15
+ pyinfra/api/deploy.py,sha256=xo4F7URUf3xzIChRHZn4zwqs_WTjLjZNC9i9eQjAFk8,2756
16
+ pyinfra/api/exceptions.py,sha256=cCbUp1qN1QO0d9aAvOAbRgYpLi0vUI5j7ZqSjcD1_P8,1861
17
+ pyinfra/api/facts.py,sha256=L_Wsrdq-u0zR69klnXWZ_2j9H7m3Oto53X0bQf670X8,10574
18
+ pyinfra/api/host.py,sha256=3lRhlZDRKvCNvpziaTglExy2Ep1wd4YdmGDNY4emAdA,13466
19
+ pyinfra/api/inventory.py,sha256=nPITdNEJ7q71adIqS_OKHsMjD7amUuHEuTl6xzgh1Gk,7734
20
+ pyinfra/api/operation.py,sha256=pB0LpjUqbMLGtoDnsckNw0FRoeo1BopL0fnXVDM1JyU,15112
21
+ pyinfra/api/operations.py,sha256=jvz9ISfwmQnAQVUKLnbrRdD9QHIAAfypo9l5b3fYG1w,10894
22
+ pyinfra/api/state.py,sha256=3dXRjeZJXnzLcbP9E4aogkRPwIg3_kK1h4Tf4FVZock,12622
23
+ pyinfra/api/util.py,sha256=vesFOxExETb-B-oAhWpJJrmALTubg3fkFqi0gYd0pJs,12265
24
+ pyinfra/connectors/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
25
+ pyinfra/connectors/base.py,sha256=2fASiV-MvpXgcZAFLM_PUwYx5ax6EHai44ri_oEKeSE,3732
26
+ pyinfra/connectors/chroot.py,sha256=Xd72I8T58KIwKOoc0LXCw91AoEIaiHfRLDcDVTHGJ0o,5931
27
+ pyinfra/connectors/docker.py,sha256=2UNHhXS4hpLo7I19ixDeSd7JR8SNo43VgqsaUIZQZJ4,8741
28
+ pyinfra/connectors/dockerssh.py,sha256=VWHY--jqs3yf-RuPUZXav4vLeON9SzoVC9CUyOJo1rg,8919
29
+ pyinfra/connectors/local.py,sha256=vYOBQS_5rf-dVaPeG4dJlLwBHqkxAzLjj3aDEgbAsx8,6900
30
+ pyinfra/connectors/ssh.py,sha256=ESCZwehJ0Ve6gkjbqGTJrNEGZlu3ItjKLMkmCWq-Z3Y,20989
31
+ pyinfra/connectors/ssh_util.py,sha256=CN_5AdTA3RpiWCnXTrRBjez1NsN59hITDzQmXIkZvoE,3683
32
+ pyinfra/connectors/terraform.py,sha256=G7lK168Fz0jNFetc_7_bPT-RnoaRDksJat0R26fqkUk,3617
33
+ pyinfra/connectors/util.py,sha256=0bvoMsGMD-Tbfaer8NUhWJjBnaNKdmE83PDg48BYjcU,11374
34
+ pyinfra/connectors/vagrant.py,sha256=oEeRglzRmemRXW3vilsp_Xg9qnZMRprRJO9fd_C-f5M,4759
35
+ pyinfra/connectors/sshuserclient/__init__.py,sha256=Qc4RO2wknSWIiNTwOeQ0y2TeiuKHmyWDW2Dz4MOo9CE,44
36
+ pyinfra/connectors/sshuserclient/client.py,sha256=7YSd3QckZuPDRnKzy2FfG3J8zp7CY-jny8tbWwxvKro,9720
37
+ pyinfra/connectors/sshuserclient/config.py,sha256=UMwkvTgAIS7__re6Wz_pwH6EU4kO1-uMQ5zuFakH0v4,2721
38
+ pyinfra/facts/__init__.py,sha256=myTXSOZmAqmU88Fyifn035h9Lr6Gj2mlka_jDcXyKGw,347
39
+ pyinfra/facts/apk.py,sha256=zihlHc6BbBUNQRL3v6wVFUHypfIL7wC6CPLrp4yynHo,518
40
+ pyinfra/facts/apt.py,sha256=8BJX79dBM9t3ceOhP_B5-I008HEJAUj_ijKDVvSxbFo,2035
41
+ pyinfra/facts/brew.py,sha256=aG77URXfNYT50ZpeHyyByiiX08GR6Oz6L0M3UMf9ztI,2302
42
+ pyinfra/facts/bsdinit.py,sha256=KyX4gc8cXKNn3O_NAlKWvEDKvMCnkTWJQg61oTV9ZN0,526
43
+ pyinfra/facts/cargo.py,sha256=mHtT2Yxoqx_g0akDq6jkHFN5VWNHQu70vKvNLZ10-b8,567
44
+ pyinfra/facts/choco.py,sha256=Tf7_DuQY0eZ4SIxV0rlyulrBCg7A0qyPbtTcHgkVP_0,739
45
+ pyinfra/facts/deb.py,sha256=dy5PKdQqy1oLdCUd6iTxCa6yG8agsaxZrPVsjvlDi74,1756
46
+ pyinfra/facts/dnf.py,sha256=7YNicP8EbRvWJQKU0OcwcW3bnIxx9GJ1Fy4qdCFnI0Y,898
47
+ pyinfra/facts/docker.py,sha256=Vr0rIEXSpK33yc2dDGct2lKhPQamvKEztxIAfwN0sk0,2046
48
+ pyinfra/facts/files.py,sha256=ki9-NQnYyt1VzuqKwEOYpX1nz5gJ_ph-ruq-4DS1VLg,11511
49
+ pyinfra/facts/gem.py,sha256=U1oF32LeiBo3ruaFm6hfF3XwNmgyhqamFUAeGn4cD3k,509
50
+ pyinfra/facts/git.py,sha256=rk4NS2SQJiosI6eY2eCy_p9kOP4O8UARRjFi16ObE2w,1294
51
+ pyinfra/facts/gpg.py,sha256=T5yVc_X9BLrDc77Yjk69x9SnP0qRWnKYEpi4JU__pKo,3765
52
+ pyinfra/facts/hardware.py,sha256=je1KjLfr4t-QZxTYei-V3Xqpll4TjbNeQxlHUvADg-c,11877
53
+ pyinfra/facts/iptables.py,sha256=sUkywfHZUXnMZF_KshAnyJufrJvZ9fBYnERSRbwOCRE,3374
54
+ pyinfra/facts/launchd.py,sha256=xjkszKmi9XNkovp7J33WTV19XfQbc5xGJkIBbFRTRhE,704
55
+ pyinfra/facts/lxd.py,sha256=ymBb_SdHbfAlx_tQyRPVa1ij_e68ZDODg1id1E0V8Rg,373
56
+ pyinfra/facts/mysql.py,sha256=0tpNks5be_mBWzIxuEqOyQ9MTYD9rRjeC3Oc_MQ2nns,6038
57
+ pyinfra/facts/npm.py,sha256=l_61BmbAWrO9RlYKUzLUcgicJ4RCMZHD70alrngC7-M,709
58
+ pyinfra/facts/openrc.py,sha256=NitG8BkwUCBrn-3SqM3FDiP4r6tAQTAWuHXTm1-3WGM,1386
59
+ pyinfra/facts/pacman.py,sha256=lU8IQYpQI3tzxRvKZHJD8giM_n17D5abzxIPasbII-A,1070
60
+ pyinfra/facts/pip.py,sha256=ORyrVxu_-8eIr0uSCkI6x4MH-sorDEavml4aozcdrOA,738
61
+ pyinfra/facts/pkg.py,sha256=2N-NlY_f3eQaW3dxCGKaKvu_ymC5_EF0-KASeul0EJc,488
62
+ pyinfra/facts/pkgin.py,sha256=Q1q7m4CCs_na92dDdQIjTuQnJ3axYv5qUdxnAy7e_XY,517
63
+ pyinfra/facts/postgres.py,sha256=M7ppmVvUXy8HSNPqrc8zLPyt8JamAyGs2IO2ocbzSZ8,4187
64
+ pyinfra/facts/postgresql.py,sha256=4nusMVvGhtku86KX4O4vjSxh_MamxZy_kmTQvvy0GhE,223
65
+ pyinfra/facts/rpm.py,sha256=v9OCfTlTSqs4UQWDwnt2tVJkqHOmHZvj7Cd1g4mZ3WI,2091
66
+ pyinfra/facts/runit.py,sha256=uqwftOBmjWma09hNhIZ9ZF2QqqgdcA5NzrbBtP95lRM,1965
67
+ pyinfra/facts/selinux.py,sha256=N0zbJrAtBeRBtxZFUHbYTLQ2L4mRV7_Oj3Cj3OA1Npw,4272
68
+ pyinfra/facts/server.py,sha256=ocUPIIveHWfe4K4-7mt7Je7TswWbKmjdu1xAF2VxaD8,19798
69
+ pyinfra/facts/snap.py,sha256=MnZDllRZ1JKLw0SKRFQ1tI6Wi05gvipQPo7m4gpL4fI,1946
70
+ pyinfra/facts/systemd.py,sha256=7uYJyP9yryq9PZT0lRH597HHQFExxebz8og2OrRQUc8,3963
71
+ pyinfra/facts/sysvinit.py,sha256=PS7yMOrVxclywKjF3BIXmxTBgn2_vpSTQrDeOly_j8Q,1490
72
+ pyinfra/facts/upstart.py,sha256=4OSQ257KmYvWWboeXiqKGbhvOmLCMCwwOBgDXKCq1XE,579
73
+ pyinfra/facts/vzctl.py,sha256=LoWXJdFVg7bWcY-aGvSk-teFaAjUjKzQHnR-VuaomZ8,627
74
+ pyinfra/facts/xbps.py,sha256=k7G0L_IgOWIQUs-UswVgs3WzqdjokSCzq0TKT3Tvok0,517
75
+ pyinfra/facts/yum.py,sha256=5nhp7iXLFyEM7MSrBqierSQpTzqyBOwMB-e658Fe838,863
76
+ pyinfra/facts/zypper.py,sha256=hCgm37xwVqgrsG6h2FMNnzW17UH64y8qZbDOVrLglIY,802
77
+ pyinfra/facts/util/__init__.py,sha256=f7HKu8z9_yFC899ajJ3RFiyivioaZeGfOI6nf9GviCs,521
78
+ pyinfra/facts/util/databases.py,sha256=EphGQApzRBXI2nG1FL9h8bozY-o4SgdQgpv9YcnCkxs,730
79
+ pyinfra/facts/util/packaging.py,sha256=4RzjDYb3HrRWZuuPlEfYHgbftLH4r1FOccN5QyIGkrk,1181
80
+ pyinfra/facts/util/win_files.py,sha256=S_IQ5kJD6ZgkEcVHajgh7BIMolLV-1q1ghIcwAS-E1Q,2561
81
+ pyinfra/operations/__init__.py,sha256=SOcW337KXIzD_LH-iJJfq14BQcCs5JzwswJ0PIzDgF4,357
82
+ pyinfra/operations/apk.py,sha256=_0vOjbSiGx6EWv9rvTmQdGnRZQ_NA_Dyd3QW1cTzFgI,2111
83
+ pyinfra/operations/apt.py,sha256=TGNO-ovc24v0T5pBzweB68Z3Hd_130sauGsmNzcXyJI,13663
84
+ pyinfra/operations/brew.py,sha256=aghLE4qyuhhRbt6fgSPV6_5fyWgTohA77Dc0gol19UU,5155
85
+ pyinfra/operations/bsdinit.py,sha256=okQUQDr2H8Z-cAdfdbPJiuGujsHLuV5gpuMZ1UlICEM,1648
86
+ pyinfra/operations/cargo.py,sha256=mXWd6pb0IR6kzJMmPHwXZN-VJ-B_y8AdOFlrRzDQOZI,1104
87
+ pyinfra/operations/choco.py,sha256=8nG0wc1tZEA0L0HTIjgR00IDiONARokyzHyKj-R3xmo,1515
88
+ pyinfra/operations/dnf.py,sha256=3154Rer6dejVB1AK-CqyJhpMVn_djaSDJrVMs62GNcE,5599
89
+ pyinfra/operations/docker.py,sha256=Mra-m2iayXkc2LgCk2tuE6M7lZHhOGNJD3WQIPM9t2I,8396
90
+ pyinfra/operations/files.py,sha256=9O_HKgmVD_z74jtSivY4pKBPrCDKKHDSy0jAB9QERHU,53639
91
+ pyinfra/operations/gem.py,sha256=2C85sOwIRMHGvmPg4uAlUVf6MokhiA7LLPqzdJRHsBg,1132
92
+ pyinfra/operations/git.py,sha256=b26tQF_4hykTy0FtxiuCkqPk9i8JdZaz-RBhH4X96yw,11789
93
+ pyinfra/operations/iptables.py,sha256=brYa4kMhZKFTu24BNds_1b6sOaG94EfqWEoWrScx-Ck,9341
94
+ pyinfra/operations/launchd.py,sha256=6HWvqoQ74idV_NStOEmFXwu0dmTv7YDvFtsK8An2Lu4,1177
95
+ pyinfra/operations/lxd.py,sha256=bKm9gsgZaruKYSL7OYFMiou-wGP4BzwIMWzjW4AZYrk,1742
96
+ pyinfra/operations/mysql.py,sha256=QcYvEQDlPESzDDoJ-HFwJFzN7ftsbsP892LMRZrmaLQ,19873
97
+ pyinfra/operations/npm.py,sha256=bUmfQsClZ2YcHiihiC7k5widIXIi6lbfx_32iyaAKfo,1499
98
+ pyinfra/operations/openrc.py,sha256=GXFoCHEEKeyQyRvrZcNYx8og4fmgmtzTVAViBzt84TE,1580
99
+ pyinfra/operations/pacman.py,sha256=QMjmsBiiw362nhZY0rEDVQL5A32MG3u7GcmX4q4PzfI,1702
100
+ pyinfra/operations/pip.py,sha256=7PpQvZHnwBGZ60V5b0XKNR4tHLW0MXJo6_6UX7HBtGY,5856
101
+ pyinfra/operations/pkg.py,sha256=rORQBbKeb-6gS0LYu0a0VdiWcDZoovcUONCaf6KMdeQ,2298
102
+ pyinfra/operations/pkgin.py,sha256=zhUyGzKjnUfGoyHbMoYMbeeMzcsiOUpBz1zIzppigJ0,1992
103
+ pyinfra/operations/postgres.py,sha256=LRoedDevQqiM5eX5Lmzb5mr_E9Od0ROVC0j18ZqaR0w,9661
104
+ pyinfra/operations/postgresql.py,sha256=agZjL2W4yxigk9ThIC0V_3wvmcWVdX308aJO24WkN6g,833
105
+ pyinfra/operations/puppet.py,sha256=eDe8D9jQbHYQ4_r4-dmEZfMASKQvj36BR8z_h8aDfw8,861
106
+ pyinfra/operations/python.py,sha256=u569cdPrPesrmzU09nwIPA3bk6TZ-Qv2QP0lJLcO_bw,2021
107
+ pyinfra/operations/runit.py,sha256=jRR5kt1OUCLbYktnu7yl3YvSiTW51VvEvOuB0yfd7Ww,5126
108
+ pyinfra/operations/selinux.py,sha256=khqWJsr9MOTyZmxP9P4dQ_7KUNlAfo5fx3Nv7kWm49w,5961
109
+ pyinfra/operations/server.py,sha256=wc5pNDQzEiwl9XEz1cG1m-51z1TV-5P39eMvSig90tY,36414
110
+ pyinfra/operations/snap.py,sha256=a-QtNE4Dlsavqq425TUIwpEJu4oGw8UlLRkdTFyT1F8,3049
111
+ pyinfra/operations/ssh.py,sha256=wocoaYDlOhhItItAVQCEfnVowTtkg3AP0hQ3mnpUnl0,5634
112
+ pyinfra/operations/systemd.py,sha256=hPHTjASj6N_fRAzLr3DNHnxxIbiiTIIT9UStSxKDkTk,3984
113
+ pyinfra/operations/sysvinit.py,sha256=WzzthkmWL46MNNY6LsBZ90e37yPj0w2QyUtEAlGBwqY,4078
114
+ pyinfra/operations/upstart.py,sha256=pHb9RGnVhT14A_y6OezfOH-lmniKpiyJqpeoOJl0beE,1978
115
+ pyinfra/operations/vzctl.py,sha256=2u2CDkuDjzHBRQ54HfyfLpLrsbT8U7_05EEjbbhKUiU,3110
116
+ pyinfra/operations/xbps.py,sha256=ru3_srMBUyUXGzAsPo7WwoomfM0AeDglFv8CDqB33B0,1508
117
+ pyinfra/operations/yum.py,sha256=Ig7AzQy1C7I8XM37lWbw0nI5lzFGMoX30P8FV8-V5uA,5600
118
+ pyinfra/operations/zypper.py,sha256=z1CWv2uwWBlCLIhHna7U5DojVoKZYoUYpezJ_FM_xK8,5555
119
+ pyinfra/operations/util/__init__.py,sha256=ZAHjeCXtLo0TIOSfZ9h0Sh5IXXRCspfHs3RR1l8tQCE,366
120
+ pyinfra/operations/util/docker.py,sha256=6CvQgeFAXH_lDqKb7RxWpMvlCDwEAXlBaDZoJ8LxrYg,4596
121
+ pyinfra/operations/util/files.py,sha256=Zcet3ydNVbdT9jss0BDm6RJFyR_s6XTr0isDR60Zubw,3622
122
+ pyinfra/operations/util/packaging.py,sha256=xFtOlEX46ms7g3gDvOOInRVR1RVfgsmhLzFzsJAL_eU,9381
123
+ pyinfra/operations/util/service.py,sha256=kJd1zj4-sAaGIp5Ts7yAJznogWaGr8oQTztwenLAr7Y,1309
124
+ pyinfra_cli/__init__.py,sha256=G0X7tNdqT45uWuK3aHIKxMdDeCgJ7zHo6vbxoG6zy_8,284
125
+ pyinfra_cli/__main__.py,sha256=8tjq8HUll8P8naFw7pGlygwSz7u9je_MQ-0pqcDlENY,881
126
+ pyinfra_cli/commands.py,sha256=J-mCJYvDebJ8M7o3HreB2zToa871-xO6_KjVhPLeHho,1832
127
+ pyinfra_cli/exceptions.py,sha256=iptx9Zj1od7VgSbOyXs7P8tD4zAZ_fwrQFKPlpPrfS0,4806
128
+ pyinfra_cli/inventory.py,sha256=lggXV9blVqNDT2lgVkq9FQWqYBPOakoLYLbuuVQ8upE,10179
129
+ pyinfra_cli/log.py,sha256=7WEGtmf3ncF1BtXL2icUjyxeRKy-7XrCcQ2Hg4GWX5Y,2201
130
+ pyinfra_cli/main.py,sha256=MsBn0RCD5ce4GY-dDBe6vLXT0LanDrrQZpJOTIYZPBs,19715
131
+ pyinfra_cli/prints.py,sha256=za6V-yjXf-LViBW73qWcyfsajCUnf0NCG-7K0ugOA0k,9170
132
+ pyinfra_cli/util.py,sha256=f3iGIPxlUiQJ5LmUGYbEz0QrySQAKmf9xov9WvHXbrk,6364
133
+ pyinfra_cli/virtualenv.py,sha256=6j9W54JkQLN02SrZZIVwszp0GxlaaDEUWFZjBDHIWNA,2466
134
+ tests/test_api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
135
+ tests/test_api/test_api.py,sha256=Ig2ebkNACYbHcC4_zRkxS9vj5ZEogoPqGx30ErIKChg,2413
136
+ tests/test_api/test_api_arguments.py,sha256=5k7w0_x5cnABEFOk0LQBCt5gU9iTN9lo2XS6MlJTnhQ,1961
137
+ tests/test_api/test_api_command.py,sha256=OW0ESMyS5vo38u17DHeCrSIaIkW9gMU5PSkXL7mRrq0,3204
138
+ tests/test_api/test_api_config.py,sha256=bf0mDrUie3On6zGC_hJBpv-wvSf3LHBIBzUDvkopEt0,708
139
+ tests/test_api/test_api_deploys.py,sha256=h_zbI6CK4K8SdzEr3LEAMPxOf9hnQBdi_suqiNPqHHQ,4200
140
+ tests/test_api/test_api_facts.py,sha256=fUPadZbZ5xaKSF-kmLj7XGwsNiBmfj7Av0gl8fE01Qc,10687
141
+ tests/test_api/test_api_host.py,sha256=U_VW2vTl35vR8EdyIGMKr4y0ydsDLbvHSjZDa99CyNE,1119
142
+ tests/test_api/test_api_inventory.py,sha256=VLbV0MXdRLOPvTXJF156ne6rAx1cBlFfgq_1S79s4tw,2013
143
+ tests/test_api/test_api_operations.py,sha256=GUfnuHK2NoTAGdOT4AbytT9R8i3ZZIvGP7KBfoYcYUQ,20134
144
+ tests/test_api/test_api_util.py,sha256=uHv4oLpoy1_tzOoqFA1zpdvC74SvjitZbxQwp0dmjTs,1716
145
+ tests/test_cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
146
+ tests/test_cli/test_cli.py,sha256=nZQH0zK1SOgIr5VxBuuHH68hyzG4lhwyw_Z7EhjPtf4,6045
147
+ tests/test_cli/test_cli_deploy.py,sha256=KBnnDsiD21h7t1S2JXpEDpiMxh0AFqwxaEl0z78IE9E,4858
148
+ tests/test_cli/test_cli_exceptions.py,sha256=02sjC6rMptuqchgcdjdsVNQbSQYW6HwGutSy6Q6sMs4,3088
149
+ tests/test_cli/test_cli_util.py,sha256=-Ehnj0cO-EkF-6KLxcPPcFeuAUMTz-fKITrxhuiYhV4,2562
150
+ tests/test_cli/test_context_objects.py,sha256=JiUTwQP7yvcqA47Kq9jtdsB_Z8nxGMZN46d9pR--FYA,2130
151
+ tests/test_cli/util.py,sha256=kp_-XsGnTyDgG6IHWorYzl5VD_WLe77dKOH007TDOUE,338
152
+ tests/test_connectors/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
153
+ tests/test_connectors/test_chroot.py,sha256=QK7YgFPXzHh8y363-tmHvzZ0Ok5PVJWFTDAvwt91eac,5907
154
+ tests/test_connectors/test_docker.py,sha256=0EjkfhCHpLCfL4X-AIdMNw5ASaseY0tbRAn7T_TAkMQ,6566
155
+ tests/test_connectors/test_dockerssh.py,sha256=MaC9IK1OZDiqoIsuLOZBJnPDglsMoPDoL19LQtXsyCE,9303
156
+ tests/test_connectors/test_local.py,sha256=N_FkejDZKu7XLnKeApqfBARYMyxf-hRXCQJrXLHvwRg,7442
157
+ tests/test_connectors/test_ssh.py,sha256=zYL0FbRXzqkYJslhmVeUgSkcHtozhmvZfRcaqDrYKvI,40386
158
+ tests/test_connectors/test_sshuserclient.py,sha256=2PQNLPhNL6lBACc6tQuXmPoog-9L6AdDQNrA-rEw1_8,5734
159
+ tests/test_connectors/test_terraform.py,sha256=Z5MhgDeRDFumu-GlbjMD0ZRkecwBIPP8C8ZVg-mq7C8,3743
160
+ tests/test_connectors/test_util.py,sha256=hQir0WyjH0LEF6xvIyHNyqdI5pkJX6qUR9287MgO2bY,4647
161
+ tests/test_connectors/test_vagrant.py,sha256=27qRB7ftjEPaj4ejBNZ-rR4Ou1AD1VyVcf2XjwZPG3M,3640
162
+ pyinfra-3.0b3.dist-info/LICENSE.md,sha256=gwC95tUll0gwB32tHNkTAasN7Sb6vjWzXa305NwClbI,1076
163
+ pyinfra-3.0b3.dist-info/METADATA,sha256=vrU3Af4J_l5fK66Ajl_i5zXpSs7r5LetayqwCEydkb4,8322
164
+ pyinfra-3.0b3.dist-info/WHEEL,sha256=DZajD4pwLWue70CAfc7YaxT1wLUciNBvN_TTcvXpltE,110
165
+ pyinfra-3.0b3.dist-info/entry_points.txt,sha256=BraEFyquy05M8ch33HZXOHoH_m2BTqejL3xX3NrpzOM,471
166
+ pyinfra-3.0b3.dist-info/top_level.txt,sha256=2K6D1mK35JTSEBgOfEPV-N-uA2SDErxGiE0J-HUMMVI,26
167
+ pyinfra-3.0b3.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.41.3)
2
+ Generator: bdist_wheel (0.43.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py2-none-any
5
5
  Tag: py3-none-any
pyinfra_cli/exceptions.py CHANGED
@@ -1,7 +1,6 @@
1
1
  import abc
2
2
  import sys
3
3
  from inspect import getframeinfo
4
- from os import path
5
4
  from traceback import format_exception, format_tb, walk_tb
6
5
  from types import TracebackType
7
6
 
@@ -24,10 +23,6 @@ def get_frame_line_from_tb(tb: TracebackType):
24
23
  info = getframeinfo(frame)
25
24
  if info.filename.startswith(PYINFRA_INSTALL_DIR):
26
25
  continue
27
- if info.filename.startswith("/"):
28
- continue
29
- if not path.exists(info.filename):
30
- continue
31
26
  return info
32
27
 
33
28
 
pyinfra_cli/inventory.py CHANGED
@@ -1,4 +1,3 @@
1
- import re
2
1
  import socket
3
2
  from collections import defaultdict
4
3
  from os import listdir, path
@@ -81,32 +80,52 @@ def _get_any_tuple_first(item: Union[T, Tuple[T, Any]]) -> T:
81
80
  return item[0] if isinstance(item, tuple) else item
82
81
 
83
82
 
83
+ def _resolves_to_host(maybe_host: str) -> bool:
84
+ """Check if a string resolves to a valid IP address."""
85
+ try:
86
+ # Use getaddrinfo to support IPv6 hosts
87
+ socket.getaddrinfo(maybe_host, port=None)
88
+ return True
89
+ except socket.gaierror:
90
+ return False
91
+
92
+
84
93
  def make_inventory(
85
94
  inventory: str,
86
95
  override_data=None,
87
96
  cwd: Optional[str] = None,
88
97
  group_data_directories=None,
89
98
  ):
90
- inventory_func = None
91
-
92
- # (Un)fortunately the CLI is pretty flexible for inventory inputs; we support a single hostname,
93
- # a Python module.function import or a Python file path. All of these are kind of similar, and
94
- # we want error handling to be a good user experience.
95
- # Thus, we'll check for everything but also drop a warning to the console if the inventory looks
96
- # like either an import or hostname but neither works.
97
- if re.match("[a-zA-Z0-9\\._]+[\\.:][a-zA-Z0-9_]+", inventory):
98
- # First, try loading the inventory as if it's a Python import function
99
+ # (Un)fortunately the CLI is pretty flexible for inventory inputs; we support inventory files, a
100
+ # single hostname, list of hosts, connectors, and python module.function or module:function
101
+ # imports.
102
+ #
103
+ # We check first for an inventory file, a list of hosts or anything with a connector, because
104
+ # (1) an inventory file is a common use case and (2) no other option can have a comma or an @
105
+ # symbol in them.
106
+ is_path_or_host_list_or_connector = (
107
+ path.exists(inventory) or "," in inventory or "@" in inventory
108
+ )
109
+ if not is_path_or_host_list_or_connector:
110
+ # Next, try loading the inventory from a python function. This happens before checking for a
111
+ # single-host inventory, so that your command does not stop working because somebody
112
+ # registered the domain `my.module.name`.
99
113
  inventory_func = try_import_module_attribute(inventory, raise_for_none=False)
100
- if inventory_func is None:
101
- try:
102
- socket.gethostbyname(inventory)
103
- except socket.gaierror:
104
- logger.warning(f"{inventory} is neither a valid Python import or hostname.")
105
-
106
- if inventory_func is None:
107
- # If not an import, load as if from the filesystem *or* comma separated list, which also
108
- # loads any all.py group data files (imported functions do not load group data).
114
+
115
+ # If the inventory does not refer to a module, we finally check if it refers to a reachable
116
+ # host
117
+ if inventory_func is None and _resolves_to_host(inventory):
118
+ is_path_or_host_list_or_connector = True
119
+
120
+ if is_path_or_host_list_or_connector:
121
+ # The inventory is either an inventory file or a (list of) hosts
109
122
  return make_inventory_from_files(inventory, override_data, cwd, group_data_directories)
123
+ elif inventory_func is None:
124
+ logger.warn(
125
+ f"{inventory} is neither an inventory file, a (list of) hosts or connectors "
126
+ "nor refers to a python module"
127
+ )
128
+ return Inventory.empty()
110
129
  else:
111
130
  return make_inventory_from_func(inventory_func, override_data)
112
131