pyinfra 0.11.dev3__py3-none-any.whl → 3.6__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 (204) hide show
  1. pyinfra/__init__.py +9 -12
  2. pyinfra/__main__.py +4 -0
  3. pyinfra/api/__init__.py +19 -3
  4. pyinfra/api/arguments.py +413 -0
  5. pyinfra/api/arguments_typed.py +79 -0
  6. pyinfra/api/command.py +274 -0
  7. pyinfra/api/config.py +222 -28
  8. pyinfra/api/connect.py +33 -13
  9. pyinfra/api/connectors.py +27 -0
  10. pyinfra/api/deploy.py +65 -66
  11. pyinfra/api/exceptions.py +73 -18
  12. pyinfra/api/facts.py +267 -200
  13. pyinfra/api/host.py +416 -50
  14. pyinfra/api/inventory.py +121 -160
  15. pyinfra/api/metadata.py +69 -0
  16. pyinfra/api/operation.py +432 -262
  17. pyinfra/api/operations.py +273 -260
  18. pyinfra/api/state.py +302 -248
  19. pyinfra/api/util.py +309 -369
  20. pyinfra/connectors/base.py +173 -0
  21. pyinfra/connectors/chroot.py +212 -0
  22. pyinfra/connectors/docker.py +405 -0
  23. pyinfra/connectors/dockerssh.py +297 -0
  24. pyinfra/connectors/local.py +238 -0
  25. pyinfra/connectors/scp/__init__.py +1 -0
  26. pyinfra/connectors/scp/client.py +204 -0
  27. pyinfra/connectors/ssh.py +727 -0
  28. pyinfra/connectors/ssh_util.py +114 -0
  29. pyinfra/connectors/sshuserclient/client.py +309 -0
  30. pyinfra/connectors/sshuserclient/config.py +102 -0
  31. pyinfra/connectors/terraform.py +135 -0
  32. pyinfra/connectors/util.py +417 -0
  33. pyinfra/connectors/vagrant.py +183 -0
  34. pyinfra/context.py +145 -0
  35. pyinfra/facts/__init__.py +7 -6
  36. pyinfra/facts/apk.py +22 -7
  37. pyinfra/facts/apt.py +117 -60
  38. pyinfra/facts/brew.py +100 -15
  39. pyinfra/facts/bsdinit.py +23 -0
  40. pyinfra/facts/cargo.py +37 -0
  41. pyinfra/facts/choco.py +47 -0
  42. pyinfra/facts/crontab.py +195 -0
  43. pyinfra/facts/deb.py +94 -0
  44. pyinfra/facts/dnf.py +48 -0
  45. pyinfra/facts/docker.py +96 -23
  46. pyinfra/facts/efibootmgr.py +113 -0
  47. pyinfra/facts/files.py +629 -58
  48. pyinfra/facts/flatpak.py +77 -0
  49. pyinfra/facts/freebsd.py +70 -0
  50. pyinfra/facts/gem.py +19 -6
  51. pyinfra/facts/git.py +59 -14
  52. pyinfra/facts/gpg.py +150 -0
  53. pyinfra/facts/hardware.py +313 -167
  54. pyinfra/facts/iptables.py +72 -62
  55. pyinfra/facts/launchd.py +44 -0
  56. pyinfra/facts/lxd.py +17 -4
  57. pyinfra/facts/mysql.py +122 -86
  58. pyinfra/facts/npm.py +17 -9
  59. pyinfra/facts/openrc.py +71 -0
  60. pyinfra/facts/opkg.py +246 -0
  61. pyinfra/facts/pacman.py +50 -7
  62. pyinfra/facts/pip.py +24 -7
  63. pyinfra/facts/pipx.py +82 -0
  64. pyinfra/facts/pkg.py +15 -6
  65. pyinfra/facts/pkgin.py +35 -0
  66. pyinfra/facts/podman.py +54 -0
  67. pyinfra/facts/postgres.py +178 -0
  68. pyinfra/facts/postgresql.py +6 -147
  69. pyinfra/facts/rpm.py +105 -0
  70. pyinfra/facts/runit.py +77 -0
  71. pyinfra/facts/selinux.py +161 -0
  72. pyinfra/facts/server.py +762 -285
  73. pyinfra/facts/snap.py +88 -0
  74. pyinfra/facts/systemd.py +139 -0
  75. pyinfra/facts/sysvinit.py +59 -0
  76. pyinfra/facts/upstart.py +35 -0
  77. pyinfra/facts/util/__init__.py +17 -0
  78. pyinfra/facts/util/databases.py +4 -6
  79. pyinfra/facts/util/packaging.py +37 -6
  80. pyinfra/facts/util/units.py +30 -0
  81. pyinfra/facts/util/win_files.py +99 -0
  82. pyinfra/facts/vzctl.py +20 -13
  83. pyinfra/facts/xbps.py +35 -0
  84. pyinfra/facts/yum.py +34 -40
  85. pyinfra/facts/zfs.py +77 -0
  86. pyinfra/facts/zypper.py +42 -0
  87. pyinfra/local.py +45 -83
  88. pyinfra/operations/__init__.py +12 -0
  89. pyinfra/operations/apk.py +99 -0
  90. pyinfra/operations/apt.py +496 -0
  91. pyinfra/operations/brew.py +232 -0
  92. pyinfra/operations/bsdinit.py +59 -0
  93. pyinfra/operations/cargo.py +45 -0
  94. pyinfra/operations/choco.py +61 -0
  95. pyinfra/operations/crontab.py +194 -0
  96. pyinfra/operations/dnf.py +213 -0
  97. pyinfra/operations/docker.py +492 -0
  98. pyinfra/operations/files.py +2014 -0
  99. pyinfra/operations/flatpak.py +95 -0
  100. pyinfra/operations/freebsd/__init__.py +12 -0
  101. pyinfra/operations/freebsd/freebsd_update.py +70 -0
  102. pyinfra/operations/freebsd/pkg.py +219 -0
  103. pyinfra/operations/freebsd/service.py +116 -0
  104. pyinfra/operations/freebsd/sysrc.py +92 -0
  105. pyinfra/operations/gem.py +48 -0
  106. pyinfra/operations/git.py +420 -0
  107. pyinfra/operations/iptables.py +312 -0
  108. pyinfra/operations/launchd.py +45 -0
  109. pyinfra/operations/lxd.py +69 -0
  110. pyinfra/operations/mysql.py +610 -0
  111. pyinfra/operations/npm.py +57 -0
  112. pyinfra/operations/openrc.py +63 -0
  113. pyinfra/operations/opkg.py +89 -0
  114. pyinfra/operations/pacman.py +82 -0
  115. pyinfra/operations/pip.py +206 -0
  116. pyinfra/operations/pipx.py +103 -0
  117. pyinfra/operations/pkg.py +71 -0
  118. pyinfra/operations/pkgin.py +92 -0
  119. pyinfra/operations/postgres.py +437 -0
  120. pyinfra/operations/postgresql.py +30 -0
  121. pyinfra/operations/puppet.py +41 -0
  122. pyinfra/operations/python.py +73 -0
  123. pyinfra/operations/runit.py +184 -0
  124. pyinfra/operations/selinux.py +190 -0
  125. pyinfra/operations/server.py +1100 -0
  126. pyinfra/operations/snap.py +118 -0
  127. pyinfra/operations/ssh.py +217 -0
  128. pyinfra/operations/systemd.py +150 -0
  129. pyinfra/operations/sysvinit.py +142 -0
  130. pyinfra/operations/upstart.py +68 -0
  131. pyinfra/operations/util/__init__.py +12 -0
  132. pyinfra/operations/util/docker.py +407 -0
  133. pyinfra/operations/util/files.py +247 -0
  134. pyinfra/operations/util/packaging.py +338 -0
  135. pyinfra/operations/util/service.py +46 -0
  136. pyinfra/operations/vzctl.py +137 -0
  137. pyinfra/operations/xbps.py +78 -0
  138. pyinfra/operations/yum.py +213 -0
  139. pyinfra/operations/zfs.py +176 -0
  140. pyinfra/operations/zypper.py +193 -0
  141. pyinfra/progress.py +44 -32
  142. pyinfra/py.typed +0 -0
  143. pyinfra/version.py +9 -1
  144. pyinfra-3.6.dist-info/METADATA +142 -0
  145. pyinfra-3.6.dist-info/RECORD +160 -0
  146. {pyinfra-0.11.dev3.dist-info → pyinfra-3.6.dist-info}/WHEEL +1 -2
  147. pyinfra-3.6.dist-info/entry_points.txt +12 -0
  148. {pyinfra-0.11.dev3.dist-info → pyinfra-3.6.dist-info/licenses}/LICENSE.md +1 -1
  149. pyinfra_cli/__init__.py +1 -0
  150. pyinfra_cli/cli.py +793 -0
  151. pyinfra_cli/commands.py +66 -0
  152. pyinfra_cli/exceptions.py +155 -65
  153. pyinfra_cli/inventory.py +233 -89
  154. pyinfra_cli/log.py +39 -43
  155. pyinfra_cli/main.py +26 -495
  156. pyinfra_cli/prints.py +215 -156
  157. pyinfra_cli/util.py +172 -105
  158. pyinfra_cli/virtualenv.py +25 -20
  159. pyinfra/api/connectors/__init__.py +0 -21
  160. pyinfra/api/connectors/ansible.py +0 -99
  161. pyinfra/api/connectors/docker.py +0 -178
  162. pyinfra/api/connectors/local.py +0 -169
  163. pyinfra/api/connectors/ssh.py +0 -402
  164. pyinfra/api/connectors/sshuserclient/client.py +0 -105
  165. pyinfra/api/connectors/sshuserclient/config.py +0 -90
  166. pyinfra/api/connectors/util.py +0 -63
  167. pyinfra/api/connectors/vagrant.py +0 -155
  168. pyinfra/facts/init.py +0 -176
  169. pyinfra/facts/util/files.py +0 -102
  170. pyinfra/hook.py +0 -41
  171. pyinfra/modules/__init__.py +0 -11
  172. pyinfra/modules/apk.py +0 -64
  173. pyinfra/modules/apt.py +0 -272
  174. pyinfra/modules/brew.py +0 -122
  175. pyinfra/modules/files.py +0 -711
  176. pyinfra/modules/gem.py +0 -30
  177. pyinfra/modules/git.py +0 -115
  178. pyinfra/modules/init.py +0 -344
  179. pyinfra/modules/iptables.py +0 -271
  180. pyinfra/modules/lxd.py +0 -45
  181. pyinfra/modules/mysql.py +0 -347
  182. pyinfra/modules/npm.py +0 -47
  183. pyinfra/modules/pacman.py +0 -60
  184. pyinfra/modules/pip.py +0 -99
  185. pyinfra/modules/pkg.py +0 -43
  186. pyinfra/modules/postgresql.py +0 -245
  187. pyinfra/modules/puppet.py +0 -20
  188. pyinfra/modules/python.py +0 -37
  189. pyinfra/modules/server.py +0 -524
  190. pyinfra/modules/ssh.py +0 -150
  191. pyinfra/modules/util/files.py +0 -52
  192. pyinfra/modules/util/packaging.py +0 -118
  193. pyinfra/modules/vzctl.py +0 -133
  194. pyinfra/modules/yum.py +0 -171
  195. pyinfra/pseudo_modules.py +0 -64
  196. pyinfra-0.11.dev3.dist-info/.DS_Store +0 -0
  197. pyinfra-0.11.dev3.dist-info/METADATA +0 -135
  198. pyinfra-0.11.dev3.dist-info/RECORD +0 -95
  199. pyinfra-0.11.dev3.dist-info/entry_points.txt +0 -3
  200. pyinfra-0.11.dev3.dist-info/top_level.txt +0 -2
  201. pyinfra_cli/__main__.py +0 -40
  202. pyinfra_cli/config.py +0 -92
  203. /pyinfra/{modules/util → connectors}/__init__.py +0 -0
  204. /pyinfra/{api/connectors → connectors}/sshuserclient/__init__.py +0 -0
