pyinfra 3.1.1__tar.gz → 3.3__tar.gz
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-3.1.1 → pyinfra-3.3}/CHANGELOG.md +92 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/LICENSE.md +1 -1
- {pyinfra-3.1.1/pyinfra.egg-info → pyinfra-3.3}/PKG-INFO +25 -25
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/api/arguments.py +9 -2
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/api/arguments_typed.py +4 -5
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/api/command.py +22 -3
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/api/config.py +5 -2
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/api/deploy.py +4 -2
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/api/facts.py +3 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/api/host.py +15 -7
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/api/operation.py +2 -1
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/api/state.py +1 -1
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/connectors/base.py +34 -8
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/connectors/chroot.py +7 -2
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/connectors/docker.py +24 -8
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/connectors/dockerssh.py +7 -2
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/connectors/local.py +7 -2
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/connectors/ssh.py +9 -2
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/connectors/sshuserclient/client.py +42 -14
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/connectors/sshuserclient/config.py +2 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/connectors/terraform.py +1 -1
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/connectors/util.py +13 -9
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/context.py +9 -2
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/facts/apk.py +8 -1
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/facts/apt.py +68 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/facts/brew.py +13 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/facts/bsdinit.py +3 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/facts/cargo.py +5 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/facts/choco.py +6 -0
- pyinfra-3.3/pyinfra/facts/crontab.py +195 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/facts/deb.py +10 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/facts/dnf.py +5 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/facts/docker.py +16 -0
- pyinfra-3.3/pyinfra/facts/efibootmgr.py +113 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/facts/files.py +112 -7
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/facts/flatpak.py +7 -0
- pyinfra-3.3/pyinfra/facts/freebsd.py +75 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/facts/gem.py +5 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/facts/git.py +12 -2
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/facts/gpg.py +7 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/facts/hardware.py +13 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/facts/iptables.py +9 -1
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/facts/launchd.py +5 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/facts/lxd.py +5 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/facts/mysql.py +9 -2
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/facts/npm.py +5 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/facts/openrc.py +8 -0
- pyinfra-3.3/pyinfra/facts/opkg.py +245 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/facts/pacman.py +9 -1
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/facts/pip.py +5 -0
- pyinfra-3.3/pyinfra/facts/pipx.py +82 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/facts/pkg.py +4 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/facts/pkgin.py +5 -0
- pyinfra-3.3/pyinfra/facts/podman.py +54 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/facts/postgres.py +10 -2
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/facts/rpm.py +11 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/facts/runit.py +7 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/facts/selinux.py +16 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/facts/server.py +87 -79
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/facts/snap.py +7 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/facts/systemd.py +5 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/facts/sysvinit.py +4 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/facts/upstart.py +5 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/facts/util/__init__.py +4 -1
- pyinfra-3.3/pyinfra/facts/util/units.py +30 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/facts/vzctl.py +5 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/facts/xbps.py +6 -1
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/facts/yum.py +5 -0
- pyinfra-3.3/pyinfra/facts/zfs.py +77 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/facts/zypper.py +5 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/local.py +3 -2
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/operations/apt.py +36 -22
- pyinfra-3.3/pyinfra/operations/crontab.py +189 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/operations/docker.py +61 -56
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/operations/files.py +65 -1
- pyinfra-3.3/pyinfra/operations/freebsd/__init__.py +12 -0
- pyinfra-3.3/pyinfra/operations/freebsd/freebsd_update.py +70 -0
- pyinfra-3.3/pyinfra/operations/freebsd/pkg.py +219 -0
- pyinfra-3.3/pyinfra/operations/freebsd/service.py +116 -0
- pyinfra-3.3/pyinfra/operations/freebsd/sysrc.py +92 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/operations/git.py +23 -7
- pyinfra-3.3/pyinfra/operations/opkg.py +88 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/operations/pip.py +3 -2
- pyinfra-3.3/pyinfra/operations/pipx.py +90 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/operations/postgres.py +114 -27
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/operations/runit.py +2 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/operations/server.py +9 -181
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/operations/util/docker.py +44 -22
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/operations/zfs.py +3 -3
- {pyinfra-3.1.1 → pyinfra-3.3/pyinfra.egg-info}/PKG-INFO +25 -25
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra.egg-info/SOURCES.txt +16 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra.egg-info/requires.txt +23 -22
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra_cli/exceptions.py +5 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra_cli/inventory.py +26 -9
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra_cli/log.py +3 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra_cli/main.py +9 -8
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra_cli/prints.py +19 -4
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra_cli/util.py +3 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra_cli/virtualenv.py +1 -1
- {pyinfra-3.1.1 → pyinfra-3.3}/pyproject.toml +1 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/setup.py +13 -14
- {pyinfra-3.1.1 → pyinfra-3.3}/tests/test_cli/test_cli_deploy.py +15 -13
- {pyinfra-3.1.1 → pyinfra-3.3}/tests/test_cli/test_cli_inventory.py +53 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/tests/test_connectors/test_ssh.py +302 -182
- {pyinfra-3.1.1 → pyinfra-3.3}/tests/test_connectors/test_sshuserclient.py +68 -1
- {pyinfra-3.1.1 → pyinfra-3.3}/tests/test_facts.py +13 -6
- {pyinfra-3.1.1 → pyinfra-3.3}/tests/test_operations.py +6 -6
- pyinfra-3.3/tests/test_units.py +30 -0
- pyinfra-3.1.1/pyinfra/facts/zfs.py +0 -57
- {pyinfra-3.1.1 → pyinfra-3.3}/MANIFEST.in +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/README.md +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/__init__.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/__main__.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/api/__init__.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/api/connect.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/api/connectors.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/api/exceptions.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/api/inventory.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/api/operations.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/api/util.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/connectors/__init__.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/connectors/ssh_util.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/connectors/sshuserclient/__init__.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/connectors/vagrant.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/facts/__init__.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/facts/postgresql.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/facts/util/databases.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/facts/util/packaging.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/facts/util/win_files.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/operations/__init__.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/operations/apk.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/operations/brew.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/operations/bsdinit.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/operations/cargo.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/operations/choco.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/operations/dnf.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/operations/flatpak.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/operations/gem.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/operations/iptables.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/operations/launchd.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/operations/lxd.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/operations/mysql.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/operations/npm.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/operations/openrc.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/operations/pacman.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/operations/pkg.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/operations/pkgin.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/operations/postgresql.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/operations/puppet.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/operations/python.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/operations/selinux.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/operations/snap.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/operations/ssh.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/operations/systemd.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/operations/sysvinit.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/operations/upstart.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/operations/util/__init__.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/operations/util/files.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/operations/util/packaging.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/operations/util/service.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/operations/vzctl.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/operations/xbps.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/operations/yum.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/operations/zypper.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/progress.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/py.typed +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra/version.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra.egg-info/dependency_links.txt +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra.egg-info/entry_points.txt +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra.egg-info/top_level.txt +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra_cli/__init__.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra_cli/__main__.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/pyinfra_cli/commands.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/setup.cfg +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/tests/test_api/__init__.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/tests/test_api/test_api.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/tests/test_api/test_api_arguments.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/tests/test_api/test_api_command.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/tests/test_api/test_api_config.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/tests/test_api/test_api_deploys.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/tests/test_api/test_api_facts.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/tests/test_api/test_api_host.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/tests/test_api/test_api_inventory.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/tests/test_api/test_api_operations.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/tests/test_api/test_api_util.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/tests/test_cli/__init__.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/tests/test_cli/test_cli.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/tests/test_cli/test_cli_exceptions.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/tests/test_cli/test_cli_util.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/tests/test_cli/test_context_objects.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/tests/test_cli/util.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/tests/test_connectors/__init__.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/tests/test_connectors/test_chroot.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/tests/test_connectors/test_docker.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/tests/test_connectors/test_dockerssh.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/tests/test_connectors/test_local.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/tests/test_connectors/test_terraform.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/tests/test_connectors/test_util.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/tests/test_connectors/test_vagrant.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/tests/test_global_arguments.py +0 -0
- {pyinfra-3.1.1 → pyinfra-3.3}/tests/test_operations_utils.py +0 -0
|
@@ -1,3 +1,95 @@
|
|
|
1
|
+
# v3.3
|
|
2
|
+
|
|
3
|
+
Second release of 2025: loads of adds, fixes and documentation improvements. A huge THANK YOU to all contributors. Slightly changed format for the change list based on commit messages which should speed up releases:
|
|
4
|
+
|
|
5
|
+
New operations & arguments:
|
|
6
|
+
|
|
7
|
+
- operations/freebsd: add FreeBSD operations & facts (@DtxdF)
|
|
8
|
+
- operations/files.move: new operation (@Pirols)
|
|
9
|
+
- operations/server.user: enable adding user to secondary groups (Pirols)
|
|
10
|
+
- operations/postgres: enhance role management by adding `ALTER ROLE` support (@wowi42)
|
|
11
|
+
- operations/postgres: enable modifying existing postgres databases (@wowi42)
|
|
12
|
+
- operations/docker.container: refactor to support container recreation (@minor-fixes)
|
|
13
|
+
|
|
14
|
+
Operation/fact fixes:
|
|
15
|
+
|
|
16
|
+
- operations/postgres: fix quoting of locale parameters (@xvello)
|
|
17
|
+
- operations/server: remove leftover deprecated parameter (@wowi42)
|
|
18
|
+
- operations/pacmen: update PACMAN_REGEX to support additional characters (@wowi42)
|
|
19
|
+
- operations/server.sysctl: handle 0 integer values correctly (@lemmi)
|
|
20
|
+
- operations/apt: dist-upgrade also supports --autoremove (@bauen1)
|
|
21
|
+
- operations/apt: fix parameter name in docs (@bauen1)
|
|
22
|
+
- operations/server: fix: lastlog is always null (@ingstem)
|
|
23
|
+
- operations/docker: Fixed a typo with the volumes parameter to docker.prune operation (@mpilone)
|
|
24
|
+
- facts/xbps.XbpsPackages: allow . in package names (@lemmi)
|
|
25
|
+
|
|
26
|
+
Connectors, CLI:
|
|
27
|
+
|
|
28
|
+
- connectors: improve detection of sudo password needed
|
|
29
|
+
- connectors/ssh: add support for `ServerAliveInterval` (@chipot)
|
|
30
|
+
- cli: enable -h as shorthand for --help (@NichtJens)
|
|
31
|
+
|
|
32
|
+
Docs:
|
|
33
|
+
|
|
34
|
+
- docs: Add a section explaining connector flow (@goetzk)
|
|
35
|
+
- docs: Add inventory processing note and reference it (@goetzk)
|
|
36
|
+
- docs: Add example of logging to using operations docs (@goetzk)
|
|
37
|
+
- docs: fix wrong example operation using forbidden argument 'name' (@robertmx)
|
|
38
|
+
- docs: Add a note to the docs about using `_inner` when calling operations from other operations (@CSDUMMI)
|
|
39
|
+
- docs: Document host, state, inventory in files.template (@mpilone)
|
|
40
|
+
- docs: Minor adjustments to wording help docs and help (@goetzk)
|
|
41
|
+
- docs: expand connectors documentation (@goetzk)
|
|
42
|
+
- docs: correct import path for any_changed, all_changed (@lemmi)
|
|
43
|
+
- docs: Add note re: global arguments to operations (@simonhammes)
|
|
44
|
+
|
|
45
|
+
Internal/meta:
|
|
46
|
+
|
|
47
|
+
- refactor: update opkg documentation and add requires_command to ZFS and Git tests (@wowi42)
|
|
48
|
+
- Update testing and development dependencies in setup.py (@wowi42)
|
|
49
|
+
- tests: Load test specs with PyYAML instead of json (@taliaferro)
|
|
50
|
+
- typing: Require explicit override decorator (@bauen1)
|
|
51
|
+
- api: don't execute callbacks within a greenlet if we're already in one
|
|
52
|
+
- ci: Github Actions support for python 3.12 (@wowi42)
|
|
53
|
+
- ci: Prevent docs job from running on forks (@simonhammes)
|
|
54
|
+
|
|
55
|
+
# v3.2
|
|
56
|
+
|
|
57
|
+
Hello 2025! Here's pyinfra 3.2 - with another incredible round of contributions from the community, THANK YOU ALL. New stuff:
|
|
58
|
+
|
|
59
|
+
- Add total counts to results summary (@NichtJens)
|
|
60
|
+
- Enable passing extra data via `local.include` (@TimothyWillard)
|
|
61
|
+
- Validate inventory files and display warnings for unexpected variables (@simonhammes)
|
|
62
|
+
|
|
63
|
+
New operations/facts:
|
|
64
|
+
|
|
65
|
+
- Add `pipx` operations (`packages`, `upgrade_all`, `ensure_path`) facts (`PipxPackages`, `PipxEnvironment`) and operations (@maisim)
|
|
66
|
+
- Add `server.OsRelease` fact (@wowi42)
|
|
67
|
+
- Add `podman.PodmanSystemInfo` and `podman.PodmanPs` facts (@bauen1)
|
|
68
|
+
- Add many extra arguments (including generic args) to `files.FindFiles*` facts (@JakkuSakura)
|
|
69
|
+
- Add `system` argument to `git.config` operation (@Pirols)
|
|
70
|
+
- Add `psql_database` argument to postgres operations & facts (@hamishfagg)
|
|
71
|
+
- Add `files.Sha384File` fact and `sha384sum` argument to `files.download` operation (@simonhammes)
|
|
72
|
+
- Add `apt.SimulateOperationWillChange` fact (@bauen1)
|
|
73
|
+
- Detect changes in `apt.upgrade` and `apt.dist_upgrade` operations (@bauen1)
|
|
74
|
+
- Add `fibootmgr.EFIBootMgr` fact (@bauen1)
|
|
75
|
+
- Add opkg facts and operations (@morrison12)
|
|
76
|
+
|
|
77
|
+
Fixes:
|
|
78
|
+
|
|
79
|
+
- Multiple fixes for `server.crontab` operation and facts (@JakkuSakura)
|
|
80
|
+
- Correctly handle `latest` argument with requirements file in `pip.packages` operation (@amiraliakbari)
|
|
81
|
+
- Fix regex used to parse installed apk packages (@simonhammes)
|
|
82
|
+
- Fix SSH connector overwriting known hosts files (@vo452)
|
|
83
|
+
|
|
84
|
+
Docs/internal tweaks:
|
|
85
|
+
|
|
86
|
+
- Add type annotations for many more operations (@simonhammes)
|
|
87
|
+
- Add typos CI checking to replace flake8-spellcheck (@simonhammes)
|
|
88
|
+
- Bump CI actions and dependencies (@simonhammes)
|
|
89
|
+
- Require JSON tests to include all arguments
|
|
90
|
+
- Remove unused `configparser` dependency (@bkmgit)
|
|
91
|
+
- Many small documentation fixes/tweaks
|
|
92
|
+
|
|
1
93
|
# v3.1.1
|
|
2
94
|
|
|
3
95
|
- Improve errors with 2.x style `@decorator` (vs `@decorator()`) functions
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
Copyright (C)
|
|
1
|
+
Copyright (C) 2025 Nick Barrett <nick@fizzadar.com>
|
|
2
2
|
|
|
3
3
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
4
4
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pyinfra
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.3
|
|
4
4
|
Summary: pyinfra automates/provisions/manages/deploys infrastructure.
|
|
5
5
|
Home-page: https://pyinfra.com
|
|
6
6
|
Author: Nick / Fizzadar
|
|
@@ -16,7 +16,6 @@ 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.8
|
|
20
19
|
Classifier: Programming Language :: Python :: 3.9
|
|
21
20
|
Classifier: Programming Language :: Python :: 3.10
|
|
22
21
|
Classifier: Programming Language :: Python :: 3.11
|
|
@@ -24,7 +23,7 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
24
23
|
Classifier: Topic :: System :: Systems Administration
|
|
25
24
|
Classifier: Topic :: System :: Installation/Setup
|
|
26
25
|
Classifier: Topic :: Utilities
|
|
27
|
-
Requires-Python: >=3.
|
|
26
|
+
Requires-Python: >=3.9
|
|
28
27
|
Description-Content-Type: text/markdown
|
|
29
28
|
License-File: LICENSE.md
|
|
30
29
|
Requires-Dist: gevent>=1.5
|
|
@@ -33,7 +32,6 @@ Requires-Dist: click>2
|
|
|
33
32
|
Requires-Dist: jinja2<4,>2
|
|
34
33
|
Requires-Dist: python-dateutil<3,>2
|
|
35
34
|
Requires-Dist: setuptools
|
|
36
|
-
Requires-Dist: configparser
|
|
37
35
|
Requires-Dist: pywinrm
|
|
38
36
|
Requires-Dist: typeguard
|
|
39
37
|
Requires-Dist: distro<2,>=1.6
|
|
@@ -42,14 +40,15 @@ Requires-Dist: graphlib_backport; python_version < "3.9"
|
|
|
42
40
|
Requires-Dist: typing-extensions; python_version < "3.11"
|
|
43
41
|
Requires-Dist: importlib_metadata>=3.6; python_version < "3.10"
|
|
44
42
|
Provides-Extra: test
|
|
45
|
-
Requires-Dist: pytest==8.
|
|
46
|
-
Requires-Dist: coverage==7.
|
|
47
|
-
Requires-Dist: pytest-cov==
|
|
48
|
-
Requires-Dist: black==
|
|
49
|
-
Requires-Dist: isort==
|
|
50
|
-
Requires-Dist: flake8==7.
|
|
43
|
+
Requires-Dist: pytest==8.3.5; extra == "test"
|
|
44
|
+
Requires-Dist: coverage==7.7.1; extra == "test"
|
|
45
|
+
Requires-Dist: pytest-cov==6.0.0; extra == "test"
|
|
46
|
+
Requires-Dist: black==25.1.0; extra == "test"
|
|
47
|
+
Requires-Dist: isort==6.0.1; extra == "test"
|
|
48
|
+
Requires-Dist: flake8==7.1.2; extra == "test"
|
|
51
49
|
Requires-Dist: flake8-black==0.3.6; extra == "test"
|
|
52
|
-
Requires-Dist: flake8-isort==6.1.
|
|
50
|
+
Requires-Dist: flake8-isort==6.1.2; extra == "test"
|
|
51
|
+
Requires-Dist: pyyaml==6.0.2; extra == "test"
|
|
53
52
|
Requires-Dist: mypy; extra == "test"
|
|
54
53
|
Requires-Dist: types-cryptography; extra == "test"
|
|
55
54
|
Requires-Dist: types-paramiko; extra == "test"
|
|
@@ -57,33 +56,34 @@ Requires-Dist: types-python-dateutil; extra == "test"
|
|
|
57
56
|
Requires-Dist: types-PyYAML; extra == "test"
|
|
58
57
|
Requires-Dist: types-setuptools; extra == "test"
|
|
59
58
|
Provides-Extra: docs
|
|
60
|
-
Requires-Dist: pyinfra-guzzle_sphinx_theme==0.
|
|
61
|
-
Requires-Dist: myst-parser==
|
|
62
|
-
Requires-Dist: sphinx==
|
|
59
|
+
Requires-Dist: pyinfra-guzzle_sphinx_theme==0.17; extra == "docs"
|
|
60
|
+
Requires-Dist: myst-parser==4.0.1; extra == "docs"
|
|
61
|
+
Requires-Dist: sphinx==8.2.3; extra == "docs"
|
|
63
62
|
Provides-Extra: dev
|
|
64
|
-
Requires-Dist: pytest==8.
|
|
65
|
-
Requires-Dist: coverage==7.
|
|
66
|
-
Requires-Dist: pytest-cov==
|
|
67
|
-
Requires-Dist: black==
|
|
68
|
-
Requires-Dist: isort==
|
|
69
|
-
Requires-Dist: flake8==7.
|
|
63
|
+
Requires-Dist: pytest==8.3.5; extra == "dev"
|
|
64
|
+
Requires-Dist: coverage==7.7.1; extra == "dev"
|
|
65
|
+
Requires-Dist: pytest-cov==6.0.0; extra == "dev"
|
|
66
|
+
Requires-Dist: black==25.1.0; extra == "dev"
|
|
67
|
+
Requires-Dist: isort==6.0.1; extra == "dev"
|
|
68
|
+
Requires-Dist: flake8==7.1.2; extra == "dev"
|
|
70
69
|
Requires-Dist: flake8-black==0.3.6; extra == "dev"
|
|
71
|
-
Requires-Dist: flake8-isort==6.1.
|
|
70
|
+
Requires-Dist: flake8-isort==6.1.2; extra == "dev"
|
|
71
|
+
Requires-Dist: pyyaml==6.0.2; extra == "dev"
|
|
72
72
|
Requires-Dist: mypy; extra == "dev"
|
|
73
73
|
Requires-Dist: types-cryptography; extra == "dev"
|
|
74
74
|
Requires-Dist: types-paramiko; extra == "dev"
|
|
75
75
|
Requires-Dist: types-python-dateutil; extra == "dev"
|
|
76
76
|
Requires-Dist: types-PyYAML; extra == "dev"
|
|
77
77
|
Requires-Dist: types-setuptools; extra == "dev"
|
|
78
|
-
Requires-Dist: pyinfra-guzzle_sphinx_theme==0.
|
|
79
|
-
Requires-Dist: myst-parser==
|
|
80
|
-
Requires-Dist: sphinx==
|
|
78
|
+
Requires-Dist: pyinfra-guzzle_sphinx_theme==0.17; extra == "dev"
|
|
79
|
+
Requires-Dist: myst-parser==4.0.1; extra == "dev"
|
|
80
|
+
Requires-Dist: sphinx==8.2.3; extra == "dev"
|
|
81
81
|
Requires-Dist: wheel; extra == "dev"
|
|
82
82
|
Requires-Dist: twine; extra == "dev"
|
|
83
83
|
Requires-Dist: ipython; extra == "dev"
|
|
84
84
|
Requires-Dist: ipdb; extra == "dev"
|
|
85
85
|
Requires-Dist: ipdbplugin; extra == "dev"
|
|
86
|
-
Requires-Dist: flake8-spellcheck==0.
|
|
86
|
+
Requires-Dist: flake8-spellcheck==0.28.0; extra == "dev"
|
|
87
87
|
Requires-Dist: redbaron; extra == "dev"
|
|
88
88
|
|
|
89
89
|
<p align="center">
|
|
@@ -248,6 +248,12 @@ __argument_docs__ = {
|
|
|
248
248
|
"Privilege & user escalation": (
|
|
249
249
|
auth_argument_meta,
|
|
250
250
|
"""
|
|
251
|
+
.. caution::
|
|
252
|
+
When combining privilege escalation arguments it is important to know the order they
|
|
253
|
+
are applied: ``doas`` -> ``sudo`` -> ``su``. For example
|
|
254
|
+
``_sudo=True,_su_user="pyinfra"`` yields a command like ``sudo su pyinfra..``.
|
|
255
|
+
""",
|
|
256
|
+
"""
|
|
251
257
|
.. code:: python
|
|
252
258
|
|
|
253
259
|
# Execute a command with sudo
|
|
@@ -268,6 +274,7 @@ __argument_docs__ = {
|
|
|
268
274
|
),
|
|
269
275
|
"Shell control & features": (
|
|
270
276
|
shell_argument_meta,
|
|
277
|
+
"",
|
|
271
278
|
"""
|
|
272
279
|
.. code:: python
|
|
273
280
|
|
|
@@ -279,8 +286,8 @@ __argument_docs__ = {
|
|
|
279
286
|
)
|
|
280
287
|
""",
|
|
281
288
|
),
|
|
282
|
-
"Operation meta & callbacks": (meta_argument_meta, ""),
|
|
283
|
-
"Execution strategy": (execution_argument_meta, ""),
|
|
289
|
+
"Operation meta & callbacks": (meta_argument_meta, "", ""),
|
|
290
|
+
"Execution strategy": (execution_argument_meta, "", ""),
|
|
284
291
|
}
|
|
285
292
|
|
|
286
293
|
|
|
@@ -32,11 +32,6 @@ class PyinfraOperation(Generic[P], Protocol):
|
|
|
32
32
|
def __call__(
|
|
33
33
|
self,
|
|
34
34
|
#
|
|
35
|
-
# op args
|
|
36
|
-
# needs to be first
|
|
37
|
-
#
|
|
38
|
-
*args: P.args,
|
|
39
|
-
#
|
|
40
35
|
# ConnectorArguments
|
|
41
36
|
#
|
|
42
37
|
# Auth
|
|
@@ -74,6 +69,10 @@ class PyinfraOperation(Generic[P], Protocol):
|
|
|
74
69
|
_run_once: bool = False,
|
|
75
70
|
_serial: bool = False,
|
|
76
71
|
#
|
|
72
|
+
# op args
|
|
73
|
+
#
|
|
74
|
+
*args: P.args,
|
|
75
|
+
#
|
|
77
76
|
# op kwargs
|
|
78
77
|
#
|
|
79
78
|
**kwargs: P.kwargs,
|
|
@@ -6,9 +6,9 @@ from string import Formatter
|
|
|
6
6
|
from typing import IO, TYPE_CHECKING, Callable, Union
|
|
7
7
|
|
|
8
8
|
import gevent
|
|
9
|
-
from typing_extensions import Unpack
|
|
9
|
+
from typing_extensions import Unpack, override
|
|
10
10
|
|
|
11
|
-
from pyinfra.context import ctx_config, ctx_host
|
|
11
|
+
from pyinfra.context import LocalContextObject, ctx_config, ctx_host
|
|
12
12
|
|
|
13
13
|
from .arguments import ConnectorArguments
|
|
14
14
|
|
|
@@ -58,6 +58,7 @@ class QuoteString:
|
|
|
58
58
|
def __init__(self, obj: Union[str, "StringCommand"]):
|
|
59
59
|
self.obj = obj
|
|
60
60
|
|
|
61
|
+
@override
|
|
61
62
|
def __repr__(self) -> str:
|
|
62
63
|
return f"QuoteString({self.obj})"
|
|
63
64
|
|
|
@@ -68,6 +69,7 @@ class PyinfraCommand:
|
|
|
68
69
|
def __init__(self, **arguments: Unpack[ConnectorArguments]):
|
|
69
70
|
self.connector_arguments = arguments
|
|
70
71
|
|
|
72
|
+
@override
|
|
71
73
|
def __eq__(self, other) -> bool:
|
|
72
74
|
if isinstance(other, self.__class__) and repr(self) == repr(other):
|
|
73
75
|
return True
|
|
@@ -88,9 +90,11 @@ class StringCommand(PyinfraCommand):
|
|
|
88
90
|
self.bits = bits
|
|
89
91
|
self.separator = _separator
|
|
90
92
|
|
|
93
|
+
@override
|
|
91
94
|
def __str__(self) -> str:
|
|
92
95
|
return self.get_masked_value()
|
|
93
96
|
|
|
97
|
+
@override
|
|
94
98
|
def __repr__(self) -> str:
|
|
95
99
|
return f"StringCommand({self.get_masked_value()})"
|
|
96
100
|
|
|
@@ -131,6 +135,7 @@ class StringCommand(PyinfraCommand):
|
|
|
131
135
|
],
|
|
132
136
|
)
|
|
133
137
|
|
|
138
|
+
@override
|
|
134
139
|
def execute(self, state: "State", host: "Host", connector_arguments: ConnectorArguments):
|
|
135
140
|
connector_arguments.update(self.connector_arguments)
|
|
136
141
|
|
|
@@ -155,9 +160,11 @@ class FileUploadCommand(PyinfraCommand):
|
|
|
155
160
|
self.dest = dest
|
|
156
161
|
self.remote_temp_filename = remote_temp_filename
|
|
157
162
|
|
|
163
|
+
@override
|
|
158
164
|
def __repr__(self):
|
|
159
165
|
return "FileUploadCommand({0}, {1})".format(self.src, self.dest)
|
|
160
166
|
|
|
167
|
+
@override
|
|
161
168
|
def execute(self, state: "State", host: "Host", connector_arguments: ConnectorArguments):
|
|
162
169
|
connector_arguments.update(self.connector_arguments)
|
|
163
170
|
|
|
@@ -184,9 +191,11 @@ class FileDownloadCommand(PyinfraCommand):
|
|
|
184
191
|
self.dest = dest
|
|
185
192
|
self.remote_temp_filename = remote_temp_filename
|
|
186
193
|
|
|
194
|
+
@override
|
|
187
195
|
def __repr__(self):
|
|
188
196
|
return "FileDownloadCommand({0}, {1})".format(self.src, self.dest)
|
|
189
197
|
|
|
198
|
+
@override
|
|
190
199
|
def execute(self, state: "State", host: "Host", connector_arguments: ConnectorArguments):
|
|
191
200
|
connector_arguments.update(self.connector_arguments)
|
|
192
201
|
|
|
@@ -213,6 +222,7 @@ class FunctionCommand(PyinfraCommand):
|
|
|
213
222
|
self.args = args
|
|
214
223
|
self.kwargs = func_kwargs
|
|
215
224
|
|
|
225
|
+
@override
|
|
216
226
|
def __repr__(self):
|
|
217
227
|
return "FunctionCommand({0}, {1}, {2})".format(
|
|
218
228
|
self.function.__name__,
|
|
@@ -220,12 +230,19 @@ class FunctionCommand(PyinfraCommand):
|
|
|
220
230
|
self.kwargs,
|
|
221
231
|
)
|
|
222
232
|
|
|
233
|
+
@override
|
|
223
234
|
def execute(self, state: "State", host: "Host", connector_arguments: ConnectorArguments):
|
|
224
235
|
argspec = getfullargspec(self.function)
|
|
225
236
|
if "state" in argspec.args and "host" in argspec.args:
|
|
226
237
|
return self.function(state, host, *self.args, **self.kwargs)
|
|
227
238
|
|
|
228
|
-
|
|
239
|
+
# If we're already running inside a greenlet (ie a nested callback) just execute the func
|
|
240
|
+
# without any gevent.spawn which will break the local host object.
|
|
241
|
+
if isinstance(host, LocalContextObject):
|
|
242
|
+
self.function(*self.args, **self.kwargs)
|
|
243
|
+
return
|
|
244
|
+
|
|
245
|
+
def execute_function() -> None:
|
|
229
246
|
with ctx_config.use(state.config.copy()):
|
|
230
247
|
with ctx_host.use(host):
|
|
231
248
|
self.function(*self.args, **self.kwargs)
|
|
@@ -241,9 +258,11 @@ class RsyncCommand(PyinfraCommand):
|
|
|
241
258
|
self.dest = dest
|
|
242
259
|
self.flags = flags
|
|
243
260
|
|
|
261
|
+
@override
|
|
244
262
|
def __repr__(self):
|
|
245
263
|
return "RsyncCommand({0}, {1}, {2})".format(self.src, self.dest, self.flags)
|
|
246
264
|
|
|
265
|
+
@override
|
|
247
266
|
def execute(self, state: "State", host: "Host", connector_arguments: ConnectorArguments):
|
|
248
267
|
return host.rsync(
|
|
249
268
|
self.src,
|
|
@@ -2,6 +2,7 @@ try:
|
|
|
2
2
|
import importlib_metadata
|
|
3
3
|
except ImportError:
|
|
4
4
|
import importlib.metadata as importlib_metadata # type: ignore[no-redef]
|
|
5
|
+
|
|
5
6
|
from os import path
|
|
6
7
|
from typing import Iterable, Optional, Set
|
|
7
8
|
|
|
@@ -9,6 +10,7 @@ from packaging.markers import Marker
|
|
|
9
10
|
from packaging.requirements import Requirement
|
|
10
11
|
from packaging.specifiers import SpecifierSet
|
|
11
12
|
from packaging.version import Version
|
|
13
|
+
from typing_extensions import override
|
|
12
14
|
|
|
13
15
|
from pyinfra import __version__, state
|
|
14
16
|
|
|
@@ -207,6 +209,7 @@ class Config(ConfigDefaults):
|
|
|
207
209
|
for key, value in config.items():
|
|
208
210
|
setattr(self, key, value)
|
|
209
211
|
|
|
212
|
+
@override
|
|
210
213
|
def __setattr__(self, key, value):
|
|
211
214
|
super().__setattr__(key, value)
|
|
212
215
|
|
|
@@ -221,10 +224,10 @@ class Config(ConfigDefaults):
|
|
|
221
224
|
for key, value in config_state:
|
|
222
225
|
setattr(self, key, value)
|
|
223
226
|
|
|
224
|
-
def lock_current_state(self):
|
|
227
|
+
def lock_current_state(self) -> None:
|
|
225
228
|
self._locked_config = self.get_current_state()
|
|
226
229
|
|
|
227
|
-
def reset_locked_state(self):
|
|
230
|
+
def reset_locked_state(self) -> None:
|
|
228
231
|
self.set_current_state(self._locked_config)
|
|
229
232
|
|
|
230
233
|
def copy(self) -> "Config":
|
|
@@ -23,7 +23,7 @@ if TYPE_CHECKING:
|
|
|
23
23
|
from pyinfra.api.state import State
|
|
24
24
|
|
|
25
25
|
|
|
26
|
-
def add_deploy(state: "State", deploy_func: Callable[..., Any], *args, **kwargs):
|
|
26
|
+
def add_deploy(state: "State", deploy_func: Callable[..., Any], *args, **kwargs) -> None:
|
|
27
27
|
"""
|
|
28
28
|
Prepare & add an deploy to pyinfra.state by executing it on all hosts.
|
|
29
29
|
|
|
@@ -54,7 +54,9 @@ def add_deploy(state: "State", deploy_func: Callable[..., Any], *args, **kwargs)
|
|
|
54
54
|
P = ParamSpec("P")
|
|
55
55
|
|
|
56
56
|
|
|
57
|
-
def deploy(
|
|
57
|
+
def deploy(
|
|
58
|
+
name: Optional[str] = None, data_defaults: Optional[dict] = None
|
|
59
|
+
) -> Callable[[Callable[P, Any]], PyinfraOperation[P]]:
|
|
58
60
|
"""
|
|
59
61
|
Decorator that takes a deploy function (normally from a pyinfra_* package)
|
|
60
62
|
and wraps any operations called inside with any deploy-wide kwargs/data.
|
|
@@ -19,6 +19,7 @@ from typing import TYPE_CHECKING, Any, Callable, Generic, Iterable, Optional, Ty
|
|
|
19
19
|
import click
|
|
20
20
|
import gevent
|
|
21
21
|
from paramiko import SSHException
|
|
22
|
+
from typing_extensions import override
|
|
22
23
|
|
|
23
24
|
from pyinfra import logger
|
|
24
25
|
from pyinfra.api import StringCommand
|
|
@@ -61,6 +62,7 @@ class FactBase(Generic[T]):
|
|
|
61
62
|
def requires_command(self, *args, **kwargs) -> str | None:
|
|
62
63
|
return None
|
|
63
64
|
|
|
65
|
+
@override
|
|
64
66
|
def __init_subclass__(cls) -> None:
|
|
65
67
|
super().__init_subclass__()
|
|
66
68
|
module_name = cls.__module__.replace("pyinfra.facts.", "")
|
|
@@ -97,6 +99,7 @@ class ShortFactBase(Generic[T]):
|
|
|
97
99
|
name: str
|
|
98
100
|
fact: Type[FactBase]
|
|
99
101
|
|
|
102
|
+
@override
|
|
100
103
|
def __init_subclass__(cls) -> None:
|
|
101
104
|
super().__init_subclass__()
|
|
102
105
|
module_name = cls.__module__.replace("pyinfra.facts.", "")
|
|
@@ -17,7 +17,7 @@ from typing import (
|
|
|
17
17
|
from uuid import uuid4
|
|
18
18
|
|
|
19
19
|
import click
|
|
20
|
-
from typing_extensions import Unpack
|
|
20
|
+
from typing_extensions import Unpack, override
|
|
21
21
|
|
|
22
22
|
from pyinfra import logger
|
|
23
23
|
from pyinfra.connectors.base import BaseConnector
|
|
@@ -75,9 +75,11 @@ class HostData:
|
|
|
75
75
|
|
|
76
76
|
raise AttributeError(f"Host `{self.host}` has no data `{key}`")
|
|
77
77
|
|
|
78
|
+
@override
|
|
78
79
|
def __setattr__(self, key: str, value: Any):
|
|
79
80
|
self.override_datas[key] = value
|
|
80
81
|
|
|
82
|
+
@override
|
|
81
83
|
def __str__(self):
|
|
82
84
|
return str(self.datas)
|
|
83
85
|
|
|
@@ -147,8 +149,10 @@ class Host:
|
|
|
147
149
|
name: str,
|
|
148
150
|
inventory: "Inventory",
|
|
149
151
|
groups,
|
|
150
|
-
connector_cls=
|
|
152
|
+
connector_cls=None,
|
|
151
153
|
):
|
|
154
|
+
if connector_cls is None:
|
|
155
|
+
connector_cls = get_execution_connector("ssh")
|
|
152
156
|
self.inventory = inventory
|
|
153
157
|
self.groups = groups
|
|
154
158
|
self.connector_cls = connector_cls
|
|
@@ -181,9 +185,11 @@ class Host:
|
|
|
181
185
|
padding_diff = longest_name_len - len(self.name)
|
|
182
186
|
self.print_prefix_padding = "".join(" " for _ in range(0, padding_diff))
|
|
183
187
|
|
|
188
|
+
@override
|
|
184
189
|
def __str__(self):
|
|
185
190
|
return "{0}".format(self.name)
|
|
186
191
|
|
|
192
|
+
@override
|
|
187
193
|
def __repr__(self):
|
|
188
194
|
return "Host({0})".format(self.name)
|
|
189
195
|
|
|
@@ -218,17 +224,19 @@ class Host:
|
|
|
218
224
|
self.print_prefix_padding,
|
|
219
225
|
)
|
|
220
226
|
|
|
221
|
-
def log(self, message, log_func=logger.info):
|
|
227
|
+
def log(self, message: str, log_func: Callable[[str], Any] = logger.info) -> None:
|
|
222
228
|
log_func(f"{self.print_prefix}{message}")
|
|
223
229
|
|
|
224
|
-
def log_styled(
|
|
230
|
+
def log_styled(
|
|
231
|
+
self, message: str, log_func: Callable[[str], Any] = logger.info, **kwargs
|
|
232
|
+
) -> None:
|
|
225
233
|
message_styled = click.style(message, **kwargs)
|
|
226
234
|
self.log(message_styled, log_func=log_func)
|
|
227
235
|
|
|
228
236
|
def get_deploy_data(self):
|
|
229
237
|
return self.current_op_deploy_data or self.current_deploy_data or {}
|
|
230
238
|
|
|
231
|
-
def noop(self, description):
|
|
239
|
+
def noop(self, description: str) -> None:
|
|
232
240
|
"""
|
|
233
241
|
Log a description for a noop operation.
|
|
234
242
|
"""
|
|
@@ -355,7 +363,7 @@ class Host:
|
|
|
355
363
|
# Connector proxy
|
|
356
364
|
#
|
|
357
365
|
|
|
358
|
-
def _check_state(self):
|
|
366
|
+
def _check_state(self) -> None:
|
|
359
367
|
if not self.state:
|
|
360
368
|
raise TypeError("Cannot call this function with no state!")
|
|
361
369
|
|
|
@@ -397,7 +405,7 @@ class Host:
|
|
|
397
405
|
self.state.trigger_callbacks("host_connect", self)
|
|
398
406
|
self.connected = True
|
|
399
407
|
|
|
400
|
-
def disconnect(self):
|
|
408
|
+
def disconnect(self) -> None:
|
|
401
409
|
"""
|
|
402
410
|
Disconnect from the host using it's configured connector.
|
|
403
411
|
"""
|
|
@@ -13,7 +13,7 @@ from io import StringIO
|
|
|
13
13
|
from types import FunctionType
|
|
14
14
|
from typing import TYPE_CHECKING, Any, Callable, Generator, Iterator, Optional, cast
|
|
15
15
|
|
|
16
|
-
from typing_extensions import ParamSpec
|
|
16
|
+
from typing_extensions import ParamSpec, override
|
|
17
17
|
|
|
18
18
|
import pyinfra
|
|
19
19
|
from pyinfra import context, logger
|
|
@@ -52,6 +52,7 @@ class OperationMeta:
|
|
|
52
52
|
self._hash = hash
|
|
53
53
|
self._maybe_is_change = is_change
|
|
54
54
|
|
|
55
|
+
@override
|
|
55
56
|
def __repr__(self) -> str:
|
|
56
57
|
"""
|
|
57
58
|
Return Operation object as a string.
|
|
@@ -86,14 +86,13 @@ class BaseConnector(abc.ABC):
|
|
|
86
86
|
@abc.abstractmethod
|
|
87
87
|
def make_names_data(name: str) -> Iterator[tuple[str, dict, list[str]]]:
|
|
88
88
|
"""
|
|
89
|
-
|
|
90
|
-
|
|
89
|
+
Generate inventory targets. This is a staticmethod because each yield will become a new host
|
|
90
|
+
object with a new (ie not this) instance of the connector.
|
|
91
91
|
"""
|
|
92
|
-
...
|
|
93
92
|
|
|
94
93
|
def connect(self) -> None:
|
|
95
94
|
"""
|
|
96
|
-
Connect this connector instance.
|
|
95
|
+
Connect this connector instance. Should raise ConnectError exceptions to indicate failure.
|
|
97
96
|
"""
|
|
98
97
|
|
|
99
98
|
def disconnect(self) -> None:
|
|
@@ -108,7 +107,20 @@ class BaseConnector(abc.ABC):
|
|
|
108
107
|
print_output: bool,
|
|
109
108
|
print_input: bool,
|
|
110
109
|
**arguments: Unpack["ConnectorArguments"],
|
|
111
|
-
) -> tuple[bool, "CommandOutput"]:
|
|
110
|
+
) -> tuple[bool, "CommandOutput"]:
|
|
111
|
+
"""
|
|
112
|
+
Execute a command.
|
|
113
|
+
|
|
114
|
+
Args:
|
|
115
|
+
command (StringCommand): actual command to execute
|
|
116
|
+
print_output (bool): whether to print command output
|
|
117
|
+
print_input (bool): whether to print command input
|
|
118
|
+
arguments: (ConnectorArguments): connector global arguments
|
|
119
|
+
|
|
120
|
+
Returns:
|
|
121
|
+
tuple: (bool, CommandOutput)
|
|
122
|
+
Bool indicating success and CommandOutput with stdout/stderr lines.
|
|
123
|
+
"""
|
|
112
124
|
|
|
113
125
|
@abc.abstractmethod
|
|
114
126
|
def put_file(
|
|
@@ -119,7 +131,14 @@ class BaseConnector(abc.ABC):
|
|
|
119
131
|
print_output: bool = False,
|
|
120
132
|
print_input: bool = False,
|
|
121
133
|
**arguments: Unpack["ConnectorArguments"],
|
|
122
|
-
) -> bool:
|
|
134
|
+
) -> bool:
|
|
135
|
+
"""
|
|
136
|
+
Upload a local file or IO object by copying it to a temporary directory
|
|
137
|
+
and then writing it to the upload location.
|
|
138
|
+
|
|
139
|
+
Returns:
|
|
140
|
+
bool: indicating success or failure.
|
|
141
|
+
"""
|
|
123
142
|
|
|
124
143
|
@abc.abstractmethod
|
|
125
144
|
def get_file(
|
|
@@ -130,9 +149,16 @@ class BaseConnector(abc.ABC):
|
|
|
130
149
|
print_output: bool = False,
|
|
131
150
|
print_input: bool = False,
|
|
132
151
|
**arguments: Unpack["ConnectorArguments"],
|
|
133
|
-
) -> bool:
|
|
152
|
+
) -> bool:
|
|
153
|
+
"""
|
|
154
|
+
Download a local file by copying it to a temporary location and then writing
|
|
155
|
+
it to our filename or IO object.
|
|
156
|
+
|
|
157
|
+
Returns:
|
|
158
|
+
bool: indicating success or failure.
|
|
159
|
+
"""
|
|
134
160
|
|
|
135
|
-
def check_can_rsync(self):
|
|
161
|
+
def check_can_rsync(self) -> None:
|
|
136
162
|
raise NotImplementedError("This connector does not support rsync")
|
|
137
163
|
|
|
138
164
|
def rsync(
|