mirror of
https://github.com/trezor/trezor-firmware.git
synced 2026-02-20 00:33:30 +01:00
chore(python): migrate to pyproject.toml and uv
This commit is contained in:
1
python/.changelog.d/+1d468db6.deprecated
Normal file
1
python/.changelog.d/+1d468db6.deprecated
Normal file
@@ -0,0 +1 @@
|
||||
`trezorlib.__version__` is deprecated, use `importlib.metadata.version("trezor")`.
|
||||
1
python/.changelog.d/+47cd2085.removed
Normal file
1
python/.changelog.d/+47cd2085.removed
Normal file
@@ -0,0 +1 @@
|
||||
Dropped support for Python 3.8.
|
||||
1
python/.changelog.d/+cabe85ab.changed
Normal file
1
python/.changelog.d/+cabe85ab.changed
Normal file
@@ -0,0 +1 @@
|
||||
Changed build system to uv.
|
||||
2
python/.gitignore
vendored
2
python/.gitignore
vendored
@@ -8,3 +8,5 @@ MANIFEST
|
||||
*.py.cache
|
||||
/.tox
|
||||
mypy_report
|
||||
uv.lock
|
||||
/.venv
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
recursive-include bash_completion.d *.sh
|
||||
include tools/*
|
||||
graft src
|
||||
graft tests
|
||||
graft stubs
|
||||
|
||||
include AUTHORS README.md COPYING CHANGELOG.md
|
||||
include requirements*.txt
|
||||
include tox.ini pyrightconfig.json
|
||||
exclude src/trezorlib/_proto_messages.mako
|
||||
exclude tests/*.bin
|
||||
global-exclude *.pyc
|
||||
global-exclude */__pycache__/*
|
||||
91
python/pyproject.toml
Normal file
91
python/pyproject.toml
Normal file
@@ -0,0 +1,91 @@
|
||||
[project]
|
||||
name = "trezor"
|
||||
version = "0.14.0"
|
||||
description = "Python library for communicating with Trezor Hardware Wallet"
|
||||
readme = "README.md"
|
||||
license = "LGPL-3.0-only"
|
||||
license-files = ["COPYING"]
|
||||
authors = [
|
||||
{name = "Trezor", email = "info@trezor.io"}
|
||||
]
|
||||
maintainers = [
|
||||
{name = "matejcik", email = "jan.matejek@satoshilabs.com"}
|
||||
]
|
||||
keywords = ["trezor", "hardware", "wallet", "cryptocurrency", "bitcoin", "ethereum"]
|
||||
classifiers = [
|
||||
"Operating System :: POSIX :: Linux",
|
||||
"Operating System :: Microsoft :: Windows",
|
||||
"Operating System :: MacOS :: MacOS X",
|
||||
"Programming Language :: Python :: 3 :: Only",
|
||||
]
|
||||
requires-python = ">=3.9"
|
||||
dependencies = [
|
||||
"ecdsa>=0.9",
|
||||
"mnemonic>=0.20",
|
||||
"shamir-mnemonic>=0.3.0",
|
||||
"slip10>=1.0.1",
|
||||
"requests>=2.4.0",
|
||||
"click>=8,<8.3",
|
||||
"libusb1>=1.6.4",
|
||||
"construct>=2.9,!=2.10.55",
|
||||
"typing_extensions>=4.7.1",
|
||||
"construct-classes>=0.1.2",
|
||||
"cryptography>=41",
|
||||
"noiseprotocol>=0.3.1,<0.4.0",
|
||||
]
|
||||
|
||||
[project.optional-dependencies]
|
||||
hidapi = ["hidapi>=0.7.99.post20"]
|
||||
ethereum = ["web3>=5"]
|
||||
qt-widgets = ["PyQt5"]
|
||||
extra = ["Pillow>=10"]
|
||||
stellar = ["stellar-sdk>=6"]
|
||||
full = [
|
||||
"hidapi>=0.7.99.post20",
|
||||
"web3>=5",
|
||||
"PyQt5",
|
||||
"Pillow>=10",
|
||||
"stellar-sdk>=6",
|
||||
]
|
||||
|
||||
[project.urls]
|
||||
Homepage = "https://github.com/trezor/trezor-firmware/tree/main/python"
|
||||
Repository = "https://github.com/trezor/trezor-firmware"
|
||||
Documentation = "https://github.com/trezor/trezor-firmware/tree/main/python"
|
||||
|
||||
[project.scripts]
|
||||
trezorctl = "trezorlib.cli.trezorctl:cli"
|
||||
|
||||
[build-system]
|
||||
requires = ["hatchling"]
|
||||
build-backend = "hatchling.build"
|
||||
|
||||
[tool.uv]
|
||||
package = true
|
||||
|
||||
[tool.hatch.build.targets.wheel]
|
||||
packages = ["src/trezorlib"]
|
||||
|
||||
[tool.hatch.build.targets.sdist]
|
||||
exclude = [
|
||||
"/.*",
|
||||
"/helper-scripts",
|
||||
"/CHANGELOG.unreleased",
|
||||
"/default.nix",
|
||||
"/Makefile",
|
||||
"/towncrier.toml",
|
||||
"tests/*.bin",
|
||||
"src/trezorlib/_proto_messages.mako",
|
||||
]
|
||||
|
||||
[dependency-groups]
|
||||
dev = [
|
||||
"autoflake>=2.3.1",
|
||||
"black>=25",
|
||||
"flake8>=2.3.0",
|
||||
"isort>=5.13.2",
|
||||
"pytest>=8.3.5",
|
||||
"pytest-random-order>=1.2.0",
|
||||
"tox>=4.25.0",
|
||||
"tox-uv>=1.13.1",
|
||||
]
|
||||
@@ -1,4 +0,0 @@
|
||||
hidapi>=0.7.99.post20
|
||||
web3>=5
|
||||
Pillow>=10
|
||||
stellar-sdk>=6
|
||||
@@ -1,12 +0,0 @@
|
||||
ecdsa>=0.9
|
||||
mnemonic>=0.20
|
||||
shamir-mnemonic>=0.3.0
|
||||
slip10>=1.0.1
|
||||
requests>=2.4.0
|
||||
click>=7,<8.2
|
||||
libusb1>=1.6.4
|
||||
construct>=2.9,!=2.10.55
|
||||
typing_extensions>=4.7.1
|
||||
construct-classes>=0.1.2
|
||||
cryptography>=41
|
||||
noiseprotocol>=0.3.1,<0.4.0
|
||||
@@ -2,6 +2,7 @@
|
||||
filename = *.py
|
||||
exclude =
|
||||
.tox/,
|
||||
.venv/,
|
||||
build/,
|
||||
dist/,
|
||||
vendor/,
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# This file is part of the Trezor project.
|
||||
#
|
||||
# Copyright (C) SatoshiLabs and contributors
|
||||
#
|
||||
# This library is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License version 3
|
||||
# as published by the Free Software Foundation.
|
||||
#
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# 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>.
|
||||
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
from setuptools import find_packages, setup
|
||||
|
||||
CWD = Path(__file__).resolve().parent
|
||||
|
||||
install_requires = (CWD / "requirements.txt").read_text().splitlines()
|
||||
|
||||
extras_require = {
|
||||
"hidapi": ["hidapi>=0.7.99.post20"],
|
||||
"ethereum": ["web3>=5"],
|
||||
"qt-widgets": ["PyQt5"],
|
||||
"extra": ["Pillow>=10"],
|
||||
"stellar": ["stellar-sdk>=6"],
|
||||
}
|
||||
|
||||
extras_require["full"] = sum(extras_require.values(), [])
|
||||
|
||||
|
||||
def find_version():
|
||||
version_file = (CWD / "src" / "trezorlib" / "__init__.py").read_text()
|
||||
version_match = re.search(r"^__version__ = \"(.*)\"$", version_file, re.M)
|
||||
if version_match:
|
||||
return version_match.group(1)
|
||||
else:
|
||||
raise RuntimeError("Version string not found")
|
||||
|
||||
|
||||
setup(
|
||||
name="trezor",
|
||||
version=find_version(),
|
||||
author="Trezor",
|
||||
author_email="info@trezor.io",
|
||||
license="LGPLv3",
|
||||
description="Python library for communicating with Trezor Hardware Wallet",
|
||||
long_description=(CWD / "README.md").read_text()
|
||||
+ "\n\n"
|
||||
+ (CWD / "CHANGELOG.md").read_text(),
|
||||
long_description_content_type="text/markdown",
|
||||
url="https://github.com/trezor/trezor-firmware/tree/master/python",
|
||||
package_data={"trezorlib": ["py.typed"]},
|
||||
packages=find_packages("src"),
|
||||
package_dir={"": "src"},
|
||||
entry_points={"console_scripts": ["trezorctl=trezorlib.cli.trezorctl:cli"]},
|
||||
install_requires=install_requires,
|
||||
extras_require=extras_require,
|
||||
python_requires=">=3.8",
|
||||
include_package_data=True,
|
||||
zip_safe=False,
|
||||
classifiers=[
|
||||
"License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)",
|
||||
"Operating System :: POSIX :: Linux",
|
||||
"Operating System :: Microsoft :: Windows",
|
||||
"Operating System :: MacOS :: MacOS X",
|
||||
"Programming Language :: Python :: 3 :: Only",
|
||||
],
|
||||
)
|
||||
@@ -14,4 +14,15 @@
|
||||
# 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>.
|
||||
|
||||
__version__ = "0.14.0"
|
||||
import importlib.metadata
|
||||
import warnings
|
||||
|
||||
|
||||
def __getattr__(name: str) -> str:
|
||||
if name == "__version__":
|
||||
warnings.warn(
|
||||
"__version__ is deprecated and will be removed in 0.15.0, use importlib.metadata.version('trezor') instead",
|
||||
DeprecationWarning,
|
||||
)
|
||||
return importlib.metadata.version("trezor")
|
||||
raise AttributeError(f"module {__name__} has no attribute {name}")
|
||||
|
||||
@@ -16,6 +16,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>.
|
||||
|
||||
import importlib.metadata
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
@@ -24,7 +25,7 @@ from typing import TYPE_CHECKING, Any, Callable, Iterable, Optional, TypeVar, ca
|
||||
|
||||
import click
|
||||
|
||||
from .. import __version__, log, messages, protobuf
|
||||
from .. import log, messages, protobuf
|
||||
from ..transport import DeviceIsBusy, enumerate_devices
|
||||
from ..transport.session import Session
|
||||
from ..transport.udp import UdpTransport
|
||||
@@ -141,7 +142,7 @@ class TrezorctlGroup(AliasedGroup):
|
||||
# This means that there is no reasonable way to use `hasattr` to detect where we
|
||||
# are, unless we want to look at the private `_result_callback` attribute.
|
||||
# Instead, we look at Click version and hope for the best.
|
||||
from click import __version__ as click_version
|
||||
click_version = importlib.metadata.version("click")
|
||||
|
||||
if click_version.startswith("7."):
|
||||
return super().resultcallback() # type: ignore [Cannot access attribute]
|
||||
@@ -194,7 +195,7 @@ def configure_logging(verbose: int) -> None:
|
||||
"--record",
|
||||
help="Record screen changes into a specified directory.",
|
||||
)
|
||||
@click.version_option(version=__version__)
|
||||
@click.version_option(package_name="trezor")
|
||||
@click.pass_context
|
||||
def cli_main(
|
||||
ctx: click.Context,
|
||||
@@ -310,7 +311,7 @@ def list_devices(no_resolve: bool) -> Optional[Iterable["Transport"]]:
|
||||
@cli.command()
|
||||
def version() -> str:
|
||||
"""Show version of trezorctl/trezorlib."""
|
||||
return __version__
|
||||
return importlib.metadata.version("trezor")
|
||||
|
||||
|
||||
#
|
||||
|
||||
@@ -165,7 +165,7 @@ def test_simple_message():
|
||||
uvarint=12345678910,
|
||||
svarint=-12345678910,
|
||||
bool=True,
|
||||
bytes=b"\xDE\xAD\xCA\xFE",
|
||||
bytes=b"\xde\xad\xca\xfe",
|
||||
unicode="Příliš žluťoučký kůň úpěl ďábelské ódy 😊",
|
||||
enum=SomeEnum.Five,
|
||||
)
|
||||
@@ -177,7 +177,7 @@ def test_simple_message():
|
||||
assert retr.uvarint == 12345678910
|
||||
assert retr.svarint == -12345678910
|
||||
assert retr.bool is True
|
||||
assert retr.bytes == b"\xDE\xAD\xCA\xFE"
|
||||
assert retr.bytes == b"\xde\xad\xca\xfe"
|
||||
assert retr.unicode == "Příliš žluťoučký kůň úpěl ďábelské ódy 😊"
|
||||
assert retr.enum == SomeEnum.Five
|
||||
assert retr.enum == 5
|
||||
|
||||
@@ -25,6 +25,7 @@ encfs --standard --extpass=./encfs_aes_getpass.py ~/.crypt ~/crypt
|
||||
"""
|
||||
|
||||
import hashlib
|
||||
import importlib.metadata
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
@@ -36,7 +37,8 @@ from trezorlib.client import TrezorClient
|
||||
from trezorlib.tools import Address
|
||||
from trezorlib.transport import enumerate_devices
|
||||
|
||||
version_tuple = tuple(map(int, trezorlib.__version__.split(".")))
|
||||
trezor_version = importlib.metadata.version("trezor")
|
||||
version_tuple = tuple(map(int, trezor_version.split(".")))
|
||||
if not (0, 11) <= version_tuple < (0, 14):
|
||||
raise RuntimeError("trezorlib version mismatch (required: 0.13, 0.12, or 0.11)")
|
||||
|
||||
|
||||
@@ -5,21 +5,17 @@
|
||||
|
||||
[tox]
|
||||
envlist =
|
||||
py{38,39,310,311,312}-{minimal,default,full}
|
||||
py{38,39,310,311,312}-click{7,80}
|
||||
py{38,39,310,311,312}-click81
|
||||
py{39,310,311,312,313}-{minimal,default,full}
|
||||
py{39,310,311,312,313}-click8{0,1}
|
||||
py{310,311,312,313}-click82
|
||||
|
||||
[testenv]
|
||||
deps =
|
||||
-rrequirements.txt
|
||||
!minimal: pytest>=3.6
|
||||
!minimal: pytest-random-order
|
||||
!minimal: importlib-metadata!=0.21
|
||||
full: -rrequirements-optional.txt
|
||||
py312: setuptools
|
||||
runner = uv-venv-runner
|
||||
dependency_groups =
|
||||
!minimal: dev
|
||||
extras =
|
||||
full: full
|
||||
commands =
|
||||
# Generate local files
|
||||
python setup.py build
|
||||
# Working in the local directory, try to compile all bytecode
|
||||
python -m compileall src tests
|
||||
# Smoke-test trezorctl
|
||||
@@ -27,12 +23,10 @@ commands =
|
||||
# Run test suite
|
||||
!minimal: pytest -c setup.cfg --random-order tests
|
||||
|
||||
[testenv:py{38,39,310,311,312}-click{7,80,81}]
|
||||
deps =
|
||||
-rrequirements.txt
|
||||
click7: click>=7,<8
|
||||
click80: click>=8.0,<8.1
|
||||
click81: click>=8.1,<8.2
|
||||
[testenv:py{39,310,311,312,313}-click{80,81,82}]
|
||||
commands =
|
||||
click80: uv pip install "click>=8.0,<8.1"
|
||||
click81: uv pip install "click>=8.1,<8.2"
|
||||
click82: uv pip install "click>=8.2,<8.3"
|
||||
# Smoke-test trezorctl
|
||||
trezorctl --version
|
||||
|
||||
@@ -8,7 +8,6 @@ import click
|
||||
|
||||
VERSION_RE = re.compile(r"^(\d+)[.](\d+)[.](\d+)$")
|
||||
HEADER_LINE_RE = re.compile(r"^#define ([A-Z_]+) \S+$")
|
||||
PYTHON_VERSION_RE = re.compile(r'^__version__ = "\d+[.]\d+[.]\d+"$', flags=re.MULTILINE)
|
||||
|
||||
|
||||
def bump_header(filename, **kwargs):
|
||||
@@ -29,14 +28,8 @@ def bump_header(filename, **kwargs):
|
||||
fh.write(line)
|
||||
|
||||
|
||||
def bump_python(filename, new_version):
|
||||
with open(filename, "r+") as fh:
|
||||
contents = fh.read()
|
||||
result = PYTHON_VERSION_RE.sub(f'__version__ = "{new_version}"', contents)
|
||||
|
||||
fh.seek(0)
|
||||
fh.truncate(0)
|
||||
fh.write(result)
|
||||
def bump_python(subdir: Path, new_version: str):
|
||||
subprocess.check_call(["uv", "version", new_version], cwd=subdir)
|
||||
|
||||
|
||||
def hex_lit(version):
|
||||
@@ -89,9 +82,7 @@ def cli(project, version):
|
||||
VERSION_PATCH=patch,
|
||||
)
|
||||
elif parts[-1] == "python":
|
||||
bump_python(
|
||||
project / "src" / "trezorlib" / "__init__.py", f"{major}.{minor}.{patch}"
|
||||
)
|
||||
bump_python(project / "python", f"{major}.{minor}.{patch}")
|
||||
else:
|
||||
raise click.ClickException(f"Unknown project {project}.")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user