@@ -0,0 +1,66 @@
1
+ from __future__ import annotations
2
+
3
+ import json
4
+
5
+ from pyinfra.api.facts import FactBase
6
+
7
+ from .exceptions import CliError
8
+ from .util import parse_cli_arg, try_import_module_attribute
9
+
10
+
11
+ def get_func_and_args(commands):
12
+ operation_name = commands[0]
13
+
14
+ op = try_import_module_attribute(operation_name, prefix="pyinfra.operations")
15
+
16
+ # Parse the arguments
17
+ operation_args = commands[1:]
18
+
19
+ if len(operation_args) == 1:
20
+ # Check if we're JSON (in which case we expect a list of two items:
21
+ # a list of args and a dict of kwargs).
22
+ try:
23
+ args, kwargs = json.loads(operation_args[0])
24
+ return op, (args or (), kwargs or {})
25
+ except ValueError:
26
+ pass
27
+
28
+ args = [parse_cli_arg(arg) for arg in operation_args if "=" not in arg]
29
+
30
+ kwargs = {
31
+ key: parse_cli_arg(value)
32
+ for key, value in [arg.split("=", 1) for arg in operation_args if "=" in arg]
33
+ }
34
+
35
+ return op, (args, kwargs)
36
+
37
+
38
+ def get_facts_and_args(commands):
39
+ facts: list[tuple[FactBase, tuple, dict]] = []
40
+
41
+ current_fact = None
42
+
43
+ for command in commands:
44
+ if "=" in command:
45
+ if not current_fact:
46
+ raise CliError("Invalid fact commands: `{0}`".format(commands))
47
+
48
+ key, value = command.split("=", 1)
49
+ current_fact[2][key] = parse_cli_arg(value)
50
+ continue
51
+
52
+ if current_fact:
53
+ facts.append(current_fact)
54
+ current_fact = None
55
+
56
+ if "." not in command:
57
+ raise CliError(f"Invalid fact: `{command}`, should be in the format `module.cls`")
58
+
59
+ fact_cls = try_import_module_attribute(command, prefix="pyinfra.facts")
60
+ assert fact_cls is not None
61
+ current_fact = (fact_cls, (), {})
62
+
63
+ if current_fact:
64
+ facts.append(current_fact)
65
+
66
+ return facts
pyinfra_cli/exceptions.py CHANGED
@@ -1,78 +1,168 @@
1
+ import abc
1
2
  import sys
