Marco Ricci commited on 2026-06-24 18:35:06
Zeige 19 geänderte Dateien mit 95 Einfügungen und 74 Löschungen.
Add a pyrefly configuration, which newer versions of hatch and VS Code prefer over mypy. Fix violations that pyrefly complains about, but mypy doesn't, e.g., `del (list_of_variables)`. Remove unnecessary casts -- pyrefly warns on those, but mypy doesn't -- and document those necessary casts explicitly, even if they are a tool deficiency (usually mypy). Conversely, add conversions or tighter type bounds where necessary, usually when interacting with third-party libraries that use too lax typing because mypy doesn't complain (cryptography, click). To be fair, I have caused my fair share of those as well. Finally, fix the "devsetup" mkdocs configuration that should have been showing private members in the API documentation (if document), but wasn't.
| ... | ... |
@@ -434,6 +434,23 @@ implicit_reexport = false |
| 434 | 434 |
sqlite_cache = true |
| 435 | 435 |
enable_error_code = ['ignore-without-code'] |
| 436 | 436 |
|
| 437 |
+[tool.pyrefly] |
|
| 438 |
+project-includes = [ |
|
| 439 |
+ "src/**/*.py", |
|
| 440 |
+ "tests/**/*.py", |
|
| 441 |
+] |
|
| 442 |
+search-path = [ |
|
| 443 |
+ "src", |
|
| 444 |
+ "other-stubs", |
|
| 445 |
+ ".", |
|
| 446 |
+] |
|
| 447 |
+preset = "legacy" |
|
| 448 |
+infer-return-types = "never" |
|
| 449 |
+permissive-ignores = true |
|
| 450 |
+ |
|
| 451 |
+[tool.pyrefly.errors] |
|
| 452 |
+unnecessary-type-conversion = "ignore" |
|
| 453 |
+ |
|
| 437 | 454 |
[tool.pytest.ini_options] |
| 438 | 455 |
addopts = '--doctest-modules --dist=loadgroup --import-mode=importlib' |
| 439 | 456 |
pythonpath = ['src'] |
| ... | ... |
@@ -136,7 +136,7 @@ def shell_complete_service( |
| 136 | 136 |
ctx: click.Context, |
| 137 | 137 |
parameter: click.Parameter, |
| 138 | 138 |
value: str, |
| 139 |
-) -> list[str | click.shell_completion.CompletionItem]: |
|
| 139 |
+) -> list[str]: |
|
| 140 | 140 |
"""Return known vault service names as completion items. |
| 141 | 141 |
|
| 142 | 142 |
Service names are looked up in the vault configuration file. All |
| ... | ... |
@@ -137,7 +137,7 @@ class DebugTranslations(gettext.NullTranslations): |
| 137 | 137 |
cache = _debug_translation_message_cache |
| 138 | 138 |
for enum_class in MSG_TEMPLATE_CLASSES: |
| 139 | 139 |
for member in enum_class.__members__.values(): |
| 140 |
- value = cast("TranslatableString", member.value)
|
|
| 140 |
+ value = member.value |
|
| 141 | 141 |
queue: list[tuple[TranslatableString, frozenset[str]]] = [ |
| 142 | 142 |
(value, frozenset()) |
| 143 | 143 |
] |
| ... | ... |
@@ -170,7 +170,7 @@ class DebugTranslations(gettext.NullTranslations): |
| 170 | 170 |
return message if not message_plural or n == 1 else message_plural |
| 171 | 171 |
return cls._format_enum_name_maybe_with_fields( |
| 172 | 172 |
enum_name=str(enum_value), |
| 173 |
- ts=cast("TranslatableString", enum_value.value),
|
|
| 173 |
+ ts=enum_value.value, |
|
| 174 | 174 |
trimmed=trimmed, |
| 175 | 175 |
) |
| 176 | 176 |
|
| ... | ... |
@@ -194,7 +194,6 @@ class DebugTranslations(gettext.NullTranslations): |
| 194 | 194 |
def gettext( |
| 195 | 195 |
self, |
| 196 | 196 |
message: str, |
| 197 |
- /, |
|
| 198 | 197 |
) -> str: |
| 199 | 198 |
return self._locate_message(message) |
| 200 | 199 |
|
| ... | ... |
@@ -204,7 +203,6 @@ class DebugTranslations(gettext.NullTranslations): |
| 204 | 203 |
msgid1: str, |
| 205 | 204 |
msgid2: str, |
| 206 | 205 |
n: int, |
| 207 |
- /, |
|
| 208 | 206 |
) -> str: # pragma: no cover [unused] |
| 209 | 207 |
"""""" # noqa: D419 |
| 210 | 208 |
return self._locate_message(msgid1, message_plural=msgid2, n=n) |
| ... | ... |
@@ -214,7 +212,6 @@ class DebugTranslations(gettext.NullTranslations): |
| 214 | 212 |
self, |
| 215 | 213 |
context: str, |
| 216 | 214 |
message: str, |
| 217 |
- /, |
|
| 218 | 215 |
) -> str: |
| 219 | 216 |
return self._locate_message(message, context=context) |
| 220 | 217 |
|
| ... | ... |
@@ -225,7 +222,6 @@ class DebugTranslations(gettext.NullTranslations): |
| 225 | 222 |
msgid1: str, |
| 226 | 223 |
msgid2: str, |
| 227 | 224 |
n: int, |
| 228 |
- /, |
|
| 229 | 225 |
) -> str: # pragma: no cover [unused] |
| 230 | 226 |
"""""" # noqa: D419 |
| 231 | 227 |
return self._locate_message( |
| ... | ... |
@@ -501,9 +497,18 @@ class TranslatedString: |
| 501 | 497 |
More keyword arguments to be passed to [`str.format`][]. |
| 502 | 498 |
|
| 503 | 499 |
""" |
| 504 |
- if isinstance(template, MSG_TEMPLATE_CLASSES): |
|
| 505 |
- template = cast("TranslatableString", template.value)
|
|
| 506 |
- self.template = template |
|
| 500 |
+ # The cast is still needed for mypy. For this use case -- |
|
| 501 |
+ # multiple related enums, all values of which share the same |
|
| 502 |
+ # type, even across enums -- mypy's type inference is |
|
| 503 |
+ # frustratingly surface-level. |
|
| 504 |
+ # |
|
| 505 |
+ # pyrefly: ignore [redundant-cast] |
|
| 506 |
+ self.template = cast( |
|
| 507 |
+ "str | TranslatableString", |
|
| 508 |
+ template.value |
|
| 509 |
+ if isinstance(template, MSG_TEMPLATE_CLASSES) |
|
| 510 |
+ else template, |
|
| 511 |
+ ) |
|
| 507 | 512 |
self.kwargs = {**args_dict, **kwargs}
|
| 508 | 513 |
self._rendered: str | None = None |
| 509 | 514 |
|
| ... | ... |
@@ -2470,7 +2475,7 @@ def _write_po_file( # noqa: C901,PLR0912 |
| 2470 | 2475 |
entries: dict[str, dict[str, MsgTemplate]] = {}
|
| 2471 | 2476 |
for enum_class in MSG_TEMPLATE_CLASSES: |
| 2472 | 2477 |
for member in enum_class.__members__.values(): |
| 2473 |
- value = cast("TranslatableString", member.value)
|
|
| 2478 |
+ value = member.value |
|
| 2474 | 2479 |
ctx = value.l10n_context |
| 2475 | 2480 |
msg = value.singular |
| 2476 | 2481 |
if ( |
| ... | ... |
@@ -2569,7 +2574,7 @@ def _write_po_file( # noqa: C901,PLR0912 |
| 2569 | 2574 |
for _msg, enum_value in sorted( |
| 2570 | 2575 |
subdict.items(), key=lambda kv: str(kv[1]) |
| 2571 | 2576 |
): |
| 2572 |
- value = cast("TranslatableString", enum_value.value)
|
|
| 2577 |
+ value = enum_value.value |
|
| 2573 | 2578 |
value2 = value.maybe_without_filename() |
| 2574 | 2579 |
fileobj.writelines( |
| 2575 | 2580 |
_format_po_entry( |
| ... | ... |
@@ -2627,7 +2632,7 @@ def _format_po_entry( |
| 2627 | 2632 |
) -> tuple[str, ...]: # pragma: no cover [internal] |
| 2628 | 2633 |
"""""" # noqa: D419 |
| 2629 | 2634 |
ret: list[str] = ["\n"] |
| 2630 |
- ts = transformed_string or cast("TranslatableString", enum_value.value)
|
|
| 2635 |
+ ts = transformed_string or enum_value.value |
|
| 2631 | 2636 |
if ts.translator_comments: |
| 2632 | 2637 |
comments = ts.translator_comments.splitlines(False) # noqa: FBT003 |
| 2633 | 2638 |
comments.extend(["", f"Message-ID: {enum_value}"])
|
| ... | ... |
@@ -1283,7 +1283,7 @@ class _VaultContext: # noqa: PLR0904 |
| 1283 | 1283 |
notes_legacy_instructions = _msg.TranslatedString( |
| 1284 | 1284 |
_msg.Label.DERIVEPASSPHRASE_VAULT_NOTES_LEGACY_INSTRUCTION_TEXT |
| 1285 | 1285 |
) |
| 1286 |
- old_notes_value = subtree.get("notes", "")
|
|
| 1286 |
+ old_notes_value = cast("str", subtree.get("notes", ""))
|
|
| 1287 | 1287 |
if modern_editor_interface: |
| 1288 | 1288 |
text = "\n".join([ |
| 1289 | 1289 |
str(notes_instructions), |
| ... | ... |
@@ -1292,8 +1292,9 @@ class _VaultContext: # noqa: PLR0904 |
| 1292 | 1292 |
]) |
| 1293 | 1293 |
else: |
| 1294 | 1294 |
text = old_notes_value or str(notes_legacy_instructions) |
| 1295 |
+ # pyrefly: ignore [bad-argument-type] |
|
| 1295 | 1296 |
notes_value = click.edit(text=text, require_save=False) |
| 1296 |
- assert notes_value is not None |
|
| 1297 |
+ assert isinstance(notes_value, str) |
|
| 1297 | 1298 |
if ( |
| 1298 | 1299 |
not modern_editor_interface |
| 1299 | 1300 |
and notes_value.strip() != old_notes_value.strip() |
| ... | ... |
@@ -1428,7 +1429,7 @@ class _VaultContext: # noqa: PLR0904 |
| 1428 | 1429 |
"symbol", |
| 1429 | 1430 |
} |
| 1430 | 1431 |
kwargs = {
|
| 1431 |
- cast("str", k): cast("int", settings[k])
|
|
| 1432 |
+ k: cast("int", settings[k])
|
|
| 1432 | 1433 |
for k in vault_service_keys |
| 1433 | 1434 |
if k in settings |
| 1434 | 1435 |
} |
| ... | ... |
@@ -391,7 +391,7 @@ def _decrypt_master_keys_data( |
| 391 | 391 |
padded_plaintext.extend(decryptor.finalize()) |
| 392 | 392 |
unpadder = padding.PKCS7(IV_SIZE * 8).unpadder() |
| 393 | 393 |
plaintext = bytearray() |
| 394 |
- plaintext.extend(unpadder.update(padded_plaintext)) |
|
| 394 |
+ plaintext.extend(unpadder.update(bytes(padded_plaintext))) |
|
| 395 | 395 |
plaintext.extend(unpadder.finalize()) |
| 396 | 396 |
hashing_key, encryption_key, signing_key = struct.unpack( |
| 397 | 397 |
f"{KEY_SIZE}s {KEY_SIZE}s {KEY_SIZE}s", plaintext
|
| ... | ... |
@@ -484,7 +484,7 @@ def _decrypt_session_keys( |
| 484 | 484 |
padded_plaintext.extend(decryptor.finalize()) |
| 485 | 485 |
unpadder = padding.PKCS7(IV_SIZE * 8).unpadder() |
| 486 | 486 |
plaintext = bytearray() |
| 487 |
- plaintext.extend(unpadder.update(padded_plaintext)) |
|
| 487 |
+ plaintext.extend(unpadder.update(bytes(padded_plaintext))) |
|
| 488 | 488 |
plaintext.extend(unpadder.finalize()) |
| 489 | 489 |
session_encryption_key, session_signing_key = struct.unpack( |
| 490 | 490 |
f"{KEY_SIZE}s {KEY_SIZE}s", plaintext
|
| ... | ... |
@@ -590,7 +590,7 @@ def _decrypt_contents( |
| 590 | 590 |
padded_plaintext.extend(decryptor.finalize()) |
| 591 | 591 |
unpadder = padding.PKCS7(IV_SIZE * 8).unpadder() |
| 592 | 592 |
plaintext = bytearray() |
| 593 |
- plaintext.extend(unpadder.update(padded_plaintext)) |
|
| 593 |
+ plaintext.extend(unpadder.update(bytes(padded_plaintext))) |
|
| 594 | 594 |
plaintext.extend(unpadder.finalize()) |
| 595 | 595 |
|
| 596 | 596 |
logger.debug( |
| ... | ... |
@@ -429,7 +429,7 @@ class VaultNativeConfigParser(abc.ABC): |
| 429 | 429 |
) |
| 430 | 430 |
unpadder = padding.PKCS7(iv_size * 8).unpadder() |
| 431 | 431 |
plaintext = bytearray() |
| 432 |
- plaintext.extend(unpadder.update(padded_plaintext)) |
|
| 432 |
+ plaintext.extend(unpadder.update(bytes(padded_plaintext))) |
|
| 433 | 433 |
plaintext.extend(unpadder.finalize()) |
| 434 | 434 |
logger.debug( |
| 435 | 435 |
_msg.TranslatedString( |
| ... | ... |
@@ -258,15 +258,13 @@ except ( |
| 258 | 258 |
dwFlagsAndAttributes: DWORD, # noqa: N803 |
| 259 | 259 |
hTemplateFile: HANDLE | None, # noqa: N803 |
| 260 | 260 |
) -> HANDLE: # pragma: no cover [external] |
| 261 |
- del ( |
|
| 262 |
- lpFilename, |
|
| 263 |
- dwDesiredAccess, |
|
| 264 |
- dwShareMode, |
|
| 265 |
- lpSecurityAttributes, |
|
| 266 |
- dwCreationDisposition, |
|
| 267 |
- dwFlagsAndAttributes, |
|
| 268 |
- hTemplateFile, |
|
| 269 |
- ) |
|
| 261 |
+ del lpFilename |
|
| 262 |
+ del dwDesiredAccess |
|
| 263 |
+ del dwShareMode |
|
| 264 |
+ del lpSecurityAttributes |
|
| 265 |
+ del dwCreationDisposition |
|
| 266 |
+ del dwFlagsAndAttributes |
|
| 267 |
+ del hTemplateFile |
|
| 270 | 268 |
msg = "This Python version does not support Windows named pipes." |
| 271 | 269 |
raise WindowsNamedPipesNotAvailableError(msg) |
| 272 | 270 |
|
| ... | ... |
@@ -277,13 +275,11 @@ except ( |
| 277 | 275 |
lpNumberOfBytesRead: LPDWORD, # noqa: N803 |
| 278 | 276 |
lpOverlapped: LPOVERLAPPED, # noqa: N803 |
| 279 | 277 |
) -> BOOL: # pragma: no cover [external] |
| 280 |
- del ( |
|
| 281 |
- hFile, |
|
| 282 |
- lpBuffer, |
|
| 283 |
- nNumberOfBytesToRead, |
|
| 284 |
- lpNumberOfBytesRead, |
|
| 285 |
- lpOverlapped, |
|
| 286 |
- ) |
|
| 278 |
+ del hFile |
|
| 279 |
+ del lpBuffer |
|
| 280 |
+ del nNumberOfBytesToRead |
|
| 281 |
+ del lpNumberOfBytesRead |
|
| 282 |
+ del lpOverlapped |
|
| 287 | 283 |
raise OSError(errno.ENOTSUP, os.strerror(errno.ENOTSUP)) |
| 288 | 284 |
|
| 289 | 285 |
def WriteFile( # noqa: N802 |
| ... | ... |
@@ -293,13 +289,11 @@ except ( |
| 293 | 289 |
lpNumberOfBytesWritten: LPDWORD, # noqa: N803 |
| 294 | 290 |
lpOverlapped: LPOVERLAPPED, # noqa: N803 |
| 295 | 291 |
) -> BOOL: # pragma: no cover [external] |
| 296 |
- del ( |
|
| 297 |
- hFile, |
|
| 298 |
- lpBuffer, |
|
| 299 |
- nNumberOfBytesToWrite, |
|
| 300 |
- lpNumberOfBytesWritten, |
|
| 301 |
- lpOverlapped, |
|
| 302 |
- ) |
|
| 292 |
+ del hFile |
|
| 293 |
+ del lpBuffer |
|
| 294 |
+ del nNumberOfBytesToWrite |
|
| 295 |
+ del lpNumberOfBytesWritten |
|
| 296 |
+ del lpOverlapped |
|
| 303 | 297 |
raise OSError(errno.ENOTSUP, os.strerror(errno.ENOTSUP)) |
| 304 | 298 |
|
| 305 | 299 |
def CloseHandle( # noqa: N802 |
| ... | ... |
@@ -162,7 +162,7 @@ class Vault: |
| 162 | 162 |
self._required: list[bytes] = [] |
| 163 | 163 |
|
| 164 | 164 |
def subtract_or_require( |
| 165 |
- count: int | None, characters: bytes | bytearray |
|
| 165 |
+ count: int | None, characters: bytes |
|
| 166 | 166 |
) -> None: |
| 167 | 167 |
if not isinstance(count, int): |
| 168 | 168 |
return |
| ... | ... |
@@ -479,15 +479,14 @@ class Vault: |
| 479 | 479 |
""" |
| 480 | 480 |
key = bytes(key) |
| 481 | 481 |
TestFunc: TypeAlias = "Callable[[bytes | bytearray], bool]" |
| 482 |
- deterministic_signature_types: dict[str, TestFunc] |
|
| 483 |
- deterministic_signature_types = {
|
|
| 482 |
+ deterministic_signature_types: dict[str, TestFunc] = {
|
|
| 484 | 483 |
"ssh-ed25519": lambda k: k.startswith( |
| 485 | 484 |
b"\x00\x00\x00\x0bssh-ed25519" |
| 486 | 485 |
), |
| 487 | 486 |
"ssh-ed448": lambda k: k.startswith(b"\x00\x00\x00\x09ssh-ed448"), |
| 488 | 487 |
"ssh-rsa": lambda k: k.startswith(b"\x00\x00\x00\x07ssh-rsa"), |
| 489 | 488 |
} |
| 490 |
- dsa_signature_types = {
|
|
| 489 |
+ dsa_signature_types: dict[str, TestFunc] = {
|
|
| 491 | 490 |
"ssh-dss": lambda k: k.startswith(b"\x00\x00\x00\x07ssh-dss"), |
| 492 | 491 |
"ecdsa-sha2-nistp256": lambda k: k.startswith( |
| 493 | 492 |
b"\x00\x00\x00\x13ecdsa-sha2-nistp256" |
| ... | ... |
@@ -499,7 +498,7 @@ class Vault: |
| 499 | 498 |
b"\x00\x00\x00\x13ecdsa-sha2-nistp521" |
| 500 | 499 |
), |
| 501 | 500 |
} |
| 502 |
- criteria = [ |
|
| 501 |
+ criteria: list[Callable[[], bool]] = [ |
|
| 503 | 502 |
lambda: any( |
| 504 | 503 |
v(key) for v in deterministic_signature_types.values() |
| 505 | 504 |
), |
| ... | ... |
@@ -19,6 +19,7 @@ from __future__ import annotations |
| 19 | 19 |
|
| 20 | 20 |
import base64 |
| 21 | 21 |
import contextlib |
| 22 |
+import importlib.metadata |
|
| 22 | 23 |
import importlib.util |
| 23 | 24 |
import json |
| 24 | 25 |
import os |
| ... | ... |
@@ -128,7 +129,7 @@ def xfail_on_the_annoying_os( |
| 128 | 129 |
empty, will follow. |
| 129 | 130 |
|
| 130 | 131 |
""" |
| 131 |
- import hypothesis # noqa: PLC0415 |
|
| 132 |
+ import hypothesis.errors # noqa: PLC0415 |
|
| 132 | 133 |
|
| 133 | 134 |
base_reason = "The Annoying OS behaves differently." |
| 134 | 135 |
full_reason = base_reason if not reason else f"{base_reason} {reason}"
|
| ... | ... |
@@ -124,7 +124,7 @@ class Strategies: |
| 124 | 124 |
@strategies.composite |
| 125 | 125 |
@staticmethod |
| 126 | 126 |
def service_name_and_data_strategy( |
| 127 |
- draw: hypothesis.strategies.DrawFn, |
|
| 127 |
+ draw: strategies.DrawFn, |
|
| 128 | 128 |
num_entries: int, |
| 129 | 129 |
) -> tuple[tuple[str, _types.VaultConfigServicesSettings], ...]: |
| 130 | 130 |
"""Return a strategy for tuples of service names and settings. |
| ... | ... |
@@ -366,10 +366,14 @@ class ConfigManagementStateMachine(stateful.RuleBasedStateMachine): |
| 366 | 366 |
""" |
| 367 | 367 |
config = copy.deepcopy(config) |
| 368 | 368 |
setting = copy.deepcopy(setting) |
| 369 |
- config_global = config.get("global", {})
|
|
| 369 |
+ config_global = config.get( |
|
| 370 |
+ "global", cast("_types.VaultConfigGlobalSettings", {})
|
|
| 371 |
+ ) |
|
| 370 | 372 |
maybe_unset = set(maybe_unset) - setting.keys() |
| 371 | 373 |
if overwrite: |
| 372 |
- config["global"] = config_global = {}
|
|
| 374 |
+ config["global"] = config_global = cast( |
|
| 375 |
+ "_types.VaultConfigGlobalSettings", {}
|
|
| 376 |
+ ) |
|
| 373 | 377 |
elif maybe_unset: |
| 374 | 378 |
for key in maybe_unset: |
| 375 | 379 |
config_global.pop(key, None) # type: ignore[misc] |
| ... | ... |
@@ -437,7 +441,7 @@ class ConfigManagementStateMachine(stateful.RuleBasedStateMachine): |
| 437 | 441 |
self, |
| 438 | 442 |
service: str, |
| 439 | 443 |
config: _types.VaultConfig, |
| 440 |
- setting: _types.VaultConfigGlobalSettings, |
|
| 444 |
+ setting: _types.VaultConfigServicesSettings, |
|
| 441 | 445 |
maybe_unset: AbstractSet[str], |
| 442 | 446 |
overwrite: bool, |
| 443 | 447 |
) -> tuple[_types.VaultConfig, AbstractSet[str]]: |
| ... | ... |
@@ -471,7 +475,7 @@ class ConfigManagementStateMachine(stateful.RuleBasedStateMachine): |
| 471 | 475 |
config_service = config["services"].get(service, {})
|
| 472 | 476 |
maybe_unset = set(maybe_unset) - setting.keys() |
| 473 | 477 |
if overwrite: |
| 474 |
- config["services"][service] = config_service = {}
|
|
| 478 |
+ config["services"][service] = config_service = cast("_types.VaultConfigServicesSettings", {})
|
|
| 475 | 479 |
elif maybe_unset: |
| 476 | 480 |
for key in maybe_unset: |
| 477 | 481 |
config_service.pop(key, None) # type: ignore[misc] |
| ... | ... |
@@ -513,11 +513,11 @@ class TestStoreroom: |
| 513 | 513 |
encryptor = ciphers.Cipher( |
| 514 | 514 |
algorithms.AES256(key), modes.CBC(iv) |
| 515 | 515 |
).encryptor() |
| 516 |
- ciphertext = bytearray(encryptor.update(plaintext)) |
|
| 516 |
+ ciphertext = bytearray(encryptor.update(bytes(plaintext))) |
|
| 517 | 517 |
ciphertext.extend(encryptor.finalize()) |
| 518 | 518 |
mac_obj = hmac.HMAC(key, hashes.SHA256()) |
| 519 | 519 |
mac_obj.update(iv) |
| 520 |
- mac_obj.update(ciphertext) |
|
| 520 |
+ mac_obj.update(bytes(ciphertext)) |
|
| 521 | 521 |
data = iv + bytes(ciphertext) + mac_obj.finalize() |
| 522 | 522 |
with pytest.raises( |
| 523 | 523 |
ValueError, |
| ... | ... |
@@ -320,9 +320,7 @@ class TestCLIUtilities: |
| 320 | 320 |
""" |
| 321 | 321 |
with self._setup_environment() as monkeypatch: |
| 322 | 322 |
if path: |
| 323 |
- monkeypatch.setenv( |
|
| 324 |
- "VAULT_PATH", os.fspath(path) if path is not None else None |
|
| 325 |
- ) |
|
| 323 |
+ monkeypatch.setenv("VAULT_PATH", os.fspath(path))
|
|
| 326 | 324 |
assert ( |
| 327 | 325 |
exporter.get_vault_path().resolve() |
| 328 | 326 |
== expected.expanduser().resolve() |
| ... | ... |
@@ -1322,7 +1322,7 @@ class TestAgentErrorResponses: |
| 1322 | 1322 |
with self._setup_agent_and_request_handler({
|
| 1323 | 1323 |
data.AgentProtocolRequest( |
| 1324 | 1324 |
_types.SSH_AGENTC.REQUEST_IDENTITIES, b"" |
| 1325 |
- ): [data.AgentProtocolResponse(response_code, response)], |
|
| 1325 |
+ ): [data.AgentProtocolResponse(response_code, bytes(response))], |
|
| 1326 | 1326 |
}) as contexts: |
| 1327 | 1327 |
_, client = contexts |
| 1328 | 1328 |
with pytest.raises(exc_type, match=exc_pattern): |
| ... | ... |
@@ -1361,7 +1361,7 @@ class TestAgentErrorResponses: |
| 1361 | 1361 |
with self._setup_agent_and_request_handler({
|
| 1362 | 1362 |
data.AgentProtocolRequest( |
| 1363 | 1363 |
_types.SSH_AGENTC.SIGN_REQUEST, sign_payload |
| 1364 |
- ): [data.AgentProtocolResponse(response_code, response)], |
|
| 1364 |
+ ): [data.AgentProtocolResponse(response_code, bytes(response))], |
|
| 1365 | 1365 |
}) as contexts: |
| 1366 | 1366 |
monkeypatch, client = contexts |
| 1367 | 1367 |
monkeypatch.setattr(client, "list_keys", lambda: loaded_keys) |
| ... | ... |
@@ -12,7 +12,7 @@ import gettext |
| 12 | 12 |
import os |
| 13 | 13 |
import re |
| 14 | 14 |
import types |
| 15 |
-from typing import TYPE_CHECKING, TypeVar, cast |
|
| 15 |
+from typing import TYPE_CHECKING, TypeVar |
|
| 16 | 16 |
|
| 17 | 17 |
import hypothesis |
| 18 | 18 |
import pytest |
| ... | ... |
@@ -57,16 +57,13 @@ class Strategies: |
| 57 | 57 |
] |
| 58 | 58 |
] = {}
|
| 59 | 59 |
for enum_class in msg.MSG_TEMPLATE_CLASSES: |
| 60 |
- all_translatable_strings_dict.update({
|
|
| 61 |
- cast("msg.TranslatableString", v.value): v for v in enum_class
|
|
| 62 |
- }) |
|
| 60 |
+ all_translatable_strings_dict.update({v.value: v for v in enum_class})
|
|
| 63 | 61 |
|
| 64 | 62 |
all_translatable_strings_enum_values = tuple( |
| 65 | 63 |
sorted(all_translatable_strings_dict.values(), key=str) |
| 66 | 64 |
) |
| 67 | 65 |
all_translatable_strings = tuple( |
| 68 |
- cast("msg.TranslatableString", v.value)
|
|
| 69 |
- for v in all_translatable_strings_enum_values |
|
| 66 |
+ v.value for v in all_translatable_strings_enum_values |
|
| 70 | 67 |
) |
| 71 | 68 |
|
| 72 | 69 |
error_codes = tuple( |
| ... | ... |
@@ -132,7 +129,7 @@ class Strategies: |
| 132 | 129 |
@classmethod |
| 133 | 130 |
def translatable_strings( |
| 134 | 131 |
cls, |
| 135 |
- ) -> strategies.SearchStrategy[msg.MsgTemplate]: |
|
| 132 |
+ ) -> strategies.SearchStrategy[msg.TranslatableString]: |
|
| 136 | 133 |
"""Return a strategy for translatable messages.""" |
| 137 | 134 |
return strategies.sampled_from(cls.all_translatable_strings) |
| 138 | 135 |
|
| ... | ... |
@@ -201,9 +198,7 @@ class TestDebugTranslations: |
| 201 | 198 |
value: msg.MsgTemplate, |
| 202 | 199 |
) -> None: |
| 203 | 200 |
"""Translating a MsgTemplate operates on the enum value.""" |
| 204 |
- self._test_interpolated( |
|
| 205 |
- str(value), cast("msg.TranslatableString", value.value)
|
|
| 206 |
- ) |
|
| 201 |
+ self._test_interpolated(str(value), value.value) |
|
| 207 | 202 |
|
| 208 | 203 |
|
| 209 | 204 |
@pytest.mark.usefixtures("use_debug_translations")
|
| 210 | 205 |