Marco Ricci commited on 2026-08-30 12:26:14
Zeige 14 geänderte Dateien mit 91 Einfügungen und 134 Löschungen.
Change all references to the SSH agent socket and socket provider types to the `derivepassphrase-sshagentsocketprovider` package. Include `derivepassphrase-sshagentsocketprovider` in the dependencies.
| ... | ... |
@@ -30,6 +30,9 @@ classifiers = [ |
| 30 | 30 |
"Typing :: Typed", |
| 31 | 31 |
] |
| 32 | 32 |
dependencies = [ |
| 33 |
+ # Our API for SSH agent socket providers is declared in a separately |
|
| 34 |
+ # published package. |
|
| 35 |
+ "derivepassphrase-sshagentsocketprovider", |
|
| 33 | 36 |
# We use click for the command-line interface. We require version |
| 34 | 37 |
# 8.1.0 or higher due to click issue #1985. |
| 35 | 38 |
"click >= 8.1", |
| ... | ... |
@@ -632,7 +635,10 @@ parametrize-names-type = 'list' |
| 632 | 635 |
ban-relative-imports = "all" |
| 633 | 636 |
|
| 634 | 637 |
[tool.ruff.lint.isort] |
| 635 |
-known-first-party = ["derivepassphrase"] |
|
| 638 |
+known-first-party = [ |
|
| 639 |
+ "derivepassphrase", |
|
| 640 |
+ "derivepassphrase_sshagentsocketprovider", |
|
| 641 |
+] |
|
| 636 | 642 |
|
| 637 | 643 |
[tool.ruff.lint.pycodestyle] |
| 638 | 644 |
ignore-overlong-task-comments = true # for E501 |
| ... | ... |
@@ -61,6 +61,8 @@ if TYPE_CHECKING: |
| 61 | 61 |
|
| 62 | 62 |
from typing_extensions import Buffer, Self |
| 63 | 63 |
|
| 64 |
+ import derivepassphrase_sshagentsocketprovider as d_sasp |
|
| 65 |
+ |
|
| 64 | 66 |
PROG_NAME = _msg.PROG_NAME |
| 65 | 67 |
KEY_DISPLAY_LENGTH = 50 |
| 66 | 68 |
|
| ... | ... |
@@ -560,7 +562,7 @@ def load_user_config() -> dict[str, Any]: |
| 560 | 562 |
|
| 561 | 563 |
def get_suitable_ssh_keys( |
| 562 | 564 |
conn: ssh_agent.SSHAgentClient |
| 563 |
- | _types.SSHAgentSocket |
|
| 565 |
+ | d_sasp.SSHAgentSocket |
|
| 564 | 566 |
| Sequence[str] |
| 565 | 567 |
| None = None, |
| 566 | 568 |
/, |
| ... | ... |
@@ -854,7 +856,7 @@ def default_error_callback( |
| 854 | 856 |
|
| 855 | 857 |
def select_ssh_key( |
| 856 | 858 |
conn: ssh_agent.SSHAgentClient |
| 857 |
- | _types.SSHAgentSocket |
|
| 859 |
+ | d_sasp.SSHAgentSocket |
|
| 858 | 860 |
| Sequence[str] |
| 859 | 861 |
| None = None, |
| 860 | 862 |
/, |
| ... | ... |
@@ -1101,13 +1103,13 @@ def check_for_misleading_passphrase( |
| 1101 | 1103 |
|
| 1102 | 1104 |
def get_configured_connection_hint( |
| 1103 | 1105 |
conn: ssh_agent.SSHAgentClient |
| 1104 |
- | _types.SSHAgentSocket |
|
| 1106 |
+ | d_sasp.SSHAgentSocket |
|
| 1105 | 1107 |
| Sequence[str] |
| 1106 | 1108 |
| None = None, |
| 1107 | 1109 |
/, |
| 1108 | 1110 |
*, |
| 1109 | 1111 |
main_config: dict[str, Any], |
| 1110 |
-) -> ssh_agent.SSHAgentClient | _types.SSHAgentSocket | Sequence[str] | None: |
|
| 1112 |
+) -> ssh_agent.SSHAgentClient | d_sasp.SSHAgentSocket | Sequence[str] | None: |
|
| 1111 | 1113 |
"""Return a suitable connection hint for the SSH agent client. |
| 1112 | 1114 |
|
| 1113 | 1115 |
If a connection hint is already known, return that connection hint. |
| ... | ... |
@@ -1129,12 +1131,12 @@ def get_configured_connection_hint( |
| 1129 | 1131 |
|
| 1130 | 1132 |
def handle_return_value( |
| 1131 | 1133 |
val: ssh_agent.SSHAgentClient |
| 1132 |
- | _types.SSHAgentSocket |
|
| 1134 |
+ | d_sasp.SSHAgentSocket |
|
| 1133 | 1135 |
| str |
| 1134 | 1136 |
| Sequence[str] |
| 1135 | 1137 |
| None, |
| 1136 | 1138 |
) -> ( |
| 1137 |
- ssh_agent.SSHAgentClient | _types.SSHAgentSocket | Sequence[str] | None |
|
| 1139 |
+ ssh_agent.SSHAgentClient | d_sasp.SSHAgentSocket | Sequence[str] | None |
|
| 1138 | 1140 |
): # pragma: no cover [external] |
| 1139 | 1141 |
# A separate function, to easily exclude it from coverage, |
| 1140 | 1142 |
# because it's just type handling, which the type checker |
| ... | ... |
@@ -1168,7 +1170,7 @@ def key_to_phrase( |
| 1168 | 1170 |
error_callback: Callable[..., NoReturn], |
| 1169 | 1171 |
warning_callback: Callable[..., None], |
| 1170 | 1172 |
conn: ssh_agent.SSHAgentClient |
| 1171 |
- | _types.SSHAgentSocket |
|
| 1173 |
+ | d_sasp.SSHAgentSocket |
|
| 1172 | 1174 |
| Sequence[str] |
| 1173 | 1175 |
| None = None, |
| 1174 | 1176 |
) -> bytes: |
| ... | ... |
@@ -17,12 +17,10 @@ from typing_extensions import ( |
| 17 | 17 |
Buffer, |
| 18 | 18 |
NamedTuple, |
| 19 | 19 |
NotRequired, |
| 20 |
- TypeAlias, |
|
| 21 | 20 |
TypedDict, |
| 22 | 21 |
deprecated, |
| 23 | 22 |
get_overloads, |
| 24 | 23 |
overload, |
| 25 |
- runtime_checkable, |
|
| 26 | 24 |
) |
| 27 | 25 |
|
| 28 | 26 |
if TYPE_CHECKING: |
| ... | ... |
@@ -1140,63 +1138,3 @@ class BuiltinSSHAgentSocketProvider(str, enum.Enum): |
| 1140 | 1138 |
|
| 1141 | 1139 |
__str__ = str.__str__ |
| 1142 | 1140 |
__format__ = str.__format__ # type: ignore[assignment] |
| 1143 |
- |
|
| 1144 |
- |
|
| 1145 |
-@runtime_checkable |
|
| 1146 |
-class SSHAgentSocket(Protocol): |
|
| 1147 |
- """An abstract networking socket connected to an SSH agent. |
|
| 1148 |
- |
|
| 1149 |
- The abstract socket supports the [`sendall`][socket.socket.sendall] |
|
| 1150 |
- and a [`recv`][socket.socket.recv] operation, with the same |
|
| 1151 |
- signatures and semantics as for "real" sockets. The abstract socket |
|
| 1152 |
- also supports use as a context manager, for automatically closing |
|
| 1153 |
- the socket upon exiting the context. |
|
| 1154 |
- |
|
| 1155 |
- """ |
|
| 1156 |
- |
|
| 1157 |
- def __enter__(self) -> Any: ... # noqa: ANN401 |
|
| 1158 |
- |
|
| 1159 |
- # mypy/typeshed has a *very* lax annotation of |
|
| 1160 |
- # socket.socket.__exit__, which we need to be compatible with. |
|
| 1161 |
- # *sigh* |
|
| 1162 |
- def __exit__( |
|
| 1163 |
- self, |
|
| 1164 |
- *args: object, |
|
| 1165 |
- ) -> bool | None: ... |
|
| 1166 |
- |
|
| 1167 |
- def sendall(self, data: Buffer, flags: int = 0, /) -> None: ... |
|
| 1168 |
- |
|
| 1169 |
- def recv(self, bufsize: int, flags: int = 0, /) -> bytes: ... |
|
| 1170 |
- |
|
| 1171 |
- |
|
| 1172 |
-SSHAgentSocketProvider: TypeAlias = "Callable[[], SSHAgentSocket]" |
|
| 1173 |
-"""A callable that provides an SSH agent socket.""" |
|
| 1174 |
- |
|
| 1175 |
- |
|
| 1176 |
-class SSHAgentSocketProviderEntry(NamedTuple): |
|
| 1177 |
- """Registry information for the table of SSH agent socket providers. |
|
| 1178 |
- |
|
| 1179 |
- Third-party developers can register new socket providers for |
|
| 1180 |
- auto-discovery by setting up an entry point named |
|
| 1181 |
- [`derivepassphrase.ssh_agent_socket_providers`][derivepassphrase.ssh_agent.socketprovider.SocketProvider.ENTRY_POINT_GROUP_NAME], |
|
| 1182 |
- referencing an instance of this class. Upon startup of the `vault` |
|
| 1183 |
- subsystem, `derivepassphrase` will then add appropriate entries to |
|
| 1184 |
- the registry. |
|
| 1185 |
- |
|
| 1186 |
- Attributes: |
|
| 1187 |
- provider: The callable that provides the socket. |
|
| 1188 |
- key: The table key which this entry is registered as. |
|
| 1189 |
- aliases: Other keys that shall point to this entry's key. |
|
| 1190 |
- |
|
| 1191 |
- Note: |
|
| 1192 |
- The socket provider registry table uses the key as the key, and |
|
| 1193 |
- the provider as the value. It does not store this info object |
|
| 1194 |
- directly. |
|
| 1195 |
- |
|
| 1196 |
- """ |
|
| 1197 |
- |
|
| 1198 |
- provider: SSHAgentSocketProvider |
|
| 1199 |
- """""" |
|
| 1200 |
- key: str |
|
| 1201 |
- """""" |
|
| 1202 |
- aliases: tuple[str, ...] |
| ... | ... |
@@ -14,6 +14,7 @@ from typing import TYPE_CHECKING, ClassVar, overload |
| 14 | 14 |
|
| 15 | 15 |
from typing_extensions import Never, Self, assert_type |
| 16 | 16 |
|
| 17 |
+import derivepassphrase_sshagentsocketprovider as d_sasp |
|
| 17 | 18 |
from derivepassphrase import _types |
| 18 | 19 |
|
| 19 | 20 |
if sys.version_info < (3, 11): |
| ... | ... |
@@ -171,7 +172,7 @@ class SSHAgentClient: |
| 171 | 172 |
|
| 172 | 173 |
""" |
| 173 | 174 |
|
| 174 |
- _connection: _types.SSHAgentSocket |
|
| 175 |
+ _connection: d_sasp.SSHAgentSocket |
|
| 175 | 176 |
SOCKET_PROVIDERS: ClassVar = ("native",)
|
| 176 | 177 |
""" |
| 177 | 178 |
The default list of SSH agent socket providers. |
| ... | ... |
@@ -181,7 +182,7 @@ class SSHAgentClient: |
| 181 | 182 |
self, |
| 182 | 183 |
/, |
| 183 | 184 |
*, |
| 184 |
- socket: _types.SSHAgentSocket | Sequence[str] | None = None, |
|
| 185 |
+ socket: d_sasp.SSHAgentSocket | Sequence[str] | None = None, |
|
| 185 | 186 |
) -> None: |
| 186 | 187 |
"""Initialize the client. |
| 187 | 188 |
|
| ... | ... |
@@ -251,7 +252,7 @@ class SSHAgentClient: |
| 251 | 252 |
socket = self.SOCKET_PROVIDERS |
| 252 | 253 |
assert isinstance(socket, Sequence) # for the type checker |
| 253 | 254 |
excs: list[NotImplementedError] = [] |
| 254 |
- providers: list[_types.SSHAgentSocketProvider] = [] |
|
| 255 |
+ providers: list[d_sasp.SSHAgentSocketProvider] = [] |
|
| 255 | 256 |
for candidate in socket: |
| 256 | 257 |
try: |
| 257 | 258 |
provider = socketprovider.SocketProvider.resolve(candidate) |
| ... | ... |
@@ -275,7 +276,7 @@ class SSHAgentClient: |
| 275 | 276 |
if excs |
| 276 | 277 |
else NotImplementedError(msg) |
| 277 | 278 |
) |
| 278 |
- elif isinstance(socket, _types.SSHAgentSocket): |
|
| 279 |
+ elif isinstance(socket, d_sasp.SSHAgentSocket): |
|
| 279 | 280 |
self._connection = socket |
| 280 | 281 |
else: # pragma: no cover [failsafe] |
| 281 | 282 |
assert_type(socket, Never) |
| ... | ... |
@@ -439,7 +440,7 @@ class SSHAgentClient: |
| 439 | 440 |
def ensure_agent_subcontext( |
| 440 | 441 |
cls, |
| 441 | 442 |
conn: SSHAgentClient |
| 442 |
- | _types.SSHAgentSocket |
|
| 443 |
+ | d_sasp.SSHAgentSocket |
|
| 443 | 444 |
| Sequence[str] |
| 444 | 445 |
| None = None, |
| 445 | 446 |
) -> Generator[SSHAgentClient, None, None]: |
| ... | ... |
@@ -486,7 +487,7 @@ class SSHAgentClient: |
| 486 | 487 |
with contextlib.nullcontext(): |
| 487 | 488 |
yield conn |
| 488 | 489 |
elif ( |
| 489 |
- isinstance(conn, (_types.SSHAgentSocket, str, Sequence)) |
|
| 490 |
+ isinstance(conn, (d_sasp.SSHAgentSocket, str, Sequence)) |
|
| 490 | 491 |
or conn is None |
| 491 | 492 |
): |
| 492 | 493 |
with SSHAgentClient(socket=conn) as client: |
| ... | ... |
@@ -27,6 +27,7 @@ from ctypes.wintypes import ( # type: ignore[attr-defined] |
| 27 | 27 |
) |
| 28 | 28 |
from typing import TYPE_CHECKING, cast |
| 29 | 29 |
|
| 30 |
+import derivepassphrase_sshagentsocketprovider as d_sasp |
|
| 30 | 31 |
from derivepassphrase import _types |
| 31 | 32 |
|
| 32 | 33 |
if TYPE_CHECKING: |
| ... | ... |
@@ -45,7 +46,7 @@ if TYPE_CHECKING: |
| 45 | 46 |
) |
| 46 | 47 |
|
| 47 | 48 |
SSHAgentSocketProviderT = TypeVar( |
| 48 |
- "SSHAgentSocketProviderT", bound=_types.SSHAgentSocketProvider |
|
| 49 |
+ "SSHAgentSocketProviderT", bound=d_sasp.SSHAgentSocketProvider |
|
| 49 | 50 |
) |
| 50 | 51 |
"""A parametrized SSH agent socket provider.""" |
| 51 | 52 |
|
| ... | ... |
@@ -759,7 +760,7 @@ class SocketProvider: |
| 759 | 760 |
return cls._windows_named_pipe(None) |
| 760 | 761 |
|
| 761 | 762 |
registry: ClassVar[ |
| 762 |
- dict[str, _types.SSHAgentSocketProvider | str | None] |
|
| 763 |
+ dict[str, d_sasp.SSHAgentSocketProvider | str | None] |
|
| 763 | 764 |
] = {}
|
| 764 | 765 |
"""A dictionary of callables that provide SSH agent sockets. |
| 765 | 766 |
|
| ... | ... |
@@ -850,8 +851,8 @@ class SocketProvider: |
| 850 | 851 |
|
| 851 | 852 |
@classmethod |
| 852 | 853 |
def lookup( |
| 853 |
- cls, provider: _types.SSHAgentSocketProvider | str | None, / |
|
| 854 |
- ) -> _types.SSHAgentSocketProvider | None: |
|
| 854 |
+ cls, provider: d_sasp.SSHAgentSocketProvider | str | None, / |
|
| 855 |
+ ) -> d_sasp.SSHAgentSocketProvider | None: |
|
| 855 | 856 |
"""Look up a socket provider entry. |
| 856 | 857 |
|
| 857 | 858 |
Args: |
| ... | ... |
@@ -876,8 +877,8 @@ class SocketProvider: |
| 876 | 877 |
|
| 877 | 878 |
@classmethod |
| 878 | 879 |
def resolve( |
| 879 |
- cls, provider: _types.SSHAgentSocketProvider | str | None, / |
|
| 880 |
- ) -> _types.SSHAgentSocketProvider: |
|
| 880 |
+ cls, provider: d_sasp.SSHAgentSocketProvider | str | None, / |
|
| 881 |
+ ) -> d_sasp.SSHAgentSocketProvider: |
|
| 881 | 882 |
"""Resolve a socket provider to a proper callable. |
| 882 | 883 |
|
| 883 | 884 |
Args: |
| ... | ... |
@@ -925,10 +926,10 @@ class SocketProvider: |
| 925 | 926 |
}) |
| 926 | 927 |
canonical: dict[str, str] = {}
|
| 927 | 928 |
sorter: graphlib.TopologicalSorter[ |
| 928 |
- _types.SSHAgentSocketProvider | str | None |
|
| 929 |
+ d_sasp.SSHAgentSocketProvider | str | None |
|
| 929 | 930 |
] = graphlib.TopologicalSorter() |
| 930 |
- k: _types.SSHAgentSocketProvider | str | None |
|
| 931 |
- v: _types.SSHAgentSocketProvider | str | None |
|
| 931 |
+ k: d_sasp.SSHAgentSocketProvider | str | None |
|
| 932 |
+ v: d_sasp.SSHAgentSocketProvider | str | None |
|
| 932 | 933 |
for k, v in cls.registry.items(): |
| 933 | 934 |
sorter.add(k, v) |
| 934 | 935 |
sorter.prepare() |
| ... | ... |
@@ -956,14 +957,6 @@ class SocketProvider: |
| 956 | 957 |
for k, v in itertools.groupby(sorted_entries, key=by_value) |
| 957 | 958 |
} |
| 958 | 959 |
|
| 959 |
- ENTRY_POINT_GROUP_NAME = "derivepassphrase.ssh_agent_socket_providers" |
|
| 960 |
- """ |
|
| 961 |
- The group name under which [entry |
|
| 962 |
- points][importlib.metadata.entry_points] for the SSH agent socket |
|
| 963 |
- provider registry should be recorded. Each target of such an entry |
|
| 964 |
- point should be a [`_types.SSHAgentSocketProviderEntry`][] object. |
|
| 965 |
- """ |
|
| 966 |
- |
|
| 967 | 960 |
@classmethod |
| 968 | 961 |
def _find_all_ssh_agent_socket_providers(cls) -> None: |
| 969 | 962 |
"""Find and load all declared SSH agent socket providers. |
| ... | ... |
@@ -988,10 +981,10 @@ class SocketProvider: |
| 988 | 981 |
origins: dict[str, str | None] = {}
|
| 989 | 982 |
entries = collections.ChainMap({}, cls.registry)
|
| 990 | 983 |
for entry_point in importlib.metadata.entry_points( |
| 991 |
- group=cls.ENTRY_POINT_GROUP_NAME |
|
| 984 |
+ group=d_sasp.ENTRY_POINT_GROUP_NAME |
|
| 992 | 985 |
): |
| 993 | 986 |
provider_entry = cast( |
| 994 |
- "_types.SSHAgentSocketProviderEntry", entry_point.load() |
|
| 987 |
+ "d_sasp.SSHAgentSocketProviderEntry", entry_point.load() |
|
| 995 | 988 |
) |
| 996 | 989 |
key = provider_entry.key |
| 997 | 990 |
value = entry_point.value |
| ... | ... |
@@ -1004,7 +997,7 @@ class SocketProvider: |
| 1004 | 997 |
if not callable(provider_entry.provider): |
| 1005 | 998 |
msg = ( |
| 1006 | 999 |
f"Not an SSHAgentSocketProvider: " |
| 1007 |
- f"{dist = }, {cls.ENTRY_POINT_GROUP_NAME = }, "
|
|
| 1000 |
+ f"{dist = }, {d_sasp.ENTRY_POINT_GROUP_NAME = }, "
|
|
| 1008 | 1001 |
f"{value = }, {provider_entry = }"
|
| 1009 | 1002 |
) |
| 1010 | 1003 |
raise AssertionError(msg) # noqa: TRY004 |
| ... | ... |
@@ -16,13 +16,15 @@ from typing import TYPE_CHECKING, Final |
| 16 | 16 |
|
| 17 | 17 |
from typing_extensions import TypeAlias, assert_type |
| 18 | 18 |
|
| 19 |
-from derivepassphrase import _types, sequin, ssh_agent |
|
| 19 |
+from derivepassphrase import sequin, ssh_agent |
|
| 20 | 20 |
|
| 21 | 21 |
if TYPE_CHECKING: |
| 22 | 22 |
from collections.abc import Callable, Sequence |
| 23 | 23 |
|
| 24 | 24 |
from typing_extensions import Buffer |
| 25 | 25 |
|
| 26 |
+ import derivepassphrase_sshagentsocketprovider as d_sasp |
|
| 27 |
+ |
|
| 26 | 28 |
|
| 27 | 29 |
class Vault: |
| 28 | 30 |
"""A work-alike of James Coglan's vault. |
| ... | ... |
@@ -517,7 +519,7 @@ class Vault: |
| 517 | 519 |
/, |
| 518 | 520 |
*, |
| 519 | 521 |
conn: ssh_agent.SSHAgentClient |
| 520 |
- | _types.SSHAgentSocket |
|
| 522 |
+ | d_sasp.SSHAgentSocket |
|
| 521 | 523 |
| Sequence[str] |
| 522 | 524 |
| None = None, |
| 523 | 525 |
) -> bytes: |
| ... | ... |
@@ -27,6 +27,8 @@ from tests.machinery import pytest as pytest_machinery |
| 27 | 27 |
if TYPE_CHECKING: |
| 28 | 28 |
from collections.abc import Generator, Sequence |
| 29 | 29 |
|
| 30 |
+ import derivepassphrase_sshagentsocketprovider as d_sasp |
|
| 31 |
+ |
|
| 30 | 32 |
startup_ssh_auth_sock = os.environ.get("SSH_AUTH_SOCK", None)
|
| 31 | 33 |
|
| 32 | 34 |
|
| ... | ... |
@@ -171,7 +173,7 @@ class SSHAgentInterfaceFunc(Protocol): |
| 171 | 173 |
self, |
| 172 | 174 |
executable: str | None, |
| 173 | 175 |
env: dict[str, Any], |
| 174 |
- ) -> tuple[_types.SSHAgentSocket, str] | None: |
|
| 176 |
+ ) -> tuple[d_sasp.SSHAgentSocket, str] | None: |
|
| 175 | 177 |
"""Interface the SSH agent. |
| 176 | 178 |
|
| 177 | 179 |
Args: |
| ... | ... |
@@ -319,7 +321,7 @@ def spawn_noop( # pragma: no cover [unused] |
| 319 | 321 |
def interface_pageant_on_the_annoying_os( |
| 320 | 322 |
executable: str | None, |
| 321 | 323 |
env: dict[str, Any], |
| 322 |
-) -> tuple[_types.SSHAgentSocket, str] | None: # pragma: no cover [external] |
|
| 324 |
+) -> tuple[d_sasp.SSHAgentSocket, str] | None: # pragma: no cover [external] |
|
| 323 | 325 |
"""Interface a Pageant instance on The Annoying OS, if possible. |
| 324 | 326 |
|
| 325 | 327 |
Args: |
| ... | ... |
@@ -346,7 +348,7 @@ def interface_pageant_on_the_annoying_os( |
| 346 | 348 |
def interface_openssh_agent_on_the_annoying_os( |
| 347 | 349 |
executable: str | None, |
| 348 | 350 |
env: dict[str, Any], |
| 349 |
-) -> tuple[_types.SSHAgentSocket, str] | None: # pragma: no cover [external] |
|
| 351 |
+) -> tuple[d_sasp.SSHAgentSocket, str] | None: # pragma: no cover [external] |
|
| 350 | 352 |
"""Interface an OpenSSH agent instance on The Annoying OS, if possible. |
| 351 | 353 |
|
| 352 | 354 |
Args: |
| ... | ... |
@@ -778,7 +780,7 @@ def spawn_named_agent( # noqa: C901 |
| 778 | 780 |
not isinstance(proc_or_socket_data, subprocess.Popen) |
| 779 | 781 |
and proc_or_socket_data is not None |
| 780 | 782 |
): |
| 781 |
- socket: _types.SSHAgentSocket |
|
| 783 |
+ socket: d_sasp.SSHAgentSocket |
|
| 782 | 784 |
socket, ssh_auth_sock = proc_or_socket_data |
| 783 | 785 |
monkeypatch.setenv("SSH_AUTH_SOCK", ssh_auth_sock)
|
| 784 | 786 |
client = exit_stack.enter_context( |
| ... | ... |
@@ -30,6 +30,7 @@ from typing import TYPE_CHECKING, cast |
| 30 | 30 |
|
| 31 | 31 |
from typing_extensions import NamedTuple, assert_never |
| 32 | 32 |
|
| 33 |
+import derivepassphrase_sshagentsocketprovider as d_sasp |
|
| 33 | 34 |
from derivepassphrase import _types, ssh_agent, vault |
| 34 | 35 |
from derivepassphrase.ssh_agent import socketprovider |
| 35 | 36 |
|
| ... | ... |
@@ -533,7 +534,7 @@ class RunningSSHAgentInfo(NamedTuple): |
| 533 | 534 |
|
| 534 | 535 |
""" |
| 535 | 536 |
|
| 536 |
- socket: str | type[_types.SSHAgentSocket] |
|
| 537 |
+ socket: str | type[d_sasp.SSHAgentSocket] |
|
| 537 | 538 |
"""""" |
| 538 | 539 |
agent_type: KnownSSHAgentType |
| 539 | 540 |
"""""" |
| ... | ... |
@@ -661,7 +662,7 @@ class VaultTestConfig(NamedTuple): |
| 661 | 662 |
# ------------------------------ |
| 662 | 663 |
|
| 663 | 664 |
|
| 664 |
-ssh_auth_sock_on_posix_entry = _types.SSHAgentSocketProviderEntry( |
|
| 665 |
+ssh_auth_sock_on_posix_entry = d_sasp.SSHAgentSocketProviderEntry( |
|
| 665 | 666 |
socketprovider.SocketProvider.resolve( |
| 666 | 667 |
_types.BuiltinSSHAgentSocketProvider.SSH_AUTH_SOCK_ON_POSIX |
| 667 | 668 |
), |
| ... | ... |
@@ -673,7 +674,7 @@ The standard [`_types.SSHAgentSocketProviderEntry`][] for the UNIX |
| 673 | 674 |
domain socket handler on POSIX systems. |
| 674 | 675 |
""" |
| 675 | 676 |
|
| 676 |
-ssh_auth_sock_on_windows_entry = _types.SSHAgentSocketProviderEntry( |
|
| 677 |
+ssh_auth_sock_on_windows_entry = d_sasp.SSHAgentSocketProviderEntry( |
|
| 677 | 678 |
socketprovider.SocketProvider.resolve( |
| 678 | 679 |
_types.BuiltinSSHAgentSocketProvider.SSH_AUTH_SOCK_ON_WINDOWS |
| 679 | 680 |
), |
| ... | ... |
@@ -685,7 +686,7 @@ The standard [`_types.SSHAgentSocketProviderEntry`][] for the Windows |
| 685 | 686 |
named pipe handler on The Annoying Operating System. |
| 686 | 687 |
""" |
| 687 | 688 |
|
| 688 |
-faulty_entry_callable = _types.SSHAgentSocketProviderEntry( |
|
| 689 |
+faulty_entry_callable = d_sasp.SSHAgentSocketProviderEntry( |
|
| 689 | 690 |
(), # type: ignore[arg-type] |
| 690 | 691 |
"tuple", |
| 691 | 692 |
(), |
| ... | ... |
@@ -695,7 +696,7 @@ A faulty [`_types.SSHAgentSocketProviderEntry`][]: the indicated handler |
| 695 | 696 |
is not a callable. |
| 696 | 697 |
""" |
| 697 | 698 |
|
| 698 |
-faulty_entry_name_exists = _types.SSHAgentSocketProviderEntry( |
|
| 699 |
+faulty_entry_name_exists = d_sasp.SSHAgentSocketProviderEntry( |
|
| 699 | 700 |
socketprovider.SocketProvider.resolve( |
| 700 | 701 |
_types.BuiltinSSHAgentSocketProvider.WINDOWS |
| 701 | 702 |
), |
| ... | ... |
@@ -707,7 +708,7 @@ A faulty [`_types.SSHAgentSocketProviderEntry`][]: the indicated handler |
| 707 | 708 |
is already registered with a different callable. |
| 708 | 709 |
""" |
| 709 | 710 |
|
| 710 |
-faulty_entry_alias_exists = _types.SSHAgentSocketProviderEntry( |
|
| 711 |
+faulty_entry_alias_exists = d_sasp.SSHAgentSocketProviderEntry( |
|
| 711 | 712 |
socketprovider.SocketProvider.resolve( |
| 712 | 713 |
_types.BuiltinSSHAgentSocketProvider.SSH_AUTH_SOCK_ON_POSIX |
| 713 | 714 |
), |
| ... | ... |
@@ -20,6 +20,7 @@ import shlex |
| 20 | 20 |
import stat |
| 21 | 21 |
from typing import TYPE_CHECKING |
| 22 | 22 |
|
| 23 |
+import derivepassphrase_sshagentsocketprovider as d_sasp |
|
| 23 | 24 |
import tests.data |
| 24 | 25 |
from derivepassphrase import _types, ssh_agent, vault |
| 25 | 26 |
|
| ... | ... |
@@ -159,18 +160,18 @@ def phrase_from_key( |
| 159 | 160 |
# =============================================== |
| 160 | 161 |
|
| 161 | 162 |
|
| 162 |
-def provider_entry_provider() -> _types.SSHAgentSocket: # pragma: no cover |
|
| 163 |
+def provider_entry_provider() -> d_sasp.SSHAgentSocket: # pragma: no cover |
|
| 163 | 164 |
"""A pseudo provider for a [`_types.SSHAgentSocketProviderEntry`][].""" |
| 164 | 165 |
msg = "We are not supposed to be called!" |
| 165 | 166 |
raise AssertionError(msg) |
| 166 | 167 |
|
| 167 | 168 |
|
| 168 |
-provider_entry1 = _types.SSHAgentSocketProviderEntry( |
|
| 169 |
+provider_entry1 = d_sasp.SSHAgentSocketProviderEntry( |
|
| 169 | 170 |
provider_entry_provider, "entry1", ("entry1a", "entry1b", "entry1c")
|
| 170 | 171 |
) |
| 171 | 172 |
"""A sample [`_types.SSHAgentSocketProviderEntry`][].""" |
| 172 | 173 |
|
| 173 |
-provider_entry2 = _types.SSHAgentSocketProviderEntry( |
|
| 174 |
+provider_entry2 = d_sasp.SSHAgentSocketProviderEntry( |
|
| 174 | 175 |
provider_entry_provider, "entry2", ("entry2d", "entry2e")
|
| 175 | 176 |
) |
| 176 | 177 |
|
| ... | ... |
@@ -51,6 +51,8 @@ if TYPE_CHECKING: |
| 51 | 51 |
|
| 52 | 52 |
from typing_extensions import Any |
| 53 | 53 |
|
| 54 |
+ import derivepassphrase_sshagentsocketprovider as d_sasp |
|
| 55 |
+ |
|
| 54 | 56 |
|
| 55 | 57 |
# Marks |
| 56 | 58 |
# ===== |
| ... | ... |
@@ -623,7 +625,7 @@ def ensure_singleton_client_if_non_reentrant_agent( |
| 623 | 625 |
|
| 624 | 626 |
def ensure_agent_subcontext( |
| 625 | 627 |
conn: ssh_agent.SSHAgentClient |
| 626 |
- | _types.SSHAgentSocket |
|
| 628 |
+ | d_sasp.SSHAgentSocket |
|
| 627 | 629 |
| Sequence[str] |
| 628 | 630 |
| None = None, |
| 629 | 631 |
) -> contextlib.AbstractContextManager[ssh_agent.SSHAgentClient]: |
| ... | ... |
@@ -44,6 +44,8 @@ if TYPE_CHECKING: |
| 44 | 44 |
|
| 45 | 45 |
from typing_extensions import Any |
| 46 | 46 |
|
| 47 |
+ import derivepassphrase_sshagentsocketprovider as d_sasp |
|
| 48 |
+ |
|
| 47 | 49 |
|
| 48 | 50 |
DUMMY_SERVICE = data.DUMMY_SERVICE |
| 49 | 51 |
DUMMY_PASSPHRASE = data.DUMMY_PASSPHRASE |
| ... | ... |
@@ -1154,7 +1156,7 @@ class TestMisc: |
| 1154 | 1156 |
"list_keys", |
| 1155 | 1157 |
callables.list_keys, |
| 1156 | 1158 |
) |
| 1157 |
- hint: ssh_agent.SSHAgentClient | _types.SSHAgentSocket | None |
|
| 1159 |
+ hint: ssh_agent.SSHAgentClient | d_sasp.SSHAgentSocket | None |
|
| 1158 | 1160 |
# TODO(the-13th-letter): Rewrite using structural pattern |
| 1159 | 1161 |
# matching. |
| 1160 | 1162 |
# https://the13thletter.info/derivepassphrase/latest/pycompatibility/#after-eol-py3.9 |
| ... | ... |
@@ -28,6 +28,8 @@ if TYPE_CHECKING: |
| 28 | 28 |
from collections.abc import Generator |
| 29 | 29 |
from typing import NoReturn |
| 30 | 30 |
|
| 31 |
+ import derivepassphrase_sshagentsocketprovider as d_sasp |
|
| 32 |
+ |
|
| 31 | 33 |
DUMMY_SERVICE = data.DUMMY_SERVICE |
| 32 | 34 |
DUMMY_PASSPHRASE = data.DUMMY_PASSPHRASE |
| 33 | 35 |
DUMMY_CONFIG_SETTINGS = data.DUMMY_CONFIG_SETTINGS |
| ... | ... |
@@ -578,7 +580,7 @@ class TestKeyBasic: |
| 578 | 580 |
}, |
| 579 | 581 |
}, |
| 580 | 582 |
main_config_str: str | None = None, |
| 581 |
- registry: dict[str, _types.SSHAgentSocketProvider | str | None] |
|
| 583 |
+ registry: dict[str, d_sasp.SSHAgentSocketProvider | str | None] |
|
| 582 | 584 |
| None = None, |
| 583 | 585 |
) -> Generator[machinery.CliRunner, None, None]: |
| 584 | 586 |
runner = machinery.CliRunner(mix_stderr=False) |
| ... | ... |
@@ -647,7 +649,7 @@ class TestKeyBasic: |
| 647 | 649 |
"services": {DUMMY_SERVICE: DUMMY_CONFIG_SETTINGS}
|
| 648 | 650 |
}, |
| 649 | 651 |
main_config_str: str | None = None, |
| 650 |
- registry: dict[str, _types.SSHAgentSocketProvider | str | None] |
|
| 652 |
+ registry: dict[str, d_sasp.SSHAgentSocketProvider | str | None] |
|
| 651 | 653 |
| None = None, |
| 652 | 654 |
multiline: bool = False, |
| 653 | 655 |
input: str | bytes | None = None, |
| ... | ... |
@@ -684,11 +686,11 @@ class TestKeyBasic: |
| 684 | 686 |
|
| 685 | 687 |
@pytest.fixture |
| 686 | 688 |
def provider_registry() -> dict[ |
| 687 |
- str, _types.SSHAgentSocketProvider | str | None |
|
| 689 |
+ str, d_sasp.SSHAgentSocketProvider | str | None |
|
| 688 | 690 |
]: |
| 689 | 691 |
"""Set up a controlled SSH agent socket provider registry.""" |
| 690 | 692 |
|
| 691 |
- def err() -> _types.SSHAgentSocket: |
|
| 693 |
+ def err() -> d_sasp.SSHAgentSocket: |
|
| 692 | 694 |
pytest.fail("Attempting to use the wrong SSH agent socket provider!")
|
| 693 | 695 |
|
| 694 | 696 |
return {
|
| ... | ... |
@@ -722,7 +724,7 @@ class TestKeyExplicitSSHAgentSocketProvider(TestKeyBasic): |
| 722 | 724 |
def test_explicit_ssh_agent_socket_provider( |
| 723 | 725 |
self, |
| 724 | 726 |
provider_registry: dict[ |
| 725 |
- str, _types.SSHAgentSocketProvider | str | None |
|
| 727 |
+ str, d_sasp.SSHAgentSocketProvider | str | None |
|
| 726 | 728 |
], |
| 727 | 729 |
config: _types.VaultConfig, |
| 728 | 730 |
on_command_line: bool, |
| ... | ... |
@@ -748,7 +750,7 @@ class TestKeyExplicitSSHAgentSocketProvider(TestKeyBasic): |
| 748 | 750 |
def test_explicit_ssh_agent_socket_provider_not_found( |
| 749 | 751 |
self, |
| 750 | 752 |
provider_registry: dict[ |
| 751 |
- str, _types.SSHAgentSocketProvider | str | None |
|
| 753 |
+ str, d_sasp.SSHAgentSocketProvider | str | None |
|
| 752 | 754 |
], |
| 753 | 755 |
config: _types.VaultConfig, |
| 754 | 756 |
on_command_line: bool, |
| ... | ... |
@@ -19,6 +19,7 @@ import pytest |
| 19 | 19 |
from hypothesis import strategies |
| 20 | 20 |
from typing_extensions import TypeAlias |
| 21 | 21 |
|
| 22 |
+import derivepassphrase_sshagentsocketprovider as d_sasp |
|
| 22 | 23 |
from derivepassphrase import _types, ssh_agent, vault |
| 23 | 24 |
from derivepassphrase._internals import cli_helpers |
| 24 | 25 |
from derivepassphrase.ssh_agent import socketprovider |
| ... | ... |
@@ -49,7 +50,7 @@ class Parametrize(pytest_machinery.Parametrize): |
| 49 | 50 |
[ |
| 50 | 51 |
importlib.metadata.EntryPoint( |
| 51 | 52 |
name=data.faulty_entry_callable.key, |
| 52 |
- group=socketprovider.SocketProvider.ENTRY_POINT_GROUP_NAME, |
|
| 53 |
+ group=d_sasp.ENTRY_POINT_GROUP_NAME, |
|
| 53 | 54 |
value="tests.data: faulty_entry_callable", |
| 54 | 55 |
), |
| 55 | 56 |
], |
| ... | ... |
@@ -59,7 +60,7 @@ class Parametrize(pytest_machinery.Parametrize): |
| 59 | 60 |
[ |
| 60 | 61 |
importlib.metadata.EntryPoint( |
| 61 | 62 |
name=data.faulty_entry_name_exists.key, |
| 62 |
- group=socketprovider.SocketProvider.ENTRY_POINT_GROUP_NAME, |
|
| 63 |
+ group=d_sasp.ENTRY_POINT_GROUP_NAME, |
|
| 63 | 64 |
value="tests.data: faulty_entry_name_exists", |
| 64 | 65 |
), |
| 65 | 66 |
], |
| ... | ... |
@@ -69,7 +70,7 @@ class Parametrize(pytest_machinery.Parametrize): |
| 69 | 70 |
[ |
| 70 | 71 |
importlib.metadata.EntryPoint( |
| 71 | 72 |
name=data.faulty_entry_alias_exists.key, |
| 72 |
- group=socketprovider.SocketProvider.ENTRY_POINT_GROUP_NAME, |
|
| 73 |
+ group=d_sasp.ENTRY_POINT_GROUP_NAME, |
|
| 73 | 74 |
value="tests.data: faulty_entry_alias_exists", |
| 74 | 75 |
), |
| 75 | 76 |
], |
| ... | ... |
@@ -84,12 +85,12 @@ class Parametrize(pytest_machinery.Parametrize): |
| 84 | 85 |
[ |
| 85 | 86 |
importlib.metadata.EntryPoint( |
| 86 | 87 |
name=data.ssh_auth_sock_on_posix_entry.key, |
| 87 |
- group=socketprovider.SocketProvider.ENTRY_POINT_GROUP_NAME, |
|
| 88 |
+ group=d_sasp.ENTRY_POINT_GROUP_NAME, |
|
| 88 | 89 |
value="tests.data: ssh_auth_sock_on_posix_entry", |
| 89 | 90 |
), |
| 90 | 91 |
importlib.metadata.EntryPoint( |
| 91 | 92 |
name=data.ssh_auth_sock_on_windows_entry.key, |
| 92 |
- group=socketprovider.SocketProvider.ENTRY_POINT_GROUP_NAME, |
|
| 93 |
+ group=d_sasp.ENTRY_POINT_GROUP_NAME, |
|
| 93 | 94 |
value="tests.data: ssh_auth_sock_on_windows_entry", |
| 94 | 95 |
), |
| 95 | 96 |
], |
| ... | ... |
@@ -99,12 +100,12 @@ class Parametrize(pytest_machinery.Parametrize): |
| 99 | 100 |
[ |
| 100 | 101 |
importlib.metadata.EntryPoint( |
| 101 | 102 |
name=callables.provider_entry1.key, |
| 102 |
- group=socketprovider.SocketProvider.ENTRY_POINT_GROUP_NAME, |
|
| 103 |
+ group=d_sasp.ENTRY_POINT_GROUP_NAME, |
|
| 103 | 104 |
value="tests.data.callables: provider_entry1", |
| 104 | 105 |
), |
| 105 | 106 |
importlib.metadata.EntryPoint( |
| 106 | 107 |
name=callables.provider_entry2.key, |
| 107 |
- group=socketprovider.SocketProvider.ENTRY_POINT_GROUP_NAME, |
|
| 108 |
+ group=d_sasp.ENTRY_POINT_GROUP_NAME, |
|
| 108 | 109 |
value="tests.data.callables: provider_entry2", |
| 109 | 110 |
), |
| 110 | 111 |
], |
| ... | ... |
@@ -439,7 +440,7 @@ class Strategies: |
| 439 | 440 |
|
| 440 | 441 |
@staticmethod |
| 441 | 442 |
def io_operations_on_handles() -> strategies.SearchStrategy[ |
| 442 |
- Callable[[_types.SSHAgentSocket], Any] |
|
| 443 |
+ Callable[[d_sasp.SSHAgentSocket], Any] |
|
| 443 | 444 |
]: |
| 444 | 445 |
"""Return an I/O operation on an SSH agent socket.""" |
| 445 | 446 |
return strategies.one_of( |
| ... | ... |
@@ -753,7 +754,7 @@ class TestSSHAgentSocketProviderRegistry: |
| 753 | 754 |
pytest.fail("Native SSH agent socket provider is unavailable?!")
|
| 754 | 755 |
# TODO(the-13th-letter): Rewrite using structural pattern matching. |
| 755 | 756 |
# https://the13thletter.info/derivepassphrase/latest/pycompatibility/#after-eol-py3.9 |
| 756 |
- target: _types.SSHAgentSocketProvider | str | None = ( |
|
| 757 |
+ target: d_sasp.SSHAgentSocketProvider | str | None = ( |
|
| 757 | 758 |
None |
| 758 | 759 |
if terminal == "unimplemented" |
| 759 | 760 |
else _types.BuiltinSSHAgentSocketProvider.NATIVE |
| ... | ... |
@@ -823,8 +824,8 @@ class TestSSHAgentSocketProviderRegistry: |
| 823 | 824 |
register = socketprovider.SocketProvider.register |
| 824 | 825 |
|
| 825 | 826 |
def ancestry_chain(name: str) -> Generator[str, None, None]: |
| 826 |
- current: _types.SSHAgentSocketProvider | str | None = name |
|
| 827 |
- seen: set[_types.SSHAgentSocketProvider | str | None] = set() |
|
| 827 |
+ current: d_sasp.SSHAgentSocketProvider | str | None = name |
|
| 828 |
+ seen: set[d_sasp.SSHAgentSocketProvider | str | None] = set() |
|
| 828 | 829 |
while isinstance(current, str) and current not in seen: |
| 829 | 830 |
yield current |
| 830 | 831 |
seen.add(current) |
| ... | ... |
@@ -889,7 +890,7 @@ class TestSSHAgentSocketProviderRegistry: |
| 889 | 890 |
) -> None: |
| 890 | 891 |
"""Registering new entries works.""" |
| 891 | 892 |
|
| 892 |
- def socket_provider() -> _types.SSHAgentSocket: |
|
| 893 |
+ def socket_provider() -> d_sasp.SSHAgentSocket: |
|
| 893 | 894 |
raise AssertionError |
| 894 | 895 |
|
| 895 | 896 |
names = ["spam", "ham", "eggs", "parrot"] |
| ... | ... |
@@ -7,6 +7,7 @@ |
| 7 | 7 |
from __future__ import annotations |
| 8 | 8 |
|
| 9 | 9 |
import contextlib |
| 10 |
+from typing import TYPE_CHECKING |
|
| 10 | 11 |
|
| 11 | 12 |
import pytest |
| 12 | 13 |
from hypothesis import stateful, strategies |
| ... | ... |
@@ -15,6 +16,9 @@ from derivepassphrase import _types |
| 15 | 16 |
from derivepassphrase.ssh_agent import socketprovider |
| 16 | 17 |
from tests.machinery import pytest as pytest_machinery |
| 17 | 18 |
|
| 19 |
+if TYPE_CHECKING: |
|
| 20 |
+ import derivepassphrase_sshagentsocketprovider as d_sasp |
|
| 21 |
+ |
|
| 18 | 22 |
# All tests in this module are heavy-duty tests. |
| 19 | 23 |
pytestmark = [pytest_machinery.heavy_duty] |
| 20 | 24 |
|
| ... | ... |
@@ -146,7 +150,7 @@ class SSHAgentSocketProviderRegistryStateMachine( |
| 146 | 150 |
) |
| 147 | 151 |
self.orig_registry = socketprovider.SocketProvider.registry |
| 148 | 152 |
self.registry: dict[ |
| 149 |
- str, _types.SSHAgentSocketProvider | str | None |
|
| 153 |
+ str, d_sasp.SSHAgentSocketProvider | str | None |
|
| 150 | 154 |
] = {
|
| 151 | 155 |
_types.BuiltinSSHAgentSocketProvider.SSH_AUTH_SOCK_ON_POSIX: ( |
| 152 | 156 |
self.orig_registry[ |
| ... | ... |
@@ -176,14 +180,14 @@ class SSHAgentSocketProviderRegistryStateMachine( |
| 176 | 180 |
self.monkeypatch.setattr( |
| 177 | 181 |
socketprovider.SocketProvider, "registry", self.registry |
| 178 | 182 |
) |
| 179 |
- self.model: dict[str, _types.SSHAgentSocketProvider | None] = {}
|
|
| 183 |
+ self.model: dict[str, d_sasp.SSHAgentSocketProvider | None] = {}
|
|
| 180 | 184 |
|
| 181 | 185 |
known_keys: stateful.Bundle[str] = stateful.Bundle("known_keys")
|
| 182 | 186 |
"""""" |
| 183 | 187 |
new_keys: stateful.Bundle[str] = stateful.Bundle("new_keys")
|
| 184 | 188 |
"""""" |
| 185 | 189 |
|
| 186 |
- def sample_provider(self) -> _types.SSHAgentSocket: |
|
| 190 |
+ def sample_provider(self) -> d_sasp.SSHAgentSocket: |
|
| 187 | 191 |
raise AssertionError |
| 188 | 192 |
|
| 189 | 193 |
@stateful.initialize( |
| 190 | 194 |