2
-
3
- from traceback import format_exception, format_tb
3
+ from inspect import getframeinfo
4
+ from traceback import format_exception, format_tb, walk_tb
5
+ from types import TracebackType
4
6
 
5
7
  import click
6
-
7
- from pyinfra import logger, pseudo_host, pseudo_state
8
- from pyinfra.api.exceptions import PyinfraError
9
- from pyinfra.hook import Error as HookError
10
-
11
-
12
- class CliError(PyinfraError, click.ClickException):
13
- def show(self):
14
- name = 'unknown error'
15
-
16
- if isinstance(self, HookError):
17
- name = 'hook error'
18
-
19
- elif isinstance(self, PyinfraError):
20
- name = 'pyinfra error'
21
-
22
- elif isinstance(self, IOError):
23
- name = 'local IO error'
24
-
25
- if pseudo_host.isset():
26
- # Get any operation meta + name
27
- op_name = None
28
- current_op_hash = pseudo_state.current_op_hash
29
- current_op_meta = pseudo_state.op_meta.get(current_op_hash)
30
- if current_op_meta:
31
- op_name = ', '.join(current_op_meta['names'])
32
-
33
- sys.stderr.write('--> {0}{1}{2}: '.format(
34
- pseudo_host.print_prefix,
35
- click.style(name, 'red', bold=True),
36
- ' (operation={0})'.format(op_name) if op_name else '',
37
- ))
38
- else:
39
- sys.stderr.write(
40
- '--> {0}: '.format(click.style(name, 'red', bold=True)),
41
- )
42
-
43
- logger.warning(self)
44
-
45
-
46
- class UnexpectedError(click.ClickException):
8
+ from typing_extensions import override
9
+
10
+ from pyinfra import logger
11
+ from pyinfra.api.exceptions import (
12
+ ArgumentTypeError,
13
+ ConnectorDataTypeError,
14
+ OperationError,
15
+ PyinfraError,
16
+ )
17
+ from pyinfra.api.util import PYINFRA_INSTALL_DIR
18
+
19
+
20
+ def get_frame_line_from_tb(tb: TracebackType):
21
+ frame_lines = list(walk_tb(tb))
22
+ frame_lines.reverse()
23
+ for frame, line in frame_lines:
24
+ info = getframeinfo(frame)
25
+ if info.filename.startswith(PYINFRA_INSTALL_DIR):
26
+ continue
27
+ return info
28
+
29
+
30
+ class WrappedError(click.ClickException):
31
+ def __init__(self, e: Exception):
32
+ self.traceback = e.__traceback__
33
+ self.exception = e
34
+
35
+ # Pull message from the wrapped exception
36
+ message = getattr(e, "message", e.args[0])
37
+ if not isinstance(message, str):
38
+ message = repr(message)
39
+ self.message = message
40
+
41
+ @override
42
+ def show(self, file=None):
43
+ name = "unknown error"
44
+
45
+ if isinstance(self.exception, ConnectorDataTypeError):
46
+ name = "Connector data type error"
47
+ elif isinstance(self.exception, ArgumentTypeError):
48
+ name = "Argument type error"
49
+ elif isinstance(self.exception, OperationError):
50
+ name = "Operation error"
51
+ elif isinstance(self.exception, PyinfraError):
52
+ name = "pyinfra error"
53
+ elif isinstance(self.exception, IOError):
54
+ name = "Local IO error"
55
+
56
+ if self.traceback:
57
+ info = get_frame_line_from_tb(self.traceback)
58
+ if info:
59
+ name = f"{name} in {info.filename} line {info.lineno}"
60
+
61
+ logger.warning(
62
+ "--> {0}: {1}".format(
63
+ click.style(name, "red", bold=True),
64
+ self,
65
+ ),
66
+ )
67
+
68
+
69
+ class CliError(click.ClickException):
70
+ @override
71
+ def show(self, file=None):
72
+ logger.warning(
73
+ "--> {0}: {1}".format(
74
+ click.style("pyinfra error", "red", bold=True),
75
+ self,
76
+ ),
77
+ )
78
+
79
+
80
+ class UnexpectedMixin(abc.ABC):
81
+ exception: Exception
82
+ traceback: TracebackType
83
+
84
+ def get_traceback_lines(self):
85
+ traceback = getattr(self.exception, "_traceback")
86
+ return format_tb(traceback)
87
+
88
+ def get_traceback(self):
89
+ return "".join(self.get_traceback_lines())
90
+
91
+ def get_exception(self):
92
+ return "".join(format_exception(self.exception.__class__, self.exception, None))
93
+
94
+
95
+ class UnexpectedExternalError(click.ClickException, UnexpectedMixin):
96
+ def __init__(self, e, filename):
97
+ _, _, traceback = sys.exc_info()
98
+ e._traceback = traceback
99
+ self.exception = e
100
+ self.filename = filename
101
+
102
+ @override
103
+ def show(self, file=None):
104
+ logger.warning(
105
+ "--> {0}:\n".format(
106
+ click.style(
107
+ "An exception occurred in: {0}".format(self.filename),
108
+ "red",
109
+ bold=True,
110
+ ),
111
+ ),
112
+ )
113
+
114
+ click.echo("Traceback (most recent call last):", err=True)
115
+ click.echo(self.get_traceback(), err=True, nl=False)
116
+ click.echo(self.get_exception(), err=True)
117
+
118
+
119
+ class UnexpectedInternalError(click.ClickException, UnexpectedMixin):
47
120
  def __init__(self, e):
