ledgered 0.9.1.dev4__tar.gz → 0.10.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ledgered-0.10.1/.github/workflows/build_and_tests.yml +69 -0
- {ledgered-0.9.1.dev4 → ledgered-0.10.1}/.github/workflows/codeql-analysis.yml +4 -0
- {ledgered-0.9.1.dev4 → ledgered-0.10.1}/.github/workflows/fast-checks.yml +4 -0
- {ledgered-0.9.1.dev4 → ledgered-0.10.1}/CHANGELOG.md +17 -0
- ledgered-0.10.1/MANIFEST.in +1 -0
- {ledgered-0.9.1.dev4/src/ledgered.egg-info → ledgered-0.10.1}/PKG-INFO +3 -2
- {ledgered-0.9.1.dev4 → ledgered-0.10.1}/pyproject.toml +2 -1
- {ledgered-0.9.1.dev4 → ledgered-0.10.1}/src/ledgered/__version__.py +2 -2
- ledgered-0.10.1/src/ledgered/devices/__init__.py +81 -0
- ledgered-0.10.1/src/ledgered/devices/devices.json +7 -0
- ledgered-0.10.1/src/ledgered/manifest/__init__.py +6 -0
- {ledgered-0.9.1.dev4 → ledgered-0.10.1}/src/ledgered/manifest/app.py +2 -7
- {ledgered-0.9.1.dev4 → ledgered-0.10.1}/src/ledgered/manifest/constants.py +0 -1
- {ledgered-0.9.1.dev4 → ledgered-0.10.1/src/ledgered.egg-info}/PKG-INFO +3 -2
- {ledgered-0.9.1.dev4 → ledgered-0.10.1}/src/ledgered.egg-info/SOURCES.txt +5 -0
- {ledgered-0.9.1.dev4 → ledgered-0.10.1}/src/ledgered.egg-info/requires.txt +2 -1
- {ledgered-0.9.1.dev4 → ledgered-0.10.1}/tests/_data/full_correct.toml +1 -1
- {ledgered-0.9.1.dev4 → ledgered-0.10.1}/tests/functional/manifest/test_cli.py +2 -2
- ledgered-0.10.1/tests/unit/devices/test___init__.py +65 -0
- ledgered-0.10.1/tests/unit/manifest/__init__.py +0 -0
- {ledgered-0.9.1.dev4 → ledgered-0.10.1}/tests/unit/manifest/test_app.py +3 -5
- ledgered-0.9.1.dev4/.github/workflows/build_and_tests.yml +0 -154
- ledgered-0.9.1.dev4/src/ledgered/manifest/__init__.py +0 -6
- {ledgered-0.9.1.dev4 → ledgered-0.10.1}/.codecov.yml +0 -0
- {ledgered-0.9.1.dev4 → ledgered-0.10.1}/.gitignore +0 -0
- {ledgered-0.9.1.dev4 → ledgered-0.10.1}/.pre-commit-config.yaml +0 -0
- {ledgered-0.9.1.dev4 → ledgered-0.10.1}/LICENSE +0 -0
- {ledgered-0.9.1.dev4 → ledgered-0.10.1}/README.md +0 -0
- {ledgered-0.9.1.dev4 → ledgered-0.10.1}/doc/binary.md +0 -0
- {ledgered-0.9.1.dev4 → ledgered-0.10.1}/doc/manifest.md +0 -0
- {ledgered-0.9.1.dev4 → ledgered-0.10.1}/setup.cfg +0 -0
- {ledgered-0.9.1.dev4 → ledgered-0.10.1}/src/ledgered/__init__.py +0 -0
- {ledgered-0.9.1.dev4 → ledgered-0.10.1}/src/ledgered/binary.py +0 -0
- {ledgered-0.9.1.dev4 → ledgered-0.10.1}/src/ledgered/github.py +0 -0
- {ledgered-0.9.1.dev4 → ledgered-0.10.1}/src/ledgered/manifest/cli.py +0 -0
- {ledgered-0.9.1.dev4 → ledgered-0.10.1}/src/ledgered/manifest/errors.py +0 -0
- {ledgered-0.9.1.dev4 → ledgered-0.10.1}/src/ledgered/manifest/manifest.py +0 -0
- {ledgered-0.9.1.dev4 → ledgered-0.10.1}/src/ledgered/manifest/tests.py +0 -0
- {ledgered-0.9.1.dev4 → ledgered-0.10.1}/src/ledgered/manifest/use_cases.py +0 -0
- {ledgered-0.9.1.dev4 → ledgered-0.10.1}/src/ledgered/manifest/utils.py +0 -0
- {ledgered-0.9.1.dev4 → ledgered-0.10.1}/src/ledgered/serializers.py +0 -0
- {ledgered-0.9.1.dev4 → ledgered-0.10.1}/src/ledgered/utils/__init__.py +0 -0
- {ledgered-0.9.1.dev4 → ledgered-0.10.1}/src/ledgered.egg-info/dependency_links.txt +0 -0
- {ledgered-0.9.1.dev4 → ledgered-0.10.1}/src/ledgered.egg-info/entry_points.txt +0 -0
- {ledgered-0.9.1.dev4 → ledgered-0.10.1}/src/ledgered.egg-info/top_level.txt +0 -0
- {ledgered-0.9.1.dev4 → ledgered-0.10.1}/tests/_data/Cargo.toml +0 -0
- {ledgered-0.9.1.dev4 → ledgered-0.10.1}/tests/_data/Makefile +0 -0
- {ledgered-0.9.1.dev4 → ledgered-0.10.1}/tests/_data/ledger_app.toml +0 -0
- {ledgered-0.9.1.dev4 → ledgered-0.10.1}/tests/_data/minimal.toml +0 -0
- {ledgered-0.9.1.dev4 → ledgered-0.10.1}/tests/_data/one_leaf.toml +0 -0
- {ledgered-0.9.1.dev4 → ledgered-0.10.1}/tests/functional/__init__.py +0 -0
- {ledgered-0.9.1.dev4 → ledgered-0.10.1}/tests/functional/conftest.py +0 -0
- {ledgered-0.9.1.dev4 → ledgered-0.10.1}/tests/functional/manifest/__init__.py +0 -0
- {ledgered-0.9.1.dev4 → ledgered-0.10.1}/tests/functional/test_github.py +0 -0
- {ledgered-0.9.1.dev4 → ledgered-0.10.1}/tests/unit/__init__.py +0 -0
- {ledgered-0.9.1.dev4/tests/unit/manifest → ledgered-0.10.1/tests/unit/devices}/__init__.py +0 -0
- {ledgered-0.9.1.dev4 → ledgered-0.10.1}/tests/unit/manifest/test_manifest.py +0 -0
- {ledgered-0.9.1.dev4 → ledgered-0.10.1}/tests/unit/manifest/test_tests.py +0 -0
- {ledgered-0.9.1.dev4 → ledgered-0.10.1}/tests/unit/manifest/test_use_cases.py +0 -0
- {ledgered-0.9.1.dev4 → ledgered-0.10.1}/tests/unit/test_binary.py +0 -0
- {ledgered-0.9.1.dev4 → ledgered-0.10.1}/tests/unit/test_github.py +0 -0
- {ledgered-0.9.1.dev4 → ledgered-0.10.1}/tests/unit/test_github_AppRepository.py +0 -0
- {ledgered-0.9.1.dev4 → ledgered-0.10.1}/tests/unit/test_serializers.py +0 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
name: Build, test and deploy Ledgered
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
push:
|
|
6
|
+
tags:
|
|
7
|
+
- '*'
|
|
8
|
+
branches:
|
|
9
|
+
- master
|
|
10
|
+
- develop
|
|
11
|
+
pull_request:
|
|
12
|
+
branches:
|
|
13
|
+
- master
|
|
14
|
+
- develop
|
|
15
|
+
paths:
|
|
16
|
+
- 'src/**'
|
|
17
|
+
- 'tests/**'
|
|
18
|
+
- .github/workflows/build_and_tests.yml
|
|
19
|
+
# Cancel previous runs on this reference
|
|
20
|
+
concurrency:
|
|
21
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
22
|
+
cancel-in-progress: true
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
jobs:
|
|
26
|
+
|
|
27
|
+
build_install_test:
|
|
28
|
+
name: Build, install and test the Ledgered Python package
|
|
29
|
+
runs-on: ubuntu-latest
|
|
30
|
+
strategy:
|
|
31
|
+
fail-fast: false
|
|
32
|
+
matrix:
|
|
33
|
+
python_version: ['3.9', '3.10', '3.11', '3.12', '3.13']
|
|
34
|
+
steps:
|
|
35
|
+
- name: Clone
|
|
36
|
+
uses: actions/checkout@v4
|
|
37
|
+
|
|
38
|
+
- name: Setup Python version
|
|
39
|
+
uses: actions/setup-python@v5
|
|
40
|
+
with:
|
|
41
|
+
python-version: ${{ matrix.python_version }}
|
|
42
|
+
|
|
43
|
+
- name: Build & install
|
|
44
|
+
run: |
|
|
45
|
+
pip install -U pip
|
|
46
|
+
pip install -U .[dev]
|
|
47
|
+
|
|
48
|
+
- name: Run unit tests and generate coverage
|
|
49
|
+
run: pytest -v --tb=short tests/unit --cov ledgered --cov-report xml
|
|
50
|
+
|
|
51
|
+
- name: Run functional tests and generate coverage
|
|
52
|
+
run: pytest -v --tb=short tests/functional --cov ledgered --cov-report xml --cov-append --token "${{ secrets.GITHUB_TOKEN }}"
|
|
53
|
+
|
|
54
|
+
- name: Upload coverage to Codecov
|
|
55
|
+
uses: codecov/codecov-action@v4
|
|
56
|
+
with:
|
|
57
|
+
name: codecov-ledgered
|
|
58
|
+
token: ${{ secrets.CODECOV_TOKEN }}
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
package_and_deploy:
|
|
62
|
+
name: Build and deploy the Ledgered Python package
|
|
63
|
+
needs: [build_install_test]
|
|
64
|
+
uses: LedgerHQ/ledger-app-workflows/.github/workflows/reusable_pypi_deployment.yml@v1
|
|
65
|
+
with:
|
|
66
|
+
package_name: ledgered
|
|
67
|
+
publish: ${{ startsWith(github.ref, 'refs/tags/') }}
|
|
68
|
+
secrets:
|
|
69
|
+
pypi_token: ${{ secrets.PYPI_PUBLIC_API_TOKEN }}
|
|
@@ -5,6 +5,23 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.10.1] - 2025-05-14
|
|
9
|
+
|
|
10
|
+
### Fix
|
|
11
|
+
|
|
12
|
+
- Parsing 'nanos+' in manifests now returns 'nanosp', which is breaking when this name is used to
|
|
13
|
+
gather a SDK tag.
|
|
14
|
+
Added a specific "sdk_name" field in the JSON / `Device` to be returned when parsing the manifest,
|
|
15
|
+
to get back the previous, 0.9.1- behavior.
|
|
16
|
+
|
|
17
|
+
## [0.10.0] - 2025-05-09
|
|
18
|
+
|
|
19
|
+
### Added
|
|
20
|
+
|
|
21
|
+
- Added `devices` module, declaring Ledger devices as class / enum, dynamically generated from a
|
|
22
|
+
JSON configuration file. This should enable to add new devices more easily, and device
|
|
23
|
+
characteristics are now reachable from a centralized place.
|
|
24
|
+
|
|
8
25
|
## [0.9.1] - 2025-03-26
|
|
9
26
|
|
|
10
27
|
### Fixed
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
include src/ledgered/devices.json
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ledgered
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.10.1
|
|
4
4
|
Summary: Python tools, utils, libraries, to be used with Ledger cryptodevices
|
|
5
5
|
Author-email: Ledger <hello@ledger.fr>
|
|
6
6
|
License: MIT License
|
|
@@ -40,9 +40,10 @@ Classifier: Typing :: Typed
|
|
|
40
40
|
Requires-Python: >=3.9
|
|
41
41
|
Description-Content-Type: text/markdown
|
|
42
42
|
License-File: LICENSE
|
|
43
|
-
Requires-Dist:
|
|
43
|
+
Requires-Dist: pydantic
|
|
44
44
|
Requires-Dist: pyelftools
|
|
45
45
|
Requires-Dist: pygithub
|
|
46
|
+
Requires-Dist: toml
|
|
46
47
|
Provides-Extra: dev
|
|
47
48
|
Requires-Dist: pytest; extra == "dev"
|
|
48
49
|
Requires-Dist: pytest-cov; extra == "dev"
|
|
@@ -17,5 +17,5 @@ __version__: str
|
|
|
17
17
|
__version_tuple__: VERSION_TUPLE
|
|
18
18
|
version_tuple: VERSION_TUPLE
|
|
19
19
|
|
|
20
|
-
__version__ = version = '0.
|
|
21
|
-
__version_tuple__ = version_tuple = (0,
|
|
20
|
+
__version__ = version = '0.10.1'
|
|
21
|
+
__version_tuple__ = version_tuple = (0, 10, 1)
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import dataclasses
|
|
2
|
+
import json
|
|
3
|
+
from enum import IntEnum, auto
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from pydantic.dataclasses import dataclass
|
|
6
|
+
from typing import Optional
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class DeviceType(IntEnum):
|
|
10
|
+
NANOS = auto()
|
|
11
|
+
NANOSP = auto()
|
|
12
|
+
NANOX = auto()
|
|
13
|
+
STAX = auto()
|
|
14
|
+
FLEX = auto()
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass
|
|
18
|
+
class Resolution:
|
|
19
|
+
x: int
|
|
20
|
+
y: int
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@dataclass
|
|
24
|
+
class Device:
|
|
25
|
+
type: DeviceType
|
|
26
|
+
resolution: Resolution
|
|
27
|
+
touchable: bool = True
|
|
28
|
+
deprecated: bool = False
|
|
29
|
+
names: list[str] = dataclasses.field(default_factory=lambda: [])
|
|
30
|
+
_sdk_name: Optional[str] = None
|
|
31
|
+
|
|
32
|
+
@property
|
|
33
|
+
def name(self) -> str:
|
|
34
|
+
"""
|
|
35
|
+
Returns the name of the current firmware's device
|
|
36
|
+
"""
|
|
37
|
+
return self.type.name.lower()
|
|
38
|
+
|
|
39
|
+
@property
|
|
40
|
+
def sdk_name(self) -> str:
|
|
41
|
+
"""
|
|
42
|
+
Returns the SDK name, meaning the device name used to tag the SDK.
|
|
43
|
+
If the device does not have a SDK name, returns the default name
|
|
44
|
+
"""
|
|
45
|
+
return self._sdk_name or self.name
|
|
46
|
+
|
|
47
|
+
@property
|
|
48
|
+
def is_nano(self):
|
|
49
|
+
"""
|
|
50
|
+
States if the firmware's name starts with 'nano' or not.
|
|
51
|
+
"""
|
|
52
|
+
return self.type in [DeviceType.NANOS, DeviceType.NANOSP, DeviceType.NANOX]
|
|
53
|
+
|
|
54
|
+
@classmethod
|
|
55
|
+
def from_dict(cls, dico: dict) -> "Device":
|
|
56
|
+
type = dico.pop("type")
|
|
57
|
+
dico["type"] = DeviceType[type.upper()]
|
|
58
|
+
return Device(**dico)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class Devices:
|
|
62
|
+
_devices_file = Path(__file__).absolute().parent / "devices.json"
|
|
63
|
+
with _devices_file.open() as filee:
|
|
64
|
+
_devices = json.load(filee)
|
|
65
|
+
|
|
66
|
+
DEVICE_DATA = {item.type: item for item in [Device.from_dict(i) for i in _devices]}
|
|
67
|
+
|
|
68
|
+
def __iter__(self):
|
|
69
|
+
for d in self.DEVICE_DATA.values():
|
|
70
|
+
yield d
|
|
71
|
+
|
|
72
|
+
@classmethod
|
|
73
|
+
def get_by_type(cls, device_type: DeviceType) -> Device:
|
|
74
|
+
return cls.DEVICE_DATA[device_type]
|
|
75
|
+
|
|
76
|
+
@classmethod
|
|
77
|
+
def get_by_name(cls, name: str) -> Device:
|
|
78
|
+
for device in cls.DEVICE_DATA.values():
|
|
79
|
+
if name.lower() == device.name or name.lower() in device.names:
|
|
80
|
+
return device
|
|
81
|
+
raise KeyError(f"Device named '{name}' unknown")
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
[
|
|
2
|
+
{"type": "nanos", "resolution": {"x": 128, "y": 32}, "touchable": false, "deprecated": true},
|
|
3
|
+
{"type": "nanosp", "resolution": {"x": 128, "y": 64}, "touchable": false, "names": ["nanos+", "nanos2", "nanosplus"], "_sdk_name": "nanos+"},
|
|
4
|
+
{"type": "nanox", "resolution": {"x": 128, "y": 64}, "touchable": false},
|
|
5
|
+
{"type": "flex", "resolution": {"x": 480, "y": 600}},
|
|
6
|
+
{"type": "stax", "resolution": {"x": 400, "y": 670}}
|
|
7
|
+
]
|
|
@@ -3,7 +3,7 @@ from pathlib import Path
|
|
|
3
3
|
from typing import Iterable, Union
|
|
4
4
|
|
|
5
5
|
from ledgered.serializers import Jsonable, JsonSet
|
|
6
|
-
from .
|
|
6
|
+
from ledgered.devices import Devices
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
@dataclass
|
|
@@ -18,12 +18,7 @@ class AppConfig(Jsonable):
|
|
|
18
18
|
raise ValueError(f"'{sdk}' unknown. Must be either 'C' or 'Rust'")
|
|
19
19
|
self.sdk = sdk
|
|
20
20
|
self.build_directory = Path(build_directory)
|
|
21
|
-
devices = JsonSet(
|
|
22
|
-
unknown_devices = devices.difference(EXISTING_DEVICES)
|
|
23
|
-
if unknown_devices:
|
|
24
|
-
unknown_devices_str = "', '".join(unknown_devices)
|
|
25
|
-
raise ValueError(f"Unknown devices: '{unknown_devices_str}'")
|
|
26
|
-
self.devices = devices
|
|
21
|
+
self.devices = JsonSet(Devices.get_by_name(device).sdk_name for device in devices)
|
|
27
22
|
|
|
28
23
|
@property
|
|
29
24
|
def is_rust(self) -> bool:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ledgered
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.10.1
|
|
4
4
|
Summary: Python tools, utils, libraries, to be used with Ledger cryptodevices
|
|
5
5
|
Author-email: Ledger <hello@ledger.fr>
|
|
6
6
|
License: MIT License
|
|
@@ -40,9 +40,10 @@ Classifier: Typing :: Typed
|
|
|
40
40
|
Requires-Python: >=3.9
|
|
41
41
|
Description-Content-Type: text/markdown
|
|
42
42
|
License-File: LICENSE
|
|
43
|
-
Requires-Dist:
|
|
43
|
+
Requires-Dist: pydantic
|
|
44
44
|
Requires-Dist: pyelftools
|
|
45
45
|
Requires-Dist: pygithub
|
|
46
|
+
Requires-Dist: toml
|
|
46
47
|
Provides-Extra: dev
|
|
47
48
|
Requires-Dist: pytest; extra == "dev"
|
|
48
49
|
Requires-Dist: pytest-cov; extra == "dev"
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
.pre-commit-config.yaml
|
|
4
4
|
CHANGELOG.md
|
|
5
5
|
LICENSE
|
|
6
|
+
MANIFEST.in
|
|
6
7
|
README.md
|
|
7
8
|
pyproject.toml
|
|
8
9
|
.github/workflows/build_and_tests.yml
|
|
@@ -21,6 +22,8 @@ src/ledgered.egg-info/dependency_links.txt
|
|
|
21
22
|
src/ledgered.egg-info/entry_points.txt
|
|
22
23
|
src/ledgered.egg-info/requires.txt
|
|
23
24
|
src/ledgered.egg-info/top_level.txt
|
|
25
|
+
src/ledgered/devices/__init__.py
|
|
26
|
+
src/ledgered/devices/devices.json
|
|
24
27
|
src/ledgered/manifest/__init__.py
|
|
25
28
|
src/ledgered/manifest/app.py
|
|
26
29
|
src/ledgered/manifest/cli.py
|
|
@@ -47,6 +50,8 @@ tests/unit/test_binary.py
|
|
|
47
50
|
tests/unit/test_github.py
|
|
48
51
|
tests/unit/test_github_AppRepository.py
|
|
49
52
|
tests/unit/test_serializers.py
|
|
53
|
+
tests/unit/devices/__init__.py
|
|
54
|
+
tests/unit/devices/test___init__.py
|
|
50
55
|
tests/unit/manifest/__init__.py
|
|
51
56
|
tests/unit/manifest/test_app.py
|
|
52
57
|
tests/unit/manifest/test_manifest.py
|
|
@@ -20,7 +20,7 @@ class PrintMock(MagicMock):
|
|
|
20
20
|
FULL_EXPECTED_TEXT = """build_directory: .
|
|
21
21
|
sdk: c
|
|
22
22
|
devices:
|
|
23
|
-
0.
|
|
23
|
+
0. nanos+
|
|
24
24
|
use_cases:
|
|
25
25
|
debug: DEBUG=1
|
|
26
26
|
test: DEBUG=1
|
|
@@ -31,7 +31,7 @@ tests:
|
|
|
31
31
|
FULL_EXPECTED_JSON = {
|
|
32
32
|
"build_directory": ".",
|
|
33
33
|
"sdk": "c",
|
|
34
|
-
"devices": ["
|
|
34
|
+
"devices": ["nanos+"],
|
|
35
35
|
"use_cases": {"debug": "DEBUG=1", "test": "DEBUG=1"},
|
|
36
36
|
"tests": {"unit_directory": "tests/unit", "pytest_directory": "tests/functional"},
|
|
37
37
|
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
from ledgered.devices import Device, DeviceType, Devices, Resolution
|
|
2
|
+
from unittest import TestCase
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class TestDevice(TestCase):
|
|
6
|
+
def setUp(self):
|
|
7
|
+
self.res = Resolution(x=10, y=20)
|
|
8
|
+
|
|
9
|
+
def test___init__simple(self):
|
|
10
|
+
type = DeviceType.NANOS
|
|
11
|
+
device = Device(type, self.res)
|
|
12
|
+
self.assertEqual(device.type, type)
|
|
13
|
+
self.assertEqual(device.touchable, True)
|
|
14
|
+
self.assertFalse(device.deprecated)
|
|
15
|
+
self.assertEqual(device.name, type.name.lower())
|
|
16
|
+
self.assertEqual(device.resolution, self.res)
|
|
17
|
+
|
|
18
|
+
def test_is_nano(self):
|
|
19
|
+
device = Device(DeviceType.NANOS, self.res)
|
|
20
|
+
self.assertTrue(device.is_nano)
|
|
21
|
+
device = Device(DeviceType.STAX, self.res)
|
|
22
|
+
self.assertFalse(device.is_nano)
|
|
23
|
+
|
|
24
|
+
def test_from_dict(self):
|
|
25
|
+
type, touchable, deprecated = "flex", False, True
|
|
26
|
+
device = Device.from_dict(
|
|
27
|
+
{
|
|
28
|
+
"type": type,
|
|
29
|
+
"resolution": {"x": self.res.x, "y": self.res.y},
|
|
30
|
+
"touchable": touchable,
|
|
31
|
+
"deprecated": deprecated,
|
|
32
|
+
}
|
|
33
|
+
)
|
|
34
|
+
self.assertEqual(device.type, DeviceType[type.upper()])
|
|
35
|
+
self.assertEqual(device.touchable, touchable)
|
|
36
|
+
self.assertEqual(device.deprecated, deprecated)
|
|
37
|
+
self.assertEqual(device.name, type)
|
|
38
|
+
self.assertEqual(device.resolution, Resolution(x=self.res.x, y=self.res.y))
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class TestDevices(TestCase):
|
|
42
|
+
def test_get_type_ok(self):
|
|
43
|
+
type = DeviceType.STAX
|
|
44
|
+
device = Devices.get_by_type(type)
|
|
45
|
+
self.assertIsInstance(device, Device)
|
|
46
|
+
self.assertEqual(device.type, type)
|
|
47
|
+
|
|
48
|
+
def test_get_type_nok(self):
|
|
49
|
+
with self.assertRaises(KeyError):
|
|
50
|
+
Devices.get_by_type(9)
|
|
51
|
+
|
|
52
|
+
def test_get_by_name_ok(self):
|
|
53
|
+
device = Devices.get_by_name("nanos+")
|
|
54
|
+
self.assertIsInstance(device, Device)
|
|
55
|
+
self.assertEqual(device.type, DeviceType.NANOSP)
|
|
56
|
+
self.assertEqual(device.name, "nanosp")
|
|
57
|
+
self.assertEqual(device.sdk_name, "nanos+")
|
|
58
|
+
|
|
59
|
+
def test_get_by_name_nok(self):
|
|
60
|
+
with self.assertRaises(KeyError):
|
|
61
|
+
Devices.get_by_name("non existent")
|
|
62
|
+
|
|
63
|
+
def test___iter__(self):
|
|
64
|
+
for d in Devices():
|
|
65
|
+
self.assertIsInstance(d, Device)
|
|
File without changes
|
|
@@ -12,7 +12,7 @@ class TestAppConfig(TestCase):
|
|
|
12
12
|
config = AppConfig(sdk=sdk, build_directory=str(bd), devices=devices)
|
|
13
13
|
self.assertEqual(config.sdk, sdk.lower())
|
|
14
14
|
self.assertEqual(config.build_directory, bd)
|
|
15
|
-
self.assertEqual(config.devices, {
|
|
15
|
+
self.assertEqual(config.devices, {"nanos", "nanos+"})
|
|
16
16
|
self.assertTrue(config.is_rust)
|
|
17
17
|
self.assertFalse(config.is_c)
|
|
18
18
|
|
|
@@ -21,8 +21,6 @@ class TestAppConfig(TestCase):
|
|
|
21
21
|
AppConfig(sdk="Java", build_directory=str(), devices=set())
|
|
22
22
|
|
|
23
23
|
def test___init___nok_unknown_device(self):
|
|
24
|
-
devices = {"hic sunt", "dracones"}
|
|
25
|
-
with self.assertRaises(
|
|
24
|
+
devices = {"nanosp", "flex", "hic sunt", "dracones"}
|
|
25
|
+
with self.assertRaises(KeyError):
|
|
26
26
|
AppConfig(sdk="rust", build_directory=str(), devices=devices)
|
|
27
|
-
for device in devices:
|
|
28
|
-
self.assertIn(device, str(error.exception))
|
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
name: Build, test and deploy Ledgered
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
workflow_dispatch:
|
|
5
|
-
push:
|
|
6
|
-
tags:
|
|
7
|
-
- '*'
|
|
8
|
-
branches:
|
|
9
|
-
- master
|
|
10
|
-
- develop
|
|
11
|
-
pull_request:
|
|
12
|
-
branches:
|
|
13
|
-
- master
|
|
14
|
-
- develop
|
|
15
|
-
paths:
|
|
16
|
-
- 'src/**'
|
|
17
|
-
- 'tests/**'
|
|
18
|
-
- .github/workflows/build_and_tests.yml
|
|
19
|
-
|
|
20
|
-
jobs:
|
|
21
|
-
|
|
22
|
-
build_install_test:
|
|
23
|
-
name: Build, install and test the Ledgered Python package
|
|
24
|
-
runs-on: ubuntu-latest
|
|
25
|
-
strategy:
|
|
26
|
-
fail-fast: false
|
|
27
|
-
matrix:
|
|
28
|
-
python_version: ['3.9', '3.10', '3.11', '3.12', '3.13']
|
|
29
|
-
steps:
|
|
30
|
-
- name: Clone
|
|
31
|
-
uses: actions/checkout@v4
|
|
32
|
-
|
|
33
|
-
- name: Setup Python version
|
|
34
|
-
uses: actions/setup-python@v5
|
|
35
|
-
with:
|
|
36
|
-
python-version: ${{ matrix.python_version }}
|
|
37
|
-
|
|
38
|
-
- name: Build & install
|
|
39
|
-
run: |
|
|
40
|
-
pip install -U pip
|
|
41
|
-
pip install -U .[dev]
|
|
42
|
-
|
|
43
|
-
- name: Run tests and generate coverage
|
|
44
|
-
run: pytest -v --tb=short tests/ --cov ledgered --cov-report xml
|
|
45
|
-
|
|
46
|
-
- name: Run unit tests and generate coverage
|
|
47
|
-
run: pytest -v --tb=short tests/unit --cov ledgered --cov-report xml
|
|
48
|
-
|
|
49
|
-
- name: Run functional tests and generate coverage
|
|
50
|
-
run: pytest -v --tb=short tests/functional --cov ledgered --cov-report xml --cov-append --token "${{ secrets.GITHUB_TOKEN }}"
|
|
51
|
-
|
|
52
|
-
- name: Upload coverage to Codecov
|
|
53
|
-
uses: codecov/codecov-action@v4
|
|
54
|
-
with:
|
|
55
|
-
name: codecov-ledgered
|
|
56
|
-
token: ${{ secrets.CODECOV_TOKEN }}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
package_and_deploy:
|
|
60
|
-
name: Build and deploy Ledgered Python package
|
|
61
|
-
runs-on: public-ledgerhq-shared-small
|
|
62
|
-
needs: [build_install_test]
|
|
63
|
-
permissions:
|
|
64
|
-
id-token: write
|
|
65
|
-
attestations: write
|
|
66
|
-
contents: write
|
|
67
|
-
steps:
|
|
68
|
-
|
|
69
|
-
- name: Clone
|
|
70
|
-
uses: actions/checkout@v4
|
|
71
|
-
with:
|
|
72
|
-
fetch-depth: 0
|
|
73
|
-
|
|
74
|
-
- name: Build Ledgered Python package
|
|
75
|
-
run: |
|
|
76
|
-
# Needed to workaround this bug https://github.com/pypa/setuptools/issues/4759
|
|
77
|
-
# To be removed when it's fixed
|
|
78
|
-
pip install -U packaging
|
|
79
|
-
pip install --upgrade pip build twine
|
|
80
|
-
python -m build
|
|
81
|
-
pip install .
|
|
82
|
-
python -m twine check dist/*
|
|
83
|
-
echo "TAG_VERSION=$(python -c 'from ledgered import __version__; print(__version__)')" >> "$GITHUB_ENV"
|
|
84
|
-
|
|
85
|
-
- name: Display current status
|
|
86
|
-
run: |
|
|
87
|
-
echo "Current status is:"
|
|
88
|
-
if [[ ${{ github.ref }} == "refs/tags/"* ]];
|
|
89
|
-
then
|
|
90
|
-
echo "- Triggered from tag, package will be a release";
|
|
91
|
-
else
|
|
92
|
-
echo "- Not triggered from tag, package will be a pre-release";
|
|
93
|
-
fi
|
|
94
|
-
echo "- Tag version: ${{ env.TAG_VERSION }}"
|
|
95
|
-
|
|
96
|
-
- name: Check version against CHANGELOG
|
|
97
|
-
if: startsWith(github.ref, 'refs/tags/')
|
|
98
|
-
run: |
|
|
99
|
-
CHANGELOG_VERSION=$(grep -Po '(?<=## \[)(\d+\.)+[^\]]' CHANGELOG.md | head -n 1)
|
|
100
|
-
if [ "${{ env.TAG_VERSION }}" == "${CHANGELOG_VERSION}" ]; \
|
|
101
|
-
then \
|
|
102
|
-
exit 0; \
|
|
103
|
-
else \
|
|
104
|
-
echo "Tag '${{ env.TAG_VERSION }}' and CHANGELOG '${CHANGELOG_VERSION}' versions mismatch!"; \
|
|
105
|
-
exit 1; \
|
|
106
|
-
fi
|
|
107
|
-
|
|
108
|
-
- name: Publish Python package on pypi.org
|
|
109
|
-
if: success() && github.event_name == 'push'
|
|
110
|
-
run: python -m twine upload dist/*
|
|
111
|
-
env:
|
|
112
|
-
TWINE_USERNAME: __token__
|
|
113
|
-
TWINE_PASSWORD: ${{ secrets.PYPI_PUBLIC_API_TOKEN }}
|
|
114
|
-
TWINE_NON_INTERACTIVE: 1
|
|
115
|
-
|
|
116
|
-
- name: Login to Ledger Artifactory
|
|
117
|
-
if: success() && github.event_name == 'push'
|
|
118
|
-
timeout-minutes: 10
|
|
119
|
-
id: jfrog-login
|
|
120
|
-
uses: LedgerHQ/actions-security/actions/jfrog-login@actions/jfrog-login-1
|
|
121
|
-
|
|
122
|
-
- name: Publish Python package on Ledger Artifactory
|
|
123
|
-
if: success() && github.event_name == 'push'
|
|
124
|
-
run: python -m twine upload dist/*
|
|
125
|
-
env:
|
|
126
|
-
TWINE_REPOSITORY_URL: https://jfrog.ledgerlabs.net/artifactory/api/pypi/embedded-apps-pypi-prod-green
|
|
127
|
-
TWINE_USERNAME: ${{ steps.jfrog-login.outputs.oidc-user }}
|
|
128
|
-
TWINE_PASSWORD: ${{ steps.jfrog-login.outputs.oidc-token }}
|
|
129
|
-
TWINE_NON_INTERACTIVE: 1
|
|
130
|
-
|
|
131
|
-
- name: Generate library build attestations
|
|
132
|
-
if: success() && github.event_name == 'push'
|
|
133
|
-
timeout-minutes: 10
|
|
134
|
-
uses: LedgerHQ/actions-security/actions/attest@actions/attest-1
|
|
135
|
-
with:
|
|
136
|
-
subject-path: dist/*
|
|
137
|
-
|
|
138
|
-
- name: Sign library artifacts
|
|
139
|
-
if: success() && github.event_name == 'push'
|
|
140
|
-
timeout-minutes: 10
|
|
141
|
-
uses: LedgerHQ/actions-security/actions/sign-blob@actions/sign-blob-1
|
|
142
|
-
with:
|
|
143
|
-
path: dist
|
|
144
|
-
|
|
145
|
-
- name: Publish a release on the repo
|
|
146
|
-
if: success() && github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
|
|
147
|
-
uses: "marvinpinto/action-automatic-releases@latest"
|
|
148
|
-
with:
|
|
149
|
-
automatic_release_tag: "v${{ env.TAG_VERSION }}"
|
|
150
|
-
repo_token: "${{ secrets.GITHUB_TOKEN }}"
|
|
151
|
-
prerelease: false
|
|
152
|
-
files: |
|
|
153
|
-
LICENSE
|
|
154
|
-
dist/
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|