What changed, and why it matters
This commit is a routine code cleanup that updates Python type annotations to a newer, recommended style (PEP 585). It does not change any program logic, security behavior, or runtime functionality. There is no security issue here.
No action needed. This is a non-security style/refactoring commit.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The commit enforces PEP 585 style type annotations across the python/ tree. Changes replace typing.List/Dict/Tuple/etc. with built-in generics (list, dict, tuple), move abstract base classes (Iterable, Sequence, Collection, Generator) from typing to collections.abc, and update ruff configuration to lint python/*/.py. These are purely syntactic/annotation changes with no runtime or security impact.
Changed components
python/src/trezorlibpython/helper-scriptspython/testspython/toolspyproject.tomlInspect captured patch +191 / −219
### pyproject.toml
@@ -98,10 +98,14 @@ extra_standard_library = [
known_first_party = ["trezorlib", "apps", "coin_info", "marketcap", "ui_tests"]
known_third_party = ["trezor", "storage"]
-# Ruff is used as a PEP 585 linter for `core` only
+# Ruff is used as a PEP 585 linter
[tool.ruff]
target-version = "py310"
-include = ["core/**/*.py"]
+per-file-target-version = { "python/**/*.py" = "py39" }
+include = [
+ "core/**/*.py",
+ "python/**/*.py",
+]
force-exclude = true
extend-exclude = [
"core/translations",
### python/helper-scripts/make-options-rst.py
@@ -20,7 +20,6 @@
import sys
from io import StringIO
from pathlib import Path
-from typing import List
import click
@@ -38,7 +37,7 @@
current = OPTIONS_RST.read_text()
output = StringIO()
-lead_in: List[str] = []
+lead_in: list[str] = []
for line in current.splitlines(keepends=True):
lead_in.append(line)
### python/helper-scripts/relicence.py
@@ -19,7 +19,7 @@
import glob
import os
import sys
-from typing import List, TextIO
+from typing import TextIO
LICENSE_NOTICE = """\
# This file is part of the Trezor project.
@@ -80,7 +80,7 @@ def one_file(fp: TextIO) -> None:
fp.truncate()
-def main(paths: List[str]) -> None:
+def main(paths: list[str]) -> None:
for path in paths:
for fn in glob.glob(f"{path}/**/*.py", recursive=True):
if any(exclude in fn for exclude in EXCLUDE_DIRS):
### python/src/trezorlib/_ed25519.py
@@ -32,9 +32,9 @@
"""
import hashlib
-from typing import List, NewType, Tuple
+from typing import NewType
-Point = NewType("Point", Tuple[int, int, int, int])
+Point = NewType("Point", tuple[int, int, int, int])
__version__ = "1.0.dev1"
@@ -154,7 +154,7 @@ def scalarmult(P: Point, e: int) -> Point:
# Bpow[i] == scalarmult(B, 2**i)
-Bpow: List[Point] = []
+Bpow: list[Point] = []
def make_Bpow() -> None:
### python/src/trezorlib/_internal/emu_ble.py
@@ -19,8 +19,9 @@
import logging
import socket
import time
+from collections.abc import Iterable
from enum import Enum
-from typing import TYPE_CHECKING, Iterable, Tuple
+from typing import TYPE_CHECKING
import construct as c
from construct_classes import Struct
@@ -132,7 +133,7 @@ def __init__(self, device: str | None = None) -> None:
port = (
int(devparts[1]) if len(devparts) > 1 else EmuBleTransport.DEFAULT_PORT
)
- self.device: Tuple[str, int] = (host, port)
+ self.device: tuple[str, int] = (host, port)
self.data_socket: socket.socket | None = None
self.event_socket: socket.socket | None = None
### python/src/trezorlib/_internal/emulator.py
@@ -24,8 +24,9 @@
import socket
import subprocess
import time
+from collections.abc import Iterable, Sequence
from pathlib import Path
-from typing import Any, Dict, Iterable, List, Optional, Sequence, TextIO, Union, cast
+from typing import Any, Optional, TextIO, Union, cast
from ..debuglink import DebugLinkNotFound, TrezorTestContext
from ..transport import Transport
@@ -217,10 +218,10 @@ def client(self) -> TrezorTestContext:
raise RuntimeError
return self._client
- def make_args(self) -> List[str]:
+ def make_args(self) -> list[str]:
return []
- def make_env(self) -> Dict[str, str]:
+ def make_env(self) -> dict[str, str]:
return os.environ.copy()
def _get_transport(self) -> UdpTransport:
@@ -393,7 +394,7 @@ def __init__(
self.heap_size = heap_size
self.display_scale = display_scale
- def make_env(self) -> Dict[str, str]:
+ def make_env(self) -> dict[str, str]:
env = super().make_env()
env.update(
TREZOR_PROFILE_DIR=str(self.profile_dir),
@@ -411,7 +412,7 @@ def make_env(self) -> Dict[str, str]:
return env
- def make_args(self) -> List[str]:
+ def make_args(self) -> list[str]:
pyopt = "-O0" if self.debug else "-O1"
return (
[pyopt, "-X", f"heapsize={self.heap_size}"]
@@ -463,7 +464,7 @@ def properties(self) -> dict[str, Any]:
class LegacyEmulator(Emulator):
STORAGE_FILENAME = "emulator.img"
- def make_env(self) -> Dict[str, str]:
+ def make_env(self) -> dict[str, str]:
env = super().make_env()
if self.headless:
env["SDL_VIDEODRIVER"] = "dummy"
### python/src/trezorlib/_internal/firmware_headers.py
@@ -154,7 +154,7 @@ def pformat(value: t.Any, indent: int) -> str:
return pformat(pb, indent)
-def _format_version(version: t.Tuple[int, ...]) -> str:
+def _format_version(version: tuple[int, ...]) -> str:
return ".".join(str(i) for i in version)
@@ -616,7 +616,7 @@ def format(self, verbose: bool = False) -> str:
def public_keys(
self, dev_keys: bool = False, signature_version: int = 3
) -> t.Sequence[bytes]:
- keymap: t.Dict[t.Tuple[int, bool], fw_models.ModelKeys] = {
+ keymap: dict[tuple[int, bool], fw_models.ModelKeys] = {
(3, False): fw_models.LEGACY_V3,
(3, True): fw_models.LEGACY_V3_DEV,
(2, False): fw_models.LEGACY_V1V2,
### python/src/trezorlib/_internal/translations.py
@@ -45,9 +45,9 @@
lambda ctx: (ALIGNMENT - (ctx._io.tell() % ALIGNMENT)) % ALIGNMENT
)
-JsonFontInfo = t.Dict[str, str]
-Order = t.Dict[int, str]
-VersionTuple = t.Tuple[int, int, int, int]
+JsonFontInfo = dict[str, str]
+Order = dict[int, str]
+VersionTuple = tuple[int, int, int, int]
class JsonHeader(TypedDict):
### python/src/trezorlib/_modeldata/__init__.py
@@ -43,10 +43,10 @@
from dataclasses import dataclass, field
from enum import Enum
-from typing import Callable, Optional, Tuple
+from typing import Callable, Optional
-def keys(*hexes: str) -> Tuple[bytes, ...]:
+def keys(*hexes: str) -> tuple[bytes, ...]:
"""Helper: turn hex strings into a tuple of key bytes."""
return tuple(bytes.fromhex(h) for h in hexes)
@@ -79,15 +79,15 @@ class KeySet:
and the dev keys that discovery boards reuse, are not production)."""
production: bool = False
- boardloader_keys: Tuple[bytes, ...] = ()
+ boardloader_keys: tuple[bytes, ...] = ()
boardloader_sigs_needed: int = -1
- bootloader_keys: Tuple[bytes, ...] = ()
+ bootloader_keys: tuple[bytes, ...] = ()
bootloader_sigs_needed: int = -1
- firmware_keys: Tuple[bytes, ...] = ()
+ firmware_keys: tuple[bytes, ...] = ()
firmware_sigs_needed: int = -1
- secmon_keys: Tuple[bytes, ...] = ()
+ secmon_keys: tuple[bytes, ...] = ()
secmon_sigs_needed: int = -1
- nrf_keys: Tuple[bytes, ...] = ()
+ nrf_keys: tuple[bytes, ...] = ()
@dataclass(frozen=True)
@@ -107,8 +107,8 @@ class ModelData:
name: str
hw_model: bytes
# --- release / protocol metadata (sidecar: not in firmware files) ---
- minimum_version: Tuple[int, int, int]
- aliases: Tuple[str, ...] = ()
+ minimum_version: tuple[int, int, int]
+ aliases: tuple[str, ...] = ()
# --- hardware / UI (source: model.toml features) ---
model_class: ModelClass = ModelClass.CORE
layout: Layout = Layout.BOLT
### python/src/trezorlib/_modeldata/registry.py
@@ -19,11 +19,11 @@
Once the firmware-side generator exists, the import list below is the only
thing it needs to emit/maintain (one line per ``core/embed/models/<NAME>``)."""
-from typing import Dict, Optional, Tuple
+from typing import Optional
from . import D001, D002, D003, T1B1, T2B1, T2T1, T3B1, T3T1, T3T2, T3W1, ModelData
-ALL: Tuple[ModelData, ...] = (
+ALL: tuple[ModelData, ...] = (
T1B1.MODEL,
T2T1.MODEL,
T2B1.MODEL,
@@ -36,7 +36,7 @@
D003.MODEL,
)
-BY_INTERNAL_NAME: Dict[str, ModelData] = {m.internal_name: m for m in ALL}
+BY_INTERNAL_NAME: dict[str, ModelData] = {m.internal_name: m for m in ALL}
def by_internal_name(internal_name: str) -> Optional[ModelData]:
### python/src/trezorlib/_proto_messages.mako
@@ -2,8 +2,9 @@
# fmt: off
# isort:skip_file
+from collections.abc import Sequence
from enum import IntEnum
-from typing import Sequence, Optional
+from typing import Optional
from . import protobuf
% for enum in enums:
### python/src/trezorlib/btc.py
@@ -17,9 +17,10 @@
from __future__ import annotations
import warnings
+from collections.abc import Sequence
from copy import copy
from decimal import Decimal
-from typing import TYPE_CHECKING, Any, AnyStr, List, Optional, Sequence, Tuple
+from typing import TYPE_CHECKING, Any, AnyStr, Optional
# TypedDict is not available in typing for python < 3.8
from typing_extensions import Protocol, TypedDict
@@ -40,15 +41,15 @@ class ScriptPubKey(TypedDict):
hex: str
type: str
reqSigs: int
- addresses: List[str]
+ addresses: list[str]
class Vin(TypedDict):
txid: str
vout: int
sequence: int
coinbase: str
scriptSig: "ScriptSig"
- txinwitness: List[str]
+ txinwitness: list[str]
class Vout(TypedDict):
value: float
@@ -63,8 +64,8 @@ class Transaction(TypedDict):
vsize: int
weight: int
locktime: int
- vin: List[Vin]
- vout: List[Vout]
+ vin: list[Vin]
+ vout: list[Vout]
class TxCacheType(Protocol):
def __getitem__(self, __key: bytes) -> messages.TransactionType: ...
@@ -113,7 +114,7 @@ def get_public_node(
coin_name: Optional[str] = None,
script_type: messages.InputScriptType = messages.InputScriptType.SPENDADDRESS,
ignore_xpub_magic: bool = False,
- unlock_path: Optional[List[int]] = None,
+ unlock_path: Optional[list[int]] = None,
unlock_path_mac: Optional[bytes] = None,
) -> messages.PublicKey:
if unlock_path:
@@ -148,7 +149,7 @@ def get_authenticated_address(
multisig: Optional[messages.MultisigRedeemScriptType] = None,
script_type: messages.InputScriptType = messages.InputScriptType.SPENDADDRESS,
ignore_xpub_magic: bool = False,
- unlock_path: Optional[List[int]] = None,
+ unlock_path: Optional[list[int]] = None,
unlock_path_mac: Optional[bytes] = None,
chunkify: bool = False,
) -> messages.Address:
@@ -199,10 +200,10 @@ def get_ownership_proof(
multisig: Optional[messages.MultisigRedeemScriptType] = None,
script_type: messages.InputScriptType = messages.InputScriptType.SPENDADDRESS,
user_confirmation: bool = False,
- ownership_ids: Optional[List[bytes]] = None,
+ ownership_ids: Optional[list[bytes]] = None,
commitment_data: Optional[bytes] = None,
preauthorized: bool = False,
-) -> Tuple[bytes, bytes]:
+) -> tuple[bytes, bytes]:
if preauthorized:
session.call(messages.DoPreauthorized(), expect=messages.PreauthorizedRequest)
@@ -279,10 +280,10 @@ def sign_tx(
prev_txes: Optional["TxCacheType"] = None,
payment_reqs: Sequence[messages.PaymentRequest] = (),
preauthorized: bool = False,
- unlock_path: Optional[List[int]] = None,
+ unlock_path: Optional[list[int]] = None,
unlock_path_mac: Optional[bytes] = None,
**kwargs: Any,
-) -> Tuple[Sequence[Optional[bytes]], bytes]:
+) -> tuple[Sequence[Optional[bytes]], bytes]:
"""Sign a Bitcoin-like transaction.
Returns a list of signatures (one for each provided input) and the
@@ -329,7 +330,7 @@ def sign_tx(
res = session.call(signtx, expect=messages.TxRequest)
# Prepare structure for signatures
- signatures: List[Optional[bytes]] = [None] * len(inputs)
+ signatures: list[Optional[bytes]] = [None] * len(inputs)
serialized_tx = b""
def copy_tx_meta(tx: messages.TransactionType) -> messages.TransactionType:
### python/src/trezorlib/cardano.py
@@ -14,22 +14,10 @@
# You should have received a copy of the License along with this library.
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
+from collections.abc import Iterable, Iterator, Sequence
from ipaddress import ip_address
from itertools import chain
-from typing import (
- TYPE_CHECKING,
- Any,
- Dict,
- Iterable,
- Iterator,
- List,
- Optional,
- Sequence,
- Tuple,
- Type,
- TypeVar,
- Union,
-)
+from typing import TYPE_CHECKING, Any, Optional, TypeVar, Union
from . import messages as m
from . import tools
@@ -71,14 +59,14 @@
INVALID_OUTPUT_TOKEN_BUNDLE_ENTRY = "The output's token_bundle entry is invalid"
INVALID_MINT_TOKEN_BUNDLE_ENTRY = "The mint token_bundle entry is invalid"
-InputWithPath = Tuple[m.CardanoTxInput, List[int]]
-CollateralInputWithPath = Tuple[m.CardanoTxCollateralInput, List[int]]
-AssetGroupWithTokens = Tuple[m.CardanoAssetGroup, List[m.CardanoToken]]
-OutputWithData = Tuple[
+InputWithPath = tuple[m.CardanoTxInput, list[int]]
+CollateralInputWithPath = tuple[m.CardanoTxCollateralInput, list[int]]
+AssetGroupWithTokens = tuple[m.CardanoAssetGroup, list[m.CardanoToken]]
+OutputWithData = tuple[
m.CardanoTxOutput,
- List[AssetGroupWithTokens],
- List[m.CardanoTxInlineDatumChunk],
- List[m.CardanoTxReferenceScriptChunk],
+ list[AssetGroupWithTokens],
+ list[m.CardanoTxInlineDatumChunk],
+ list[m.CardanoTxReferenceScriptChunk],
]
OutputItem = Union[
m.CardanoTxOutput,
@@ -93,16 +81,16 @@
m.CardanoPoolRelayParameters,
]
MintItem = Union[m.CardanoTxMint, m.CardanoAssetGroup, m.CardanoToken]
-PoolOwnersAndRelays = Tuple[
- List[m.CardanoPoolOwner], List[m.CardanoPoolRelayParameters]
+PoolOwnersAndRelays = tuple[
+ list[m.CardanoPoolOwner], list[m.CardanoPoolRelayParameters]
]
-CertificateWithPoolOwnersAndRelays = Tuple[
+CertificateWithPoolOwnersAndRelays = tuple[
m.CardanoTxCertificate, Optional[PoolOwnersAndRelays]
]
-Path = List[int]
-Witness = Tuple[Path, bytes]
-AuxiliaryDataSupplement = Dict[str, Union[int, bytes]]
-SignTxResponse = Dict[str, Union[bytes, List[Witness], AuxiliaryDataSupplement]]
+Path = list[int]
+Witness = tuple[Path, bytes]
+AuxiliaryDataSupplement = dict[str, Union[int, bytes]]
+SignTxResponse = dict[str, Union[bytes, list[Witness], AuxiliaryDataSupplement]]
Chunk = TypeVar(
"Chunk",
bound=Union[
@@ -122,8 +110,8 @@ def parse_optional_int(value: Optional[str]) -> Optional[int]:
def create_address_parameters(
address_type: m.CardanoAddressType,
- address_n: List[int],
- address_n_staking: Optional[List[int]] = None,
+ address_n: list[int],
+ address_n_staking: Optional[list[int]] = None,
staking_key_hash: Optional[bytes] = None,
block_index: Optional[int] = None,
tx_index: Optional[int] = None,
@@ -235,7 +223,7 @@ def parse_output(output: dict) -> OutputWithData:
def _parse_token_bundle(
token_bundle: Iterable[dict], is_mint: bool
-) -> List[AssetGroupWithTokens]:
+) -> list[AssetGroupWithTokens]:
error_message: str
if is_mint:
error_message = INVALID_MINT_TOKEN_BUNDLE_ENTRY
@@ -262,7 +250,7 @@ def _parse_token_bundle(
return result
-def _parse_tokens(tokens: Iterable[dict], is_mint: bool) -> List[m.CardanoToken]:
+def _parse_tokens(tokens: Iterable[dict], is_mint: bool) -> list[m.CardanoToken]:
error_message: str
if is_mint:
error_message = INVALID_MINT_TOKEN_BUNDLE_ENTRY
@@ -344,8 +332,8 @@ def parse_optional_address_parameters(
def _parse_chunkable_data(
- data: Optional[bytes], chunk_type: Type[Chunk]
-) -> Tuple[int, List[Chunk]]:
+ data: Optional[bytes], chunk_type: type[Chunk]
+) -> tuple[int, list[Chunk]]:
if data is None:
return 0, []
data_size = len(data)
@@ -530,7 +518,7 @@ def parse_certificate(certificate: dict) -> CertificateWithPoolOwnersAndRelays:
def _parse_credential(
obj: dict, error: ValueError
-) -> Tuple[List[int], Optional[bytes], Optional[bytes]]:
+) -> tuple[list[int], Optional[bytes], Optional[bytes]]:
if not any(k in obj for k in ("path", "script_hash", "key_hash")):
raise error
@@ -673,7 +661,7 @@ def parse_auxiliary_data(
)
-def parse_mint(mint: Iterable[dict]) -> List[AssetGroupWithTokens]:
+def parse_mint(mint: Iterable[dict]) -> list[AssetGroupWithTokens]:
return _parse_token_bundle(mint, is_mint=True)
@@ -731,7 +719,7 @@ def _get_witness_requests(
required_signers: Sequence[m.CardanoTxRequiredSigner],
additional_witness_requests: Sequence[Path],
signing_mode: m.CardanoTxSigningMode,
-) -> List[m.CardanoTxWitnessRequest]:
+) -> list[m.CardanoTxWitnessRequest]:
paths = set()
# don't gather paths from tx elements in MULTISIG_TRANSACTION signing mode
@@ -781,12 +769,12 @@ def _get_witness_requests(
return [m.CardanoTxWitnessRequest(path=path) for path in sorted_paths]
-def _get_inputs_items(inputs: List[InputWithPath]) -> Iterator[m.CardanoTxInput]:
+def _get_inputs_items(inputs: list[InputWithPath]) -> Iterator[m.CardanoTxInput]:
for input, _ in inputs:
yield input
-def _get_outputs_items(outputs: List[OutputWithData]) -> Iterator[OutputItem]:
+def _get_outputs_items(outputs: list[OutputWithData]) -> Iterator[OutputItem]:
for output_with_data in outputs:
yield from _get_output_items(output_with_data)
@@ -866,7 +854,7 @@ def get_authenticated_address(
@tools.workflow(capability=m.Capability.Cardano)
def get_public_key(
session: "Session",
- address_n: List[int],
+ address_n: list[int],
derivation_type: m.CardanoDerivationType = m.CardanoDerivationType.ICARUS,
show_display: bool = False,
) -> m.CardanoPublicKey:
@@ -901,8 +889,8 @@ def get_native_script_hash(
def sign_tx(
session: "Session",
signing_mode: m.CardanoTxSigningMode,
- inputs: List[InputWithPath],
- outputs: List[OutputWithData],
+ inputs: list[InputWithPath],
+ outputs: list[OutputWithData],
fee: int,
ttl: Optional[int],
validity_interval_start: Optional[int],
@@ -924,7 +912,7 @@ def sign_tx(
chunkify: bool = False,
tag_cbor_sets: bool = False,
payment_req: Optional[m.PaymentRequest] = None,
-) -> Dict[str, Any]:
+) -> dict[str, Any]:
witness_requests = _get_witness_requests(
inputs,
certificates,
@@ -973,7 +961,7 @@ def sign_tx(
):
response = session.call(tx_item, expect=m.CardanoTxItemAck)
- sign_tx_response: Dict[str, Any] = {}
+ sign_tx_response: dict[str, Any] = {}
if auxiliary_data is not None:
auxiliary_data_supplement = session.call(
### python/src/trezorlib/cli/__init__.py
@@ -54,9 +54,7 @@
class ChoiceType(click.Choice):
- def __init__(
- self, typemap: t.Dict[str, t.Any], case_sensitive: bool = True
- ) -> None:
+ def __init__(self, typemap: dict[str, t.Any], case_sensitive: bool = True) -> None:
super().__init__(list(typemap.keys()))
self.case_sensitive = case_sensitive
if case_sensitive:
@@ -622,7 +620,7 @@ class AliasedGroup(click.Group):
def __init__(
self,
- aliases: t.Dict[str, click.Command] | None = None,
+ aliases: dict[str, click.Command] | None = None,
*args: t.Any,
**kwargs: t.Any,
) -> None:
### python/src/trezorlib/cli/benchmark.py
@@ -15,7 +15,7 @@
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
from fnmatch import fnmatch
-from typing import TYPE_CHECKING, List, Optional
+from typing import TYPE_CHECKING, Optional
import click
@@ -27,7 +27,7 @@
from ..client import Session
-def list_names_patern(session: "Session", pattern: Optional[str] = None) -> List[str]:
+def list_names_patern(session: "Session", pattern: Optional[str] = None) -> list[str]:
names = list(benchmark.list_names(session).names)
if pattern is None:
return names
### python/src/trezorlib/cli/btc.py
@@ -18,7 +18,7 @@
import base64
import json
-from typing import TYPE_CHECKING, Dict, List, Optional, TextIO, Tuple
+from typing import TYPE_CHECKING, Optional, TextIO
import click
import construct as c
@@ -101,7 +101,7 @@
)
-def xpub_deserialize(xpubstr: str) -> Tuple[str, messages.HDNodeType]:
+def xpub_deserialize(xpubstr: str) -> tuple[str, messages.HDNodeType]:
xpub_bytes = tools.b58check_decode(xpubstr)
data = XpubStruct.parse(xpub_bytes)
if data.key[0] == 0:
@@ -123,7 +123,7 @@ def xpub_deserialize(xpubstr: str) -> Tuple[str, messages.HDNodeType]:
return data.version, node
-def guess_script_type_from_path(address_n: List[int]) -> messages.InputScriptType:
+def guess_script_type_from_path(address_n: list[int]) -> messages.InputScriptType:
if len(address_n) < 1 or not tools.is_hardened(address_n[0]):
return messages.InputScriptType.SPENDADDRESS
@@ -139,7 +139,7 @@ def guess_script_type_from_path(address_n: List[int]) -> messages.InputScriptTyp
return messages.InputScriptType.SPENDADDRESS
-def get_unlock_path(address_n: List[int]) -> Optional[List[int]]:
+def get_unlock_path(address_n: list[int]) -> Optional[list[int]]:
if address_n and address_n[0] == tools.H_(10025):
return address_n[:1]
return None
@@ -183,7 +183,7 @@ def get_address(
address: str,
script_type: messages.InputScriptType | None,
show_display: bool,
- multisig_xpub: List[str],
+ multisig_xpub: list[str],
multisig_threshold: int | None,
multisig_suffix_length: int,
multisig_sort_pubkeys: bool,
@@ -461,7 +461,7 @@ def sign_message(
script_type: Optional[messages.InputScriptType],
electrum_compat: bool,
chunkify: bool,
-) -> Dict[str, str]:
+) -> dict[str, str]:
"""Sign message using address of given path."""
address_n = tools.parse_path(address)
if script_type is None:
### python/src/trezorlib/cli/crypto.py
@@ -14,7 +14,7 @@
# You should have received a copy of the License along with this library.
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
-from typing import TYPE_CHECKING, Tuple
+from typing import TYPE_CHECKING
import click
@@ -61,7 +61,7 @@ def encrypt_keyvalue(
address: str,
key: str,
value: str,
- prompt: Tuple[bool, bool],
+ prompt: tuple[bool, bool],
) -> str:
"""Encrypt value by given key and path.
@@ -97,7 +97,7 @@ def decrypt_keyvalue(
address: str,
key: str,
value: str,
- prompt: Tuple[bool, bool],
+ prompt: tuple[bool, bool],
) -> bytes:
"""Decrypt value by given key and path.
### python/src/trezorlib/cli/ethereum.py
@@ -20,17 +20,7 @@
import tarfile
from decimal import Decimal
from pathlib import Path
-from typing import (
- TYPE_CHECKING,
- Any,
- AnyStr,
- Dict,
- List,
- NoReturn,
- Optional,
- TextIO,
- cast,
-)
+from typing import TYPE_CHECKING, Any, AnyStr, NoReturn, Optional, TextIO, cast
import click
@@ -115,7 +105,7 @@ def _amount_to_int(
def _parse_access_list(
ctx: click.Context, param: Any, value: str
-) -> List[EthereumAccessList]:
+) -> list[EthereumAccessList]:
try:
return [_parse_access_list_item(val) for val in value]
@@ -163,7 +153,7 @@ def _erc20_contract(
def _format_access_list(
- access_list: List[EthereumAccessList],
+ access_list: list[EthereumAccessList],
) -> "_rlp.RLPItem":
return [
(ethereum.decode_hex(item.address), item.storage_keys) for item in access_list
@@ -396,7 +386,7 @@ def sign_tx(
token: Optional[str],
max_gas_fee: Optional[int],
max_priority_fee: Optional[int],
- access_list: List[EthereumAccessList],
+ access_list: list[EthereumAccessList],
eip2718_type: Optional[int],
chunkify: bool,
) -> str:
@@ -571,7 +561,7 @@ def sign_tx(
@with_session
def sign_message(
session: "Session", address: str, message: str, chunkify: bool
-) -> Dict[str, str]:
+) -> dict[str, str]:
"""Sign message with Ethereum address."""
address_n = tools.parse_path(address)
network = _network_def_from_address_n(address_n)
@@ -595,7 +585,7 @@ def sign_message(
@with_session
def sign_typed_data(
session: "Session", address: str, metamask_v4_compat: bool, file: TextIO
-) -> Dict[str, str]:
+) -> dict[str, str]:
"""Sign typed data (EIP-712) with Ethereum address.
Currently NOT supported:
@@ -647,7 +637,7 @@ def verify_message(
@with_session
def sign_typed_data_hash(
session: "Session", address: str, domain_hash_hex: str, message_hash_hex: str
-) -> Dict[str, str]:
+) -> dict[str, str]:
"""
Sign hash of typed data (EIP-712) with Ethereum address.
### python/src/trezorlib/cli/firmware.py
@@ -17,17 +17,8 @@
import os
import sys
import time
-from typing import (
- TYPE_CHECKING,
- Any,
- BinaryIO,
- Dict,
- Iterable,
- List,
- Optional,
- Tuple,
- Union,
-)
+from collections.abc import Iterable
+from typing import TYPE_CHECKING, Any, BinaryIO, Optional, Union
from urllib.parse import urlparse
import click
@@ -54,7 +45,7 @@
)
-def _print_version(version: Tuple[int, int, int, int]) -> None:
+def _print_version(version: tuple[int, int, int, int]) -> None:
major, minor, patch, build = version
click.echo(f"Firmware version {major}.{minor}.{patch} build {build}")
@@ -201,7 +192,7 @@ def check_device_match(
def get_all_firmware_releases(
model: TrezorModel, bitcoin_only: bool
-) -> List[Dict[str, Any]]:
+) -> list[dict[str, Any]]:
"""Get sorted list of all releases suitable for inputted parameters"""
url = f"https://data.trezor.io/firmware/{model.internal_name.lower()}/releases.json"
req = requests.get(url)
@@ -221,7 +212,7 @@ def get_all_firmware_releases(
def get_url_and_fingerprint_from_release(
release: dict,
bitcoin_only: bool,
-) -> Tuple[str, str]:
+) -> tuple[str, str]:
"""Get appropriate url and fingerprint from release dictionary."""
if bitcoin_only:
url = release["url_bitcoinonly"]
@@ -243,7 +234,7 @@ def find_specified_firmware_version(
model: TrezorModel,
version: str,
bitcoin_only: bool,
-) -> Tuple[str, str]:
+) -> tuple[str, str]:
"""Get the url from which to download the firmware and its expected fingerprint.
If the specified version is not found, exits with a failure.
@@ -276,7 +267,7 @@ def find_best_firmware_version(
client: "TrezorClient",
version: Optional[str],
bitcoin_only: Optional[bool],
-) -> Tuple[str, str]:
+) -> tuple[str, str]:
"""Get the url from which to download the firmware and its expected fingerprint.
When the version (X.Y.Z) is specified, checks for that specific release.
### python/src/trezorlib/cli/monero.py
@@ -14,7 +14,7 @@
# You should have received a copy of the License along with this library.
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
-from typing import TYPE_CHECKING, Dict
+from typing import TYPE_CHECKING
import click
@@ -66,7 +66,7 @@ def get_address(
@with_session
def get_watch_key(
session: "Session", address: str, network_type: messages.MoneroNetworkType
-) -> Dict[str, str]:
+) -> dict[str, str]:
"""Get Monero watch key for specified path."""
address_n = tools.parse_path(address)
res = monero.get_watch_key(session, address_n, network_type)
### python/src/trezorlib/cosi.py
@@ -14,8 +14,8 @@
# You should have received a copy of the License along with this library.
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
+from collections.abc import Iterable, Sequence
from functools import reduce
-from typing import Iterable, Sequence, Tuple
from . import _ed25519
@@ -45,7 +45,7 @@ def combine_sig(
def get_nonce(
sk: Ed25519PrivateKey, data: bytes, ctr: int = 0
-) -> Tuple[int, Ed25519PublicPoint]:
+) -> tuple[int, Ed25519PublicPoint]:
"""Calculate CoSi nonces for given data.
These differ from Ed25519 deterministic nonces in that there is a counter appended at end.
### python/src/trezorlib/debuglink.py
@@ -51,8 +51,8 @@
ExpectedResponse = t.Union[ExpectedMessage, tuple[bool, ExpectedMessage]]
ExpectedResponses = t.Sequence[ExpectedResponse]
- AnyDict = t.Dict[str, t.Any]
- Coords = t.Tuple[int, int]
+ AnyDict = dict[str, t.Any]
+ Coords = tuple[int, int]
class InputFunc(Protocol):
@@ -747,7 +747,7 @@ def encode_pin(self, pin: str, matrix: str | None = None) -> str:
return "".join([str(matrix.index(p) + 1) for p in pin])
- def read_recovery_word(self) -> t.Tuple[str | None, int | None]:
+ def read_recovery_word(self) -> tuple[str | None, int | None]:
state = self.state()
return (state.recovery_fake_word, state.recovery_word_pos)
@@ -841,7 +841,7 @@ def input(self, word: str) -> None:
def click(
self,
- click: t.Tuple[int, int],
+ click: tuple[int, int],
hold_ms: int | None = None,
wait: bool | None = None,
) -> None:
@@ -1222,10 +1222,10 @@ def get_pin(self, _request: messages.PinMatrixRequest | None = None) -> str:
class MessageFilter:
def __init__(
- self, message_type: t.Type[protobuf.MessageType], **fields: t.Any
+ self, message_type: type[protobuf.MessageType], **fields: t.Any
) -> None:
self.message_type = message_type
- self.fields: t.Dict[str, t.Any] = {}
+ self.fields: dict[str, t.Any] = {}
self.update_fields(**fields)
def update_fields(self, **fields: t.Any) -> "MessageFilter":
@@ -1276,7 +1276,7 @@ def match(self, message: protobuf.MessageType) -> bool:
return True
def to_string(self, maxwidth: int = 80) -> str:
- fields: list[t.Tuple[str, str]] = []
+ fields: list[tuple[str, str]] = []
for field in self.message_type.FIELDS.values():
if field.name not in self.fields:
continue
@@ -1595,7 +1595,7 @@ def set_expected_responses(self, expected: ExpectedResponses) -> None:
def set_filter(
self,
- message_type: t.Type[protobuf.MessageType],
+ message_type: type[protobuf.MessageType],
callback: t.Callable[[protobuf.MessageType], protobuf.MessageType] | None,
) -> None:
"""Configure a filter function for a specified message type.
@@ -2210,13 +2210,13 @@ def _label_choices(self, char: str) -> "tuple[str, ...]":
else:
return PASSPHRASE_SPECIAL
- def passphrase(self, char: str) -> t.Tuple[Coords, int]:
+ def passphrase(self, char: str) -> tuple[Coords, int]:
choices = self._passphrase_choices(char)
idx = next(i for i, letters in enumerate(choices) if char in letters)
click_amount = choices[idx].index(char) + 1
return self.debuglink.screen_buttons.pin_passphrase_index(idx), click_amount
- def label(self, char: str) -> t.Tuple[Coords, int]:
+ def label(self, char: str) -> tuple[Coords, int]:
choices = self._label_choices(char)
idx = next(i for i, letters in enumerate(choices) if char in letters)
click_amount = choices[idx].index(char) + 1
@@ -2248,7 +2248,7 @@ def _type_word_bip39(self, word: str) -> t.Iterator[Coords]:
for _ in range(amount):
yield coords
- def _letter_coords_and_amount(self, letter: str) -> t.Tuple[Coords, int]:
+ def _letter_coords_and_amount(self, letter: str) -> tuple[Coords, int]:
idx = next(
i for i, letters in enumerate(BUTTON_LETTERS_BIP39) if letter in letters
)
### python/src/trezorlib/definitions.py
@@ -68,7 +68,7 @@ class DefinitionPayload(Struct):
class Definition(Struct):
payload: DefinitionPayload = subcon(DefinitionPayload)
- proof: t.List[bytes]
+ proof: list[bytes]
sigmask: int
signature: bytes
### python/src/trezorlib/device.py
@@ -23,15 +23,8 @@
import secrets
import time
import warnings
-from typing import (
- TYPE_CHECKING,
- Callable,
- Iterable,
- Optional,
- Sequence,
- Tuple,
- overload,
-)
+from collections.abc import Iterable, Sequence
+from typing import TYPE_CHECKING, Callable, Optional, overload
from slip10 import SLIP10
@@ -344,7 +337,7 @@ def setup(
entropy_check_count: Optional[int] = None,
paths: Iterable[Address] = [],
_get_entropy: Callable[[], bytes] = _get_external_entropy,
-) -> Iterable[Tuple[Address, str]]:
+) -> Iterable[tuple[Address, str]]:
"""Create a new wallet on device.
On supporting devices, automatically performs the entropy check: for N rounds, ask
### python/src/trezorlib/eos.py
@@ -15,7 +15,7 @@
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
from datetime import datetime
-from typing import TYPE_CHECKING, List, Tuple
+from typing import TYPE_CHECKING
from . import exceptions, messages
from .tools import b58decode, workflow
@@ -72,7 +72,7 @@ def parse_asset(asset: str) -> messages.EosAsset:
return messages.EosAsset(amount=amount, symbol=symbol)
-def public_key_to_buffer(pub_key: str) -> Tuple[int, bytes]:
+def public_key_to_buffer(pub_key: str) -> tuple[int, bytes]:
_t = 0
if pub_key[:3] == "EOS":
pub_key = pub_key[3:]
@@ -295,7 +295,7 @@ def parse_action(action: dict) -> messages.EosTxActionAck:
def parse_transaction_json(
transaction: dict,
-) -> Tuple[messages.EosTxHeader, List[messages.EosTxActionAck]]:
+) -> tuple[messages.EosTxHeader, list[messages.EosTxActionAck]]:
header = messages.EosTxHeader(
expiration=int(
(
### python/src/trezorlib/ethereum.py
@@ -16,8 +16,9 @@
import re
import warnings
+from collections.abc import Sequence
from dataclasses import dataclass
-from typing import TYPE_CHECKING, Any, AnyStr, Dict, List, Optional, Sequence, Union
+from typing import TYPE_CHECKING, Any, AnyStr, Optional, Union
from typing_extensions import Self
@@ -352,7 +353,7 @@ def sign_tx_eip1559(
chain_id: int,
max_gas_fee: int,
max_priority_fee: int,
- access_list: Optional[List[messages.EthereumAccessList]] = None,
+ access_list: Optional[list[messages.EthereumAccessList]] = None,
definitions: Optional[messages.EthereumDefinitions] = None,
chunkify: bool = False,
payment_req: Optional[messages.PaymentRequest] = None,
@@ -407,7 +408,7 @@ def sign_message(
def sign_typed_data(
session: "Session",
n: "Address",
- data: Dict[str, Any],
+ data: dict[str, Any],
*,
metamask_v4_compat: bool = True,
definitions: Optional[messages.EthereumDefinitions] = None,
@@ -430,7 +431,7 @@ def sign_typed_data(
while isinstance(response, messages.EthereumTypedDataStructRequest):
struct_name = response.name
- members: List["messages.EthereumStructMember"] = []
+ members: list["messages.EthereumStructMember"] = []
for field in types[struct_name]:
field_type = get_field_type(field["type"], types)
struct_member = messages.EthereumStructMember(
### python/src/trezorlib/fido.py
@@ -16,7 +16,8 @@
from __future__ import annotations
-from typing import TYPE_CHECKING, Sequence
+from collections.abc import Sequence
+from typing import TYPE_CHECKING
from . import messages
from .tools import workflow
### python/src/trezorlib/firmware/sanity_struct.py
@@ -57,7 +57,7 @@ class SanityCheckedStruct(Struct):
@classmethod
def parse(
- cls: t.Type[Self], data: bytes, *, strict: bool = STRICT_SANITY_CHECK_DEFAULT
+ cls: type[Self], data: bytes, *, strict: bool = STRICT_SANITY_CHECK_DEFAULT
) -> Self:
parsed_image = super().parse(data)
try:
### python/src/trezorlib/mapping.py
@@ -32,12 +32,12 @@ class ProtobufMapping:
"""Mapping of protobuf classes to Python classes"""
def __init__(self) -> None:
- self.type_to_class: t.Dict[int, t.Type[protobuf.MessageType]] = {}
- self.class_to_type_override: t.Dict[t.Type[protobuf.MessageType], int] = {}
+ self.type_to_class: dict[int, type[protobuf.MessageType]] = {}
+ self.class_to_type_override: dict[type[protobuf.MessageType], int] = {}
def register(
self,
- msg_class: t.Type[protobuf.MessageType],
+ msg_class: type[protobuf.MessageType],
msg_wire_type: int | None = None,
) -> None:
"""Register a Python class as a protobuf type.
### python/src/trezorlib/merkle_tree.py
@@ -54,7 +54,7 @@ class Leaf:
def __init__(self, value: bytes) -> None:
self.tree_hash = leaf_hash(value)
- self.proof: t.List[bytes] = []
+ self.proof: list[bytes] = []
def add_to_proof_list(self, proof_entry: bytes) -> None:
self.proof.append(proof_entry)
@@ -113,7 +113,7 @@ class MerkleTree:
verifier does not need to distinguish between left and right subtree.
"""
- entries: t.Dict[bytes, Leaf]
+ entries: dict[bytes, Leaf]
"""Map of leaf hash -> leaf node.
Use `leaf_hash` to calculate the hash of a value, or use `get_proof(value)`
@@ -163,15 +163,15 @@ def _build_tree(leaves: t.Sequence[NodeType]) -> NodeType:
def get_root_hash(self) -> bytes:
return self.root.tree_hash
- def get_proof(self, value: bytes) -> t.List[bytes]:
+ def get_proof(self, value: bytes) -> list[bytes]:
"""Get the proof for a given value."""
try:
return self.entries[leaf_hash(value)].proof
except KeyError:
raise KeyError("Value not found in Merkle tree") from None
-def evaluate_proof(value: bytes, proof: t.List[bytes]) -> bytes:
+def evaluate_proof(value: bytes, proof: list[bytes]) -> bytes:
"""Evaluate the provided proof of membership.
Reconstructs the Merkle root hash for a tree that contains `value` as a leaf node,
### python/src/trezorlib/messages.py
@@ -2,8 +2,9 @@
# fmt: off
# isort:skip_file
+from collections.abc import Sequence
from enum import IntEnum
-from typing import Sequence, Optional
+from typing import Optional
from . import protobuf
### python/src/trezorlib/models.py
@@ -16,14 +16,14 @@
from __future__ import annotations
+from collections.abc import Collection
from dataclasses import dataclass
-from typing import Collection, Tuple
from . import _modeldata as _md
from . import mapping, messages
from ._modeldata import registry as _registry
-UsbId = Tuple[int, int]
+UsbId = tuple[int, int]
VENDORS = ("bitcointrezor.com", "trezor.io")
### python/src/trezorlib/solana.py
@@ -14,7 +14,7 @@
# You should have received a copy of the License along with this library.
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
-from typing import TYPE_CHECKING, Any, List, Optional
+from typing import TYPE_CHECKING, Any, Optional
from . import exceptions, messages
from .tools import workflow
@@ -26,7 +26,7 @@
@workflow(capability=messages.Capability.Solana)
def get_public_key(
session: "Session",
- address_n: List[int],
+ address_n: list[int],
show_display: bool,
) -> bytes:
return session.call(
@@ -42,7 +42,7 @@ def get_address(*args: Any, **kwargs: Any) -> str:
@workflow(capability=messages.Capability.Solana)
def get_authenticated_address(
session: "Session",
- address_n: List[int],
+ address_n: list[int],
show_display: bool,
chunkify: bool = False,
) -> messages.SolanaAddress:
@@ -59,7 +59,7 @@ def get_authenticated_address(
@workflow(capability=messages.Capability.Solana)
def sign_tx(
session: "Session",
- address_n: List[int],
+ address_n: list[int],
serialized_tx: bytes,
additional_info: Optional[messages.SolanaTxAdditionalInfo],
payment_req: Optional[messages.PaymentRequest] = None,
@@ -80,7 +80,7 @@ def sign_tx(
@workflow(capability=messages.Capability.Solana)
def sign_message(
session: "Session",
- address_n: List[int],
+ address_n: list[int],
message: messages.SolanaOffchainMessageV1,
chunkify: bool = False,
) -> messages.SolanaMessageSignature:
### python/src/trezorlib/testing/common.py
@@ -1,4 +1,5 @@
-from typing import TYPE_CHECKING, Generator, Optional
+from collections.abc import Generator
+from typing import TYPE_CHECKING, Optional
from .. import messages
from ..debuglink import LayoutType
### python/src/trezorlib/toif.py
@@ -16,9 +16,9 @@
import struct
import zlib
+from collections.abc import Sequence
from dataclasses import dataclass
from enum import Enum
-from typing import Sequence, Tuple
import construct as c
from typing_extensions import Literal
@@ -35,7 +35,7 @@
PIL_AVAILABLE = False
-RGBPixel = Tuple[int, int, int]
+RGBPixel = tuple[int, int, int]
class ToifMode(Enum):
@@ -117,7 +117,7 @@ def _from_pil_grayscale(
def _from_pil_grayscale_alpha(
- pixels: Sequence[Tuple[int, int]], right_hi: bool, width: int, height: int
+ pixels: Sequence[tuple[int, int]], right_hi: bool, width: int, height: int
) -> bytes:
data = bytearray()
for y in range(0, height):
@@ -161,7 +161,7 @@ def _to_grayscale(data: bytes, right_hi: bool) -> bytes:
@dataclass
class Toif:
mode: ToifMode
- size: Tuple[int, int]
+ size: tuple[int, int]
data: bytes
def __post_init__(self) -> None:
@@ -230,7 +230,7 @@ def load(filename: str) -> Toif:
def from_image(
image: "Image.Image",
- background: Tuple[int, int, int, int] = (0, 0, 0, 255),
+ background: tuple[int, int, int, int] = (0, 0, 0, 255),
legacy_format: bool = False,
) -> Toif:
if not PIL_AVAILABLE:
### python/src/trezorlib/transport/__init__.py
@@ -38,7 +38,7 @@
""".strip()
-MessagePayload = t.Tuple[int, bytes]
+MessagePayload = tuple[int, bytes]
class TransportException(TrezorException):
### python/src/trezorlib/transport/bridge.py
@@ -59,7 +59,7 @@ def call_bridge(
return r
-def get_bridge_version() -> t.Tuple[int, ...]:
+def get_bridge_version() -> tuple[int, ...]:
config = call_bridge("configure").json()
return tuple(map(int, config["version"].split(".")))
### python/src/trezorlib/transport/hid.py
@@ -36,7 +36,7 @@
HID_IMPORTED = False
-HidDevice = t.Dict[str, t.Any]
+HidDevice = dict[str, t.Any]
HidDeviceHandle = t.Any
@@ -67,7 +67,7 @@ def enumerate(
models = {TREZOR_ONE}
usb_ids = [id for model in models for id in model.usb_ids]
- devices: t.List["HidTransport"] = []
+ devices: list["HidTransport"] = []
for dev in hid.enumerate(0, 0):
usb_id = (dev["vendor_id"], dev["product_id"])
if usb_id not in usb_ids:
### python/src/trezorlib/transport/udp.py
@@ -20,7 +20,8 @@
import socket
import time
from collections import deque
-from typing import TYPE_CHECKING, Deque, Iterable, Tuple
+from collections.abc import Iterable
+from typing import TYPE_CHECKING
from ..log import DUMP_PACKETS
from . import Timeout, Transport, TransportException
@@ -37,7 +38,7 @@ class _SendRateLimiter:
def __init__(self, max_events: int, window: float) -> None:
self.max_events = max_events
self.window = window
- self._events: Deque[float] = deque()
+ self._events: deque[float] = deque()
def wait(self) -> None:
now = time.monotonic()
@@ -71,7 +72,7 @@ def __init__(self, device: str | None = None) -> None:
devparts = device.split(":")
host = devparts[0]
port = int(devparts[1]) if len(devparts) > 1 else UdpTransport.DEFAULT_PORT
- self.device: Tuple[str, int] = (host, port)
+ self.device: tuple[str, int] = (host, port)
self.socket: socket.socket | None = None
self._send_limiter = _SendRateLimiter(
### python/src/trezorlib/transport/webusb.py
@@ -20,7 +20,7 @@
import logging
import sys
import time
-from typing import Iterable, List
+from collections.abc import Iterable
from ..log import DUMP_PACKETS
from ..models import ALL_MODELS, TrezorModel
@@ -82,7 +82,7 @@ def enumerate(
if models is None:
models = ALL_MODELS
usb_ids = [id for model in models for id in model.usb_ids]
- devices: List["WebUsbTransport"] = []
+ devices: list["WebUsbTransport"] = []
for dev in cls.context.getDeviceIterator(skip_on_error=True):
usb_id = (dev.getVendorID(), dev.getProductID())
if usb_id not in usb_ids:
### python/src/trezorlib/tron.py
@@ -1,5 +1,5 @@
import io
-from typing import TYPE_CHECKING, Any, Tuple, Union
+from typing import TYPE_CHECKING, Any, Union
from . import messages
from .protobuf import load_message
@@ -25,7 +25,7 @@
def from_raw_data(
raw_data: bytes,
-) -> Tuple[messages.TronSignTx, "TronMessageType"]:
+) -> tuple[messages.TronSignTx, "TronMessageType"]:
raw_tx = load_message(io.BytesIO(raw_data), messages.TronRawTransaction)
tx = messages.TronSignTx(
ref_block_bytes=raw_tx.ref_block_bytes,
### python/tests/test_merkle_tree.py
@@ -96,9 +96,9 @@ def test_node(node: t.Union[Node, Leaf], expected_hash: str) -> None:
@pytest.mark.parametrize("values, root_hash, proofs", MERKLE_TREE_VECTORS)
def test_tree(
- values: t.List[bytes],
+ values: list[bytes],
root_hash: bytes,
- proofs: t.Dict[bytes, t.List[bytes]],
+ proofs: dict[bytes, list[bytes]],
) -> None:
mt = MerkleTree(values)
assert mt.get_root_hash() == root_hash
### python/tools/build_tx.py
@@ -18,7 +18,7 @@
import decimal
import json
-from typing import Any, Dict, List, Optional, Tuple
+from typing import Any, Optional
import click
import requests
@@ -48,7 +48,7 @@ def prompt(*args: Any, **kwargs: Any):
return click.prompt(*args, err=True, **kwargs)
-def _default_script_type(address_n: Optional[List[int]], script_types: Any) -> str:
+def _default_script_type(address_n: Optional[list[int]], script_types: Any) -> str:
script_type = "address"
if address_n is None:
@@ -62,16 +62,16 @@ def _default_script_type(address_n: Optional[List[int]], script_types: Any) -> s
# return script_types[script_type]
-def parse_vin(s: str) -> Tuple[bytes, int]:
+def parse_vin(s: str) -> tuple[bytes, int]:
txid, vout = s.split(":")
return bytes.fromhex(txid), int(vout)
def _get_inputs_interactive(
blockbook_url: str,
-) -> Tuple[List[messages.TxInputType], Dict[str, messages.TransactionType]]:
- inputs: List[messages.TxInputType] = []
- txes: Dict[str, messages.TransactionType] = {}
+) -> tuple[list[messages.TxInputType], dict[str, messages.TransactionType]]:
+ inputs: list[messages.TxInputType] = []
+ txes: dict[str, messages.TransactionType] = {}
while True:
echo()
prev = prompt(
@@ -139,8 +139,8 @@ def _get_inputs_interactive(
return inputs, txes
-def _get_outputs_interactive() -> List[messages.TxOutputType]:
- outputs: List[messages.TxOutputType] = []
+def _get_outputs_interactive() -> list[messages.TxOutputType]:
+ outputs: list[messages.TxOutputType] = []
while True:
echo()
address = prompt("Output address for non-change output", default="")
### python/tools/encfs_aes_getpass.py
@@ -29,7 +29,8 @@
import json
import os
import sys
-from typing import TYPE_CHECKING, Sequence
+from collections.abc import Sequence
+from typing import TYPE_CHECKING
import trezorlib
import trezorlib.misc
### python/tools/pwd_reader.py
@@ -20,7 +20,6 @@
import hmac
import json
import os
-from typing import Tuple
from urllib.parse import urlparse
from cryptography.hazmat.backends import default_backend
@@ -46,7 +45,7 @@ def getMasterKey(session: Session) -> str:
# Deriving file name and encryption key
-def getFileEncKey(key: str) -> Tuple[str, str, str]:
+def getFileEncKey(key: str) -> tuple[str, str, str]:
filekey, enckey = key[: len(key) // 2], key[len(key) // 2 :]
FILENAME_MESS = b"5f91add3fa1c3c76e90c90a3bd0999e2bd7833d06a483fe884ee60397aca277a"
digest = hmac.new(str.encode(filekey), FILENAME_MESS, hashlib.sha256).hexdigest()Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.