Marco Ricci commited on 2024-07-19 18:58:12
Zeige 8 geänderte Dateien mit 44 Einfügungen und 29 Löschungen.
(One of them actually was a bug: an f-string missing the leading `f`.)
... | ... |
@@ -81,7 +81,6 @@ detached = false |
81 | 81 |
[tool.hatch.envs.types] |
82 | 82 |
extra-dependencies = [ |
83 | 83 |
"mypy>=1.0.0", |
84 |
- "pytest", |
|
85 | 84 |
] |
86 | 85 |
[tool.hatch.envs.types.scripts] |
87 | 86 |
check = "mypy --install-types --non-interactive {args:src/derivepassphrase tests}" |
... | ... |
@@ -115,3 +114,13 @@ exclude_also = [ |
115 | 114 |
"raise NotImplementedError", |
116 | 115 |
'assert False', |
117 | 116 |
] |
117 |
+ |
|
118 |
+[tool.ruff] |
|
119 |
+line-length = 79 |
|
120 |
+src = ["src"] |
|
121 |
+ |
|
122 |
+[tool.ruff.format] |
|
123 |
+quote-style = 'single' |
|
124 |
+ |
|
125 |
+[tool.ruff.lint.pydocstyle] |
|
126 |
+convention = 'google' |
... | ... |
@@ -810,7 +810,7 @@ def derivepassphrase( |
810 | 810 |
with outfile: |
811 | 811 |
json.dump(configuration, outfile) |
812 | 812 |
except OSError as e: |
813 |
- ctx.fail('cannot write config: {e.strerror}') |
|
813 |
+ ctx.fail(f'cannot write config: {e.strerror}') |
|
814 | 814 |
else: |
815 | 815 |
configuration = get_config() |
816 | 816 |
# This block could be type checked more stringently, but this |
... | ... |
@@ -874,7 +874,7 @@ def derivepassphrase( |
874 | 874 |
_save_config(configuration) |
875 | 875 |
else: |
876 | 876 |
if not service: |
877 |
- raise click.UsageError(f'SERVICE is required') |
|
877 |
+ raise click.UsageError('SERVICE is required') |
|
878 | 878 |
kwargs: dict[str, Any] = {k: v for k, v in settings.items() |
879 | 879 |
if k in service_keys and v is not None} |
880 | 880 |
# If either --key or --phrase are given, use that setting. |
... | ... |
@@ -885,7 +885,10 @@ def derivepassphrase( |
885 | 885 |
# these above cases, set the phrase via |
886 | 886 |
# derivepassphrase.Vault.phrase_from_key if a key is |
887 | 887 |
# given. Finally, if nothing is set, error out. |
888 |
- key_to_phrase = lambda key: dpp.Vault.phrase_from_key( |
|
888 |
+ def key_to_phrase( |
|
889 |
+ key: str | bytes | bytearray |
|
890 |
+ ) -> bytes | bytearray: |
|
891 |
+ return dpp.Vault.phrase_from_key( |
|
889 | 892 |
base64.standard_b64decode(key)) |
890 | 893 |
if use_key or use_phrase: |
891 | 894 |
if use_key: |
... | ... |
@@ -157,7 +157,8 @@ class SSHAgentClient: |
157 | 157 |
Examples: |
158 | 158 |
>>> bytes(SSHAgentClient.unstring(b'\x00\x00\x00\x07ssh-rsa')) |
159 | 159 |
b'ssh-rsa' |
160 |
- >>> bytes(SSHAgentClient.unstring(SSHAgentClient.string(b'ssh-ed25519'))) |
|
160 |
+ >>> bytes(SSHAgentClient.unstring( |
|
161 |
+ ... SSHAgentClient.string(b'ssh-ed25519'))) |
|
161 | 162 |
b'ssh-ed25519' |
162 | 163 |
|
163 | 164 |
""" |
... | ... |
@@ -41,7 +41,7 @@ idwcakUGCekJD/vCEml2AAAAG3Rlc3Qga2V5IHdpdGhvdXQgcGFzc3BocmFzZQEC |
41 | 41 |
-----END OPENSSH PRIVATE KEY----- |
42 | 42 |
''', |
43 | 43 |
'public_key': rb'''ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIF4gWgm1gJIXw//Mkhv5MEwidwcakUGCekJD/vCEml2 test key without passphrase |
44 |
-''', |
|
44 |
+''', # noqa: E501 |
|
45 | 45 |
'public_key_data': bytes.fromhex(''' |
46 | 46 |
00 00 00 0b 73 73 68 2d 65 64 32 35 35 31 39 |
47 | 47 |
00 00 00 20 |
... | ... |
@@ -56,7 +56,7 @@ idwcakUGCekJD/vCEml2AAAAG3Rlc3Qga2V5IHdpdGhvdXQgcGFzc3BocmFzZQEC |
56 | 56 |
0d 08 1f ec f8 73 9b 8c 5f 55 39 16 7c 53 54 2c |
57 | 57 |
1e 52 bb 30 ed 7f 89 e2 2f 69 51 55 d8 9e a6 02 |
58 | 58 |
'''), |
59 |
- 'derived_passphrase': rb'8JgZgGwal9UmA27M42WPhmYHExkTCSEzM/nkNlMdr/0NCB/s+HObjF9VORZ8U1QsHlK7MO1/ieIvaVFV2J6mAg==', |
|
59 |
+ 'derived_passphrase': rb'8JgZgGwal9UmA27M42WPhmYHExkTCSEzM/nkNlMdr/0NCB/s+HObjF9VORZ8U1QsHlK7MO1/ieIvaVFV2J6mAg==', # noqa: E501 |
|
60 | 60 |
}, |
61 | 61 |
# Currently only supported by PuTTY (which is deficient in other |
62 | 62 |
# niceties of the SSH agent and the agent's client). |
... | ... |
@@ -73,7 +73,7 @@ dGhvdXQgcGFzc3BocmFzZQECAwQFBgcICQ== |
73 | 73 |
-----END OPENSSH PRIVATE KEY----- |
74 | 74 |
''', |
75 | 75 |
'public_key': rb'''ssh-ed448 AAAACXNzaC1lZDQ0OAAAADni9nLTT1a7zATGO8RveGq0vPUY7/53m+YZRsStZDgBQ72ZgtPMckdzabiz7JbM/b0JzcRzGLMsbwA= test key without passphrase |
76 |
-''', |
|
76 |
+''', # noqa: E501 |
|
77 | 77 |
'public_key_data': bytes.fromhex(''' |
78 | 78 |
00 00 00 09 73 73 68 2d 65 64 34 34 38 |
79 | 79 |
00 00 00 39 |
... | ... |
@@ -94,7 +94,7 @@ dGhvdXQgcGFzc3BocmFzZQECAwQFBgcICQ== |
94 | 94 |
db bd 77 7c 80 20 7f 3a 48 61 f6 1f ae a9 5e 53 |
95 | 95 |
7b e0 9d 93 1e ea dc eb b5 cd 56 4c ea 8f 08 00 |
96 | 96 |
'''), |
97 |
- 'derived_passphrase': rb'Bob0ZKSmutnDIsSTSZn8Ed5nlwjy2Lc8LBPnxRwekqYO2C9tgQOCAONy5DJtctJtMoQ/zKkeVywAmrOZ3kXazi7R2+WJ8zW+JFiQxsoE8NuIgNu9d3yAIH86SGH2H66pXlN74J2THurc67XNVkzqjwgA', |
|
97 |
+ 'derived_passphrase': rb'Bob0ZKSmutnDIsSTSZn8Ed5nlwjy2Lc8LBPnxRwekqYO2C9tgQOCAONy5DJtctJtMoQ/zKkeVywAmrOZ3kXazi7R2+WJ8zW+JFiQxsoE8NuIgNu9d3yAIH86SGH2H66pXlN74J2THurc67XNVkzqjwgA', # noqa: E501 |
|
98 | 98 |
}, |
99 | 99 |
'rsa': { |
100 | 100 |
'private_key': rb'''-----BEGIN OPENSSH PRIVATE KEY----- |
... | ... |
@@ -137,7 +137,7 @@ Bgp6142WnSCQAAABt0ZXN0IGtleSB3aXRob3V0IHBhc3NwaHJhc2UB |
137 | 137 |
-----END OPENSSH PRIVATE KEY----- |
138 | 138 |
''', |
139 | 139 |
'public_key': rb'''ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCxoe7pezhxWy4NI0mUwKqg9WCYOAS+IjxN9eYcqpfcmQiojcuy9XsiN/xYJ1O94SrsKS5mEia2xHnYA4RUChTyYNcM2v6cnnBQ/N/VQhpGMN7SVxdbhKUXTWFCwbjBgO6rGyHB6WtoH8vd7TOEPt+NgcXwhsWyoaUUdYTA62V+GF9vEmxMaC4ubgDz+B0QkPnauSoNxmkhcIe0lsLNb1pClZyz88PDnKXCX/d0HuN/HJ+sbPg7dCvOyqFYSyKn3uY6bCXqoIdurxXzH3O7z0P8f5sbmKOrGGKNuNxVRbeVl/D/3uDL0nqsbfUc1qvkfwbJwtMXC4IV6kOZMSk2BAsqh7x48gQ+rhYeEVSi8F3CWs4HJQoqrGt7K9a3mCSlMBHP70u3w6ME7eumoryxlUofewTd17ZEkzdX08l2ZlKzZvwQUrc+xQZ2Uw8z2mfW6Ti4gi0pYGaig7Ke4PwuXpo/C5YAWfeXycsvJZ2uaYRjMdZeJGNAnHLUGLkBscw5aI8= test key without passphrase |
140 |
-''', |
|
140 |
+''', # noqa: E501 |
|
141 | 141 |
'public_key_data': bytes.fromhex(''' |
142 | 142 |
00 00 00 07 73 73 68 2d 72 73 61 |
143 | 143 |
00 00 00 03 01 00 01 |
... | ... |
@@ -195,7 +195,7 @@ Bgp6142WnSCQAAABt0ZXN0IGtleSB3aXRob3V0IHBhc3NwaHJhc2UB |
195 | 195 |
de 69 2c 48 62 d9 fd d1 9b 6b b0 49 db d3 ff 38 |
196 | 196 |
e7 10 d9 2d ce 9f 0d 5e 09 7b 37 d2 7b c3 bf ce |
197 | 197 |
'''), |
198 |
- 'derived_passphrase': rb'ohB8Lva7U6h0KqEZma2Bvnmc7dadCU5uxRhIM5B3mWj3ngNazU4Y64l9haLurkqS9m/Ouf6GfyprMdpuGv6ipYi4RH+hdnOz7HW10Ka5FZdlCRN9lCHR+10PiyMEd8LDVSKxoAmK9Tgq1n8bhymgJdMlb8tkYQeY3BTFhPiSJF5QEWtJ5fDMKcspqRnYp3EfkQsFsQFLwl8ApbYhv/gsnWebRzsKSWt5Lfwd7Ayw5Sci1an408P530ho6fvvPNwmv8/qKUMBpuPFUZX0Zm2KVeJH7OgwRUyuR+fJpCGLZLq2iPYh+HO5yxGheHWSxlrlZP7tQtmVmeYrbzwWPCh0pHIvDT8sM2eqNRmO57URL7P3asUC4m+jQuNiGZkD6qUg56HjvMgGo7V81nZd329gRoMqCADW09mkwUGM+GBWRYHaO6IWH55OdYMX2sNTwz4ZpBu80im4eGEreOaxUrDV7N5pLEhi2f3Rm2uwSdvT/zjnENktzp8NXgl7N9J7w7/O', |
|
198 |
+ 'derived_passphrase': rb'ohB8Lva7U6h0KqEZma2Bvnmc7dadCU5uxRhIM5B3mWj3ngNazU4Y64l9haLurkqS9m/Ouf6GfyprMdpuGv6ipYi4RH+hdnOz7HW10Ka5FZdlCRN9lCHR+10PiyMEd8LDVSKxoAmK9Tgq1n8bhymgJdMlb8tkYQeY3BTFhPiSJF5QEWtJ5fDMKcspqRnYp3EfkQsFsQFLwl8ApbYhv/gsnWebRzsKSWt5Lfwd7Ayw5Sci1an408P530ho6fvvPNwmv8/qKUMBpuPFUZX0Zm2KVeJH7OgwRUyuR+fJpCGLZLq2iPYh+HO5yxGheHWSxlrlZP7tQtmVmeYrbzwWPCh0pHIvDT8sM2eqNRmO57URL7P3asUC4m+jQuNiGZkD6qUg56HjvMgGo7V81nZd329gRoMqCADW09mkwUGM+GBWRYHaO6IWH55OdYMX2sNTwz4ZpBu80im4eGEreOaxUrDV7N5pLEhi2f3Rm2uwSdvT/zjnENktzp8NXgl7N9J7w7/O', # noqa: E501 |
|
199 | 199 |
}, |
200 | 200 |
} |
201 | 201 |
|
... | ... |
@@ -224,7 +224,7 @@ u7HfrQhdOiKSa+ZO9AAojbURqrLDRfBJa5dXn2AAAAFQDJHfenj4EJ9WkehpdJatPBlqCW |
224 | 224 |
-----END OPENSSH PRIVATE KEY----- |
225 | 225 |
''', |
226 | 226 |
'public_key': rb'''ssh-dss AAAAB3NzaC1kc3MAAACBALsoBleoEY1UsFA+twxgCg1bngGEPxoiF7sENZjMlyxoy3vZUpKSC5nz5dHudFrQL9mwGL64mnR2nHL1kxM5Zfi7lg8x5BxcR0YTFkh+KYapI4CzLp8KV3Yh8lklkTFwKaF71KyOx3dhIA8lGW45cVBz3kxmhHmEzCUgMPxDOsTtAAAAFQD32c5k6B3tocxUahelQQFyfseiywAAAIAuvYCDeHEzesp3HNVTDx9fRVU9c77f4qvyEZ7Qpz/s3BVoFUvUZDx96cG5bKekBRsfTCjeHXCQH/yFfqn5Lxye7msgGVS5U3AvD9shiiEr3wt+pNgr9X6DooP7ybfjC8SJdmarLBjnifZuSxyHU2q+P+02kvMTFLH9dLSRIzVqKAAAAIBtA1E9xUS4YOsRx/7GDm2AB6M9cE9ev8myz4KGTriSbeaKsxiMBbJZi1VyBP7uE5jG1hGKfwvIwuopGaprRDlSu8N8KGAuG+wb1hJv8ynDmqbw+IdJp/CGRrP+17f7yEqiCqh7ux360IXToikmvmTvQAKI21Eaqyw0XwSWuXV59g== test key without passphrase |
227 |
-''', |
|
227 |
+''', # noqa: E501 |
|
228 | 228 |
'public_key_data': bytes.fromhex(''' |
229 | 229 |
00 00 00 07 73 73 68 2d 64 73 73 |
230 | 230 |
00 00 00 81 00 |
... | ... |
@@ -272,7 +272,7 @@ dGhvdXQgcGFzc3BocmFzZQECAwQ= |
272 | 272 |
-----END OPENSSH PRIVATE KEY----- |
273 | 273 |
''', |
274 | 274 |
'public_key': rb'''ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBMttTTMPCyTYO+n5Vgiuw1V/mBbDPZLdJnxNvGJBGSmcZJWrIigck4lz41Ai0BrvGUn/xnqB/PntndqlSRowmbo= test key without passphrase |
275 |
-''', |
|
275 |
+''', # noqa: E501 |
|
276 | 276 |
'public_key_data': bytes.fromhex(''' |
277 | 277 |
00 00 00 13 65 63 64 73 61 2d 73 68 61 32 2d 6e |
278 | 278 |
69 73 74 70 32 35 36 |
... | ... |
@@ -299,7 +299,7 @@ JAu0J3Q+cypZuKQVAAAAMQD5sTy8p+B1cn/DhOmXquui1BcxvASqzzevkBlbQoBa73y04B |
299 | 299 |
-----END OPENSSH PRIVATE KEY----- |
300 | 300 |
''', |
301 | 301 |
'public_key': rb'''ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBKCQ6OQC+ru/m8e6PcoEvj8QBZyfmFkPIpxvJXR4EwYWruEpdCVmohqEtWp4xHRCqaTE0nauXLZUdxed6re9n718ixYI51iTlY/c1k/O/3XVefvBsSQLtCd0PnMqWbikFQ== test key without passphrase |
302 |
-''', |
|
302 |
+''', # noqa: E501 |
|
303 | 303 |
'public_key_data': bytes.fromhex(''' |
304 | 304 |
00 00 00 13 |
305 | 305 |
65 63 64 73 61 2d 73 68 61 32 2d 6e 69 73 74 70 |
... | ... |
@@ -335,7 +335,7 @@ DUMMY_PHRASE_FROM_KEY1_RAW = ( |
335 | 335 |
b'\x1d\xaf\xfd\r\x08\x1f\xec\xf8s\x9b\x8c_U9\x16|ST,' |
336 | 336 |
b'\x1eR\xbb0\xed\x7f\x89\xe2/iQU\xd8\x9e\xa6\x02' |
337 | 337 |
) |
338 |
-DUMMY_PHRASE_FROM_KEY1 = b'8JgZgGwal9UmA27M42WPhmYHExkTCSEzM/nkNlMdr/0NCB/s+HObjF9VORZ8U1QsHlK7MO1/ieIvaVFV2J6mAg==' |
|
338 |
+DUMMY_PHRASE_FROM_KEY1 = b'8JgZgGwal9UmA27M42WPhmYHExkTCSEzM/nkNlMdr/0NCB/s+HObjF9VORZ8U1QsHlK7MO1/ieIvaVFV2J6mAg==' # noqa: E501 |
|
339 | 339 |
|
340 | 340 |
skip_if_no_agent = pytest.mark.skipif( |
341 | 341 |
not os.environ.get('SSH_AUTH_SOCK'), reason='running SSH agent required') |
... | ... |
@@ -137,11 +137,10 @@ class TestVault: |
137 | 137 |
assert v._estimate_sufficient_hash_length(8.0) >= entropy |
138 | 138 |
|
139 | 139 |
def test_222_hash_length_estimation(self) -> None: |
140 |
- v = Vault(phrase=self.phrase) |
|
141 |
- v2 = Vault(phrase=self.phrase, lower=0, upper=0, number=0, |
|
140 |
+ v = Vault(phrase=self.phrase, lower=0, upper=0, number=0, |
|
142 | 141 |
symbol=0, space=1, length=1) |
143 |
- assert v2._entropy() == 0.0 |
|
144 |
- assert v2._estimate_sufficient_hash_length() > 0 |
|
142 |
+ assert v._entropy() == 0.0 |
|
143 |
+ assert v._estimate_sufficient_hash_length() > 0 |
|
145 | 144 |
|
146 | 145 |
@pytest.mark.parametrize(['service', 'expected'], [ |
147 | 146 |
(b'google', google_phrase), |
... | ... |
@@ -763,7 +763,7 @@ Our menu: |
763 | 763 |
Your selection? (1-10, leave empty to abort): 9 |
764 | 764 |
A fine choice: Spam, spam, spam, spam, spam, spam, baked beans, spam, spam, spam and spam |
765 | 765 |
(Note: Vikings strictly optional.) |
766 |
-''', 'driver program produced unexpected output' |
|
766 |
+''', 'driver program produced unexpected output' # noqa: E501 |
|
767 | 767 |
result = runner.invoke(driver, ['--heading='], input='', |
768 | 768 |
catch_exceptions=True) |
769 | 769 |
assert result.exit_code > 0, 'driver program succeeded?!' |
... | ... |
@@ -778,7 +778,7 @@ A fine choice: Spam, spam, spam, spam, spam, spam, baked beans, spam, spam, spam |
778 | 778 |
[8] Spam, spam, spam, egg and spam |
779 | 779 |
[9] Spam, spam, spam, spam, spam, spam, baked beans, spam, spam, spam and spam |
780 | 780 |
[10] Lobster thermidor aux crevettes with a mornay sauce garnished with truffle paté, brandy and a fried egg on top and spam |
781 |
-Your selection? (1-10, leave empty to abort): \n''', ( |
|
781 |
+Your selection? (1-10, leave empty to abort): \n''', ( # noqa: E501 |
|
782 | 782 |
'driver program produced unexpected output' |
783 | 783 |
) |
784 | 784 |
assert isinstance(result.exception, IndexError), ( |
... | ... |
@@ -800,7 +800,8 @@ Your selection? (1-10, leave empty to abort): \n''', ( |
800 | 800 |
else: |
801 | 801 |
click.echo('Great!') |
802 | 802 |
runner = click.testing.CliRunner(mix_stderr=True) |
803 |
- result = runner.invoke(driver, ['Will replace with spam. Confirm, y/n?'], |
|
803 |
+ result = runner.invoke(driver, |
|
804 |
+ ['Will replace with spam. Confirm, y/n?'], |
|
804 | 805 |
input='y') |
805 | 806 |
assert result.exit_code == 0, 'driver program failed' |
806 | 807 |
assert result.stdout == '''\ |
... | ... |
@@ -825,7 +826,8 @@ Boo. |
825 | 826 |
|
826 | 827 |
def test_103_prompt_for_passphrase(self, monkeypatch: Any) -> None: |
827 | 828 |
monkeypatch.setattr(click, 'prompt', |
828 |
- lambda *a, **kw: json.dumps({'args': a, 'kwargs': kw})) |
|
829 |
+ lambda *a, **kw: |
|
830 |
+ json.dumps({'args': a, 'kwargs': kw})) |
|
829 | 831 |
res = json.loads(cli._prompt_for_passphrase()) |
830 | 832 |
assert 'args' in res and 'kwargs' in res, ( |
831 | 833 |
'missing arguments to passphrase prompt' |
... | ... |
@@ -919,4 +921,4 @@ Boo. |
919 | 921 |
except Exception as e: # pragma: no cover |
920 | 922 |
exception = e |
921 | 923 |
finally: |
922 |
- assert exception == None, 'exception querying suitable SSH keys' |
|
924 |
+ assert exception is None, 'exception querying suitable SSH keys' |
... | ... |
@@ -88,7 +88,8 @@ class TestSequin: |
88 | 88 |
|
89 | 89 |
def test_211_shifting(self): |
90 | 90 |
seq = sequin.Sequin([1, 0, 1, 0, 0, 1, 0, 0, 0, 1], is_bitstring=True) |
91 |
- assert seq.bases == {2: collections.deque([1, 0, 1, 0, 0, 1, 0, 0, 0, 1])} |
|
91 |
+ assert seq.bases == {2: collections.deque([ |
|
92 |
+ 1, 0, 1, 0, 0, 1, 0, 0, 0, 1])} |
|
92 | 93 |
# |
93 | 94 |
assert seq._all_or_nothing_shift(3) == (1, 0, 1) |
94 | 95 |
assert seq._all_or_nothing_shift(3) == (0, 0, 1) |
... | ... |
@@ -124,7 +124,7 @@ class TestAgentInteraction: |
124 | 124 |
def test_200_sign_data_via_agent(self, keytype, data_dict): |
125 | 125 |
private_key = data_dict['private_key'] |
126 | 126 |
try: |
127 |
- result = subprocess.run(['ssh-add', '-t', '30', '-q', '-'], |
|
127 |
+ _ = subprocess.run(['ssh-add', '-t', '30', '-q', '-'], |
|
128 | 128 |
input=private_key, check=True, |
129 | 129 |
capture_output=True) |
130 | 130 |
except subprocess.CalledProcessError as e: |
... | ... |
@@ -161,7 +161,7 @@ class TestAgentInteraction: |
161 | 161 |
def test_201_sign_data_via_agent_unsupported(self, keytype, data_dict): |
162 | 162 |
private_key = data_dict['private_key'] |
163 | 163 |
try: |
164 |
- result = subprocess.run(['ssh-add', '-t', '30', '-q', '-'], |
|
164 |
+ _ = subprocess.run(['ssh-add', '-t', '30', '-q', '-'], |
|
165 | 165 |
input=private_key, check=True, |
166 | 166 |
capture_output=True) |
167 | 167 |
except subprocess.CalledProcessError as e: # pragma: no cover |
... | ... |
@@ -178,7 +178,7 @@ class TestAgentInteraction: |
178 | 178 |
key_comment_pairs = {bytes(k): bytes(c) |
179 | 179 |
for k, c in client.list_keys()} |
180 | 180 |
public_key_data = data_dict['public_key_data'] |
181 |
- expected_signature = data_dict['expected_signature'] |
|
181 |
+ _ = data_dict['expected_signature'] |
|
182 | 182 |
if public_key_data not in key_comment_pairs: # pragma: no cover |
183 | 183 |
pytest.skip('prerequisite SSH key not loaded') |
184 | 184 |
signature = bytes(client.sign( |
... | ... |
@@ -211,7 +211,7 @@ class TestAgentInteraction: |
211 | 211 |
keys = [pair.key for pair in tests.list_keys_singleton() |
212 | 212 |
if key_is_suitable(pair.key)] |
213 | 213 |
index = '1' |
214 |
- text = f'Use this key? yes\n' |
|
214 |
+ text = 'Use this key? yes\n' |
|
215 | 215 |
else: |
216 | 216 |
monkeypatch.setattr(ssh_agent_client.SSHAgentClient, |
217 | 217 |
'list_keys', tests.list_keys) |
218 | 218 |