48
- self.e = e
49
-
50
- def show(self):
51
- sys.stderr.write('--> {0}:\n'.format(click.style(
52
- 'An unexpected exception occurred',
53
- 'red',
54
- bold=True,
55
- )))
56
- print()
57
-
58
- traceback = getattr(self.e, '_traceback')
59
- traceback_lines = format_tb(traceback)
60
- traceback = ''.join(traceback_lines)
121
+ _, _, traceback = sys.exc_info()
122
+ e._traceback = traceback
123
+ self.exception = e
124
+
125
+ @override
126
+ def show(self, file=None):
127
+ click.echo(
128
+ "--> {0}:\n".format(
129
+ click.style(
130
+ "An internal exception occurred",
131
+ "red",
132
+ bold=True,
133
+ ),
134
+ ),
135
+ err=True,
136
+ )
137
+
138
+ traceback_lines = self.get_traceback_lines()
139
+ traceback = self.get_traceback()
61
140
 
62
141
  # Syntax errors contain the filename/line/etc, but other exceptions
63
142
  # don't, so print the *last* call to stderr.
64
- if not isinstance(self.e, SyntaxError):
143
+ if not isinstance(self.exception, SyntaxError):
65
144
  sys.stderr.write(traceback_lines[-1])
66
145
 
67
- exception = ''.join(format_exception(self.e.__class__, self.e, None))
68
- sys.stderr.write(exception)
146
+ exception = self.get_exception()
147
+ click.echo(exception, err=True)
69
148
 
70
- # Write the full trace + exception to pyinfra-debug.log
71
- with open('pyinfra-debug.log', 'w') as f:
149
+ with open("pyinfra-debug.log", "w", encoding="utf-8") as f:
72
150
  f.write(traceback)
73
151
  f.write(exception)
74
152
 
75
- print()
76
- print('--> The full traceback has been written to {0}'.format(
77
- click.style('pyinfra-debug.log', bold=True),
78
- ))
153
+ logger.debug(traceback)
154
+ logger.debug(exception)
155
+
156
+ click.echo(
157
+ "--> The full traceback has been written to {0}".format(
158
+ click.style("pyinfra-debug.log", bold=True),
159
+ ),
160
+ err=True,
161
+ )
162
+ click.echo(
163
+ (
164
+ "--> If this is unexpected please consider submitting a bug report "
165
+ "on GitHub, for more information run `pyinfra --support`."
166
+ ),
167
+ err=True,
168
+ )