Marco Ricci commited on 2024-06-22 21:19:30
Zeige 1 geänderte Dateien mit 18 Einfügungen und 24 Löschungen.
... | ... |
@@ -35,16 +35,8 @@ class SSHAgentClient: |
35 | 35 |
issue other requests as defined in the protocol---it's merely the |
36 | 36 |
wrapper functions and the protocol numbers table that are missing. |
37 | 37 |
|
38 |
- Attributes: |
|
39 |
- connection: |
|
40 |
- The socket connected to the SSH agent. |
|
41 |
- ssh_auth_sock: |
|
42 |
- The UNIX domain socket the SSH agent is listening on. Unset |
|
43 |
- if socket auto-discovery is not used. |
|
44 |
- |
|
45 | 38 |
""" |
46 |
- connection: socket.socket |
|
47 |
- ssh_auth_sock: str | None |
|
39 |
+ _connection: socket.socket |
|
48 | 40 |
def __init__( |
49 | 41 |
self, /, *, socket: socket.socket | None = None, timeout: int = 125 |
50 | 42 |
) -> None: |
... | ... |
@@ -62,41 +54,43 @@ class SSHAgentClient: |
62 | 54 |
SSH on high-latency networks (e.g. Tor). |
63 | 55 |
|
64 | 56 |
""" |
65 |
- self.ssh_auth_sock = None |
|
66 | 57 |
if socket is not None: |
67 |
- self.connection = socket |
|
58 |
+ self._connection = socket |
|
68 | 59 |
else: |
69 |
- self.connection = _socket.socket(family=_socket.AF_UNIX) |
|
60 |
+ self._connection = _socket.socket(family=_socket.AF_UNIX) |
|
70 | 61 |
try: |
71 |
- self.connection.getpeername() |
|
62 |
+ # Test whether the socket is connected. |
|
63 |
+ self._connection.getpeername() |
|
72 | 64 |
except OSError as e: |
73 |
- if e.errno != errno.ENOTCONN: |
|
65 |
+ # This condition is hard to test purposefully, so exclude |
|
66 |
+ # from coverage. |
|
67 |
+ if e.errno != errno.ENOTCONN: # pragma: no cover |
|
74 | 68 |
raise |
75 | 69 |
try: |
76 |
- self.ssh_auth_sock = os.environ['SSH_AUTH_SOCK'] |
|
70 |
+ ssh_auth_sock = os.environ['SSH_AUTH_SOCK'] |
|
77 | 71 |
except KeyError as e: |
78 | 72 |
raise RuntimeError( |
79 | 73 |
"Can't find running ssh-agent: missing SSH_AUTH_SOCK" |
80 | 74 |
) from e |
81 |
- self.connection.settimeout(timeout) |
|
75 |
+ self._connection.settimeout(timeout) |
|
82 | 76 |
try: |
83 |
- self.connection.connect(self.ssh_auth_sock) |
|
77 |
+ self._connection.connect(ssh_auth_sock) |
|
84 | 78 |
except FileNotFoundError as e: |
85 | 79 |
raise RuntimeError( |
86 | 80 |
"Can't find running ssh-agent: unusable SSH_AUTH_SOCK" |
87 | 81 |
) from e |
88 | 82 |
|
89 | 83 |
def __enter__(self) -> Self: |
90 |
- """Context management: defer to `self.connection`.""" |
|
91 |
- self.connection.__enter__() |
|
84 |
+ """Close socket connection upon context manager completion.""" |
|
85 |
+ self._connection.__enter__() |
|
92 | 86 |
return self |
93 | 87 |
|
94 | 88 |
def __exit__( |
95 | 89 |
self, exc_type: Any, exc_val: Any, exc_tb: Any |
96 | 90 |
) -> bool: |
97 |
- """Context management: defer to `self.connection`.""" |
|
91 |
+ """Close socket connection upon context manager completion.""" |
|
98 | 92 |
return bool( |
99 |
- self.connection.__exit__( |
|
93 |
+ self._connection.__exit__( |
|
100 | 94 |
exc_type, exc_val, exc_tb) # type: ignore[func-returns-value] |
101 | 95 |
) |
102 | 96 |
|
... | ... |
@@ -200,12 +194,12 @@ class SSHAgentClient: |
200 | 194 |
""" |
201 | 195 |
request_message = bytearray([code]) |
202 | 196 |
request_message.extend(payload) |
203 |
- self.connection.sendall(self.string(request_message)) |
|
204 |
- chunk = self.connection.recv(4) |
|
197 |
+ self._connection.sendall(self.string(request_message)) |
|
198 |
+ chunk = self._connection.recv(4) |
|
205 | 199 |
if len(chunk) < 4: |
206 | 200 |
raise EOFError('cannot read response length') |
207 | 201 |
response_length = int.from_bytes(chunk, 'big', signed=False) |
208 |
- response = self.connection.recv(response_length) |
|
202 |
+ response = self._connection.recv(response_length) |
|
209 | 203 |
if len(response) < response_length: |
210 | 204 |
raise EOFError('truncated response from SSH agent') |
211 | 205 |
return response[0], response[1:] |
212 | 206 |