ragger 1.41.0__py3-none-any.whl → 1.41.2__py3-none-any.whl

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.
ragger/__version__.py CHANGED
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '1.41.0'
32
- __version_tuple__ = version_tuple = (1, 41, 0)
31
+ __version__ = version = '1.41.2'
32
+ __version_tuple__ = version_tuple = (1, 41, 2)
33
33
 
34
34
  __commit_id__ = commit_id = None
@@ -1,6 +1,7 @@
1
1
  import os
2
2
  import pytest
3
3
  import logging
4
+ import warnings
4
5
  from dataclasses import fields
5
6
  from ledgered.devices import Device, Devices
6
7
  from ledgered.manifest import Manifest
@@ -14,6 +15,7 @@ from ragger.logger import init_loggers, standalone_conf_logger
14
15
  from ragger.navigator import Navigator, NanoNavigator, TouchNavigator, NavigateWithScenario
15
16
  from ragger.utils import find_project_root_dir, find_library_application, find_application
16
17
  from ragger.utils.misc import get_current_app_name_and_version, exit_current_app, open_app_from_dashboard
18
+ from ragger.error import MissingElfError
17
19
 
18
20
  from . import configuration as conf
19
21
 
@@ -47,6 +49,10 @@ def pytest_addoption(parser):
47
49
  const="apdu.log",
48
50
  help="Log the APDU in a file. If no pattern provided, uses 'apdu_xxx.log'.")
49
51
  parser.addoption("--seed", action="store", default=None, help="Set a custom seed")
52
+ parser.addoption("--ignore-missing-binaries",
53
+ action="store_true",
54
+ default=False,
55
+ help="Skip tests instead of failing when application binaries are missing")
50
56
  # Always allow "default" even if application conftest does not define it
51
57
  allowed_setups = conf.OPTIONAL.ALLOWED_SETUPS
52
58
  if "default" not in allowed_setups:
@@ -102,6 +108,11 @@ def cli_user_seed(pytestconfig):
102
108
  return pytestconfig.getoption("seed")
103
109
 
104
110
 
111
+ @pytest.fixture(scope="session")
112
+ def ignore_missing_binaries(pytestconfig):
113
+ return pytestconfig.getoption("ignore_missing_binaries")
114
+
115
+
105
116
  @pytest.fixture(scope="session")
106
117
  def pki_prod(pytestconfig):
107
118
  return pytestconfig.getoption("pki_prod")
@@ -238,7 +249,8 @@ def prepare_speculos_args(root_pytest_dir: Path,
238
249
  pki_prod: bool,
239
250
  cli_user_seed: str,
240
251
  additional_args: List[str],
241
- verbose_speculos: bool = False):
252
+ verbose_speculos: bool = False,
253
+ ignore_missing_binaries: bool = False):
242
254
  speculos_args = additional_args.copy()
243
255
 
244
256
  if display:
@@ -270,16 +282,14 @@ def prepare_speculos_args(root_pytest_dir: Path,
270
282
  f"Expected a single folder in {manifest.app.build_directory}, found {len(app_dir_subdirectories)}"
271
283
  )
272
284
  main_app_path = find_application(app_dir_subdirectories[0], device_name, "c")
273
- # If the app is standalone, the main app should be located in project_root_dir / manifest.app.build_directory
274
- else:
275
- main_app_path = find_application(project_root_dir / manifest.app.build_directory,
276
- device_name, manifest.app.sdk)
277
285
 
278
- # If this repository does not hold the main app, then we need to load this repository's application as a library
279
- if conf.OPTIONAL.MAIN_APP_DIR is not None:
280
286
  # This repo holds the library, not the standalone app: search in root_dir/build
281
287
  lib_path = find_application(project_root_dir, device_name, manifest.app.sdk)
282
288
  speculos_args.append(f"-l{lib_path}")
289
+ # If the app is standalone, the main app should be located in project_root_dir / manifest.app.build_directory
290
+ else:
291
+ main_app_path = find_application(project_root_dir / manifest.app.build_directory,
292
+ device_name, manifest.app.sdk)
283
293
 
284
294
  # Legacy lib method, remove once exchange is ported
285
295
  if len(conf.OPTIONAL.SIDELOADED_APPS) != 0:
@@ -290,8 +300,15 @@ def prepare_speculos_args(root_pytest_dir: Path,
290
300
  libs_dir = Path(project_root_dir / conf.OPTIONAL.SIDELOADED_APPS_DIR)
291
301
  # Add "-l Appname:filepath" to Speculos command line for every required lib app
292
302
  for coin_name, lib_name in conf.OPTIONAL.SIDELOADED_APPS.items():
293
- lib_path = find_library_application(libs_dir, coin_name, device_name)
294
- speculos_args.append(f"-l{lib_name}:{lib_path}")
303
+ try:
304
+ lib_path = find_library_application(libs_dir, coin_name, device_name)
305
+ speculos_args.append(f"-l{lib_name}:{lib_path}")
306
+ except MissingElfError as e:
307
+ if ignore_missing_binaries:
308
+ warnings.warn(f"Could not find sideloaded app library for '{lib_name}': {e}",
309
+ UserWarning)
310
+ else:
311
+ raise
295
312
  else:
296
313
  # Keep this method instead
297
314
  # Find all external libraries that have to be sideloaded
@@ -300,8 +317,17 @@ def prepare_speculos_args(root_pytest_dir: Path,
300
317
  subdirs = sorted(
301
318
  filter(lambda d: (sideloaded_dir / d).is_dir(), os.listdir(sideloaded_dir)))
302
319
  for subdir in subdirs:
303
- lib_path = find_application(sideloaded_dir / subdir, device_name, manifest.app.sdk)
304
- speculos_args.append(f"-l{lib_path}")
320
+ try:
321
+ # Currently only C apps are used as additional binaries by ragger (Ethereum and Exchange)
322
+ # TODO: add support for Rust SDK libraries if needed
323
+ lib_path = find_application(sideloaded_dir / subdir, device_name, "c")
324
+ speculos_args.append(f"-l{lib_path}")
325
+ except MissingElfError as e:
326
+ if ignore_missing_binaries:
327
+ warnings.warn(f"Could not find sideloaded app binary for '{subdir}': {e}",
328
+ UserWarning)
329
+ else:
330
+ raise
305
331
 
306
332
  # Check if custom user seed has been provided through CLI or optional configuration.
307
333
  # CLI user seed has priority over the optional configuration seed.
@@ -324,7 +350,8 @@ def create_backend(root_pytest_dir: Path,
324
350
  log_apdu_file: Optional[Path],
325
351
  cli_user_seed: str,
326
352
  additional_speculos_arguments: List[str],
327
- verbose_speculos: bool = False) -> BackendInterface:
353
+ verbose_speculos: bool = False,
354
+ ignore_missing_binaries: bool = False) -> BackendInterface:
328
355
  if backend_name.lower() == "ledgercomm":
329
356
  return LedgerCommBackend(device=device,
330
357
  interface="hid",
@@ -336,7 +363,8 @@ def create_backend(root_pytest_dir: Path,
336
363
  main_app_path, speculos_args = prepare_speculos_args(root_pytest_dir, device, display,
337
364
  pki_prod, cli_user_seed,
338
365
  additional_speculos_arguments,
339
- verbose_speculos)
366
+ verbose_speculos,
367
+ ignore_missing_binaries)
340
368
  return SpeculosBackend(main_app_path,
341
369
  device=device,
342
370
  log_apdu_file=log_apdu_file,
@@ -351,12 +379,21 @@ def create_backend(root_pytest_dir: Path,
351
379
  @pytest.fixture(scope=conf.OPTIONAL.BACKEND_SCOPE)
352
380
  def backend(skip_tests_for_unsupported_devices, root_pytest_dir: Path, backend_name: str,
353
381
  device: Device, display: bool, pki_prod: bool, log_apdu_file: Optional[Path],
354
- cli_user_seed: str, additional_speculos_arguments: List[str],
355
- verbose_speculos: bool) -> Generator[BackendInterface, None, None]:
382
+ cli_user_seed: str, additional_speculos_arguments: List[str], verbose_speculos: bool,
383
+ ignore_missing_binaries: bool) -> Generator[BackendInterface, None, None]:
356
384
  # to separate the test name and its following logs
357
385
  print("")
358
- with create_backend(root_pytest_dir, backend_name, device, display, pki_prod, log_apdu_file,
359
- cli_user_seed, additional_speculos_arguments, verbose_speculos) as b:
386
+ backend_instance = None
387
+ try:
388
+ backend_instance = create_backend(root_pytest_dir, backend_name, device, display, pki_prod,
389
+ log_apdu_file, cli_user_seed,
390
+ additional_speculos_arguments, verbose_speculos,
391
+ ignore_missing_binaries)
392
+ except MissingElfError as e:
393
+ pytest.fail(f"Missing ELF: {e}")
394
+
395
+ assert backend_instance is not None, "Backend instance should be initialized"
396
+ with backend_instance as b:
360
397
  if backend_name.lower() != "speculos" and conf.OPTIONAL.APP_NAME:
361
398
  # Make sure the app is restarted as this is what is requested by the fixture scope
362
399
  app_name, version = get_current_app_name_and_version(b)
ragger/error.py CHANGED
@@ -173,3 +173,11 @@ class ExceptionRAPDU(Exception):
173
173
 
174
174
  def __str__(self):
175
175
  return f"Error [0x{self.status:x}] {str(self.data)}"
176
+
177
+
178
+ class MissingElfError(Exception):
179
+ """Exception raised when an expected ELF binary is missing."""
180
+
181
+ def __init__(self, path: str):
182
+ super().__init__(f"File '{path}' missing. Did you compile for this target?")
183
+ self.path = path
ragger/utils/misc.py CHANGED
@@ -16,7 +16,7 @@
16
16
  import toml
17
17
  from typing import Optional, Tuple, List
18
18
  from pathlib import Path
19
- from ragger.error import ExceptionRAPDU
19
+ from ragger.error import ExceptionRAPDU, MissingElfError
20
20
  import subprocess
21
21
  import json
22
22
 
@@ -48,7 +48,7 @@ def find_library_application(base_dir: Path, name: str, device: str) -> Path:
48
48
  raise AssertionError(f"{base_dir} is not a directory")
49
49
  lib = Path(base_dir / (name + "_" + device + ".elf")).resolve()
50
50
  if not lib.is_file():
51
- raise AssertionError(f"File '{lib}' missing. Did you compile for this target?")
51
+ raise MissingElfError(str(lib))
52
52
  return lib
53
53
 
54
54
 
@@ -91,7 +91,7 @@ def find_application(base_dir: Path, device: str, sdk: str) -> Path:
91
91
  else:
92
92
  app = app / "build" / device / "bin" / "app.elf"
93
93
  if not app.is_file():
94
- raise AssertionError(f"File '{app}' missing. Did you compile for this target?")
94
+ raise MissingElfError(str(app))
95
95
  return app
96
96
 
97
97
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ragger
3
- Version: 1.41.0
3
+ Version: 1.41.2
4
4
  Summary: Testing framework using Speculos and LedgerComm as backends
5
5
  Author-email: Ledger <hello@ledger.fr>
6
6
  Project-URL: Homepage, https://github.com/LedgerHQ/ragger
@@ -1,6 +1,6 @@
1
1
  ragger/__init__.py,sha256=Vbk78M7VtDVMTu02zYQquYSTxtgbieknkvr3uXONrig,713
2
- ragger/__version__.py,sha256=E1ZnJIkHAjOyZueq2FTrD7-A-X_nF3GK9RHXFfxJOQQ,706
3
- ragger/error.py,sha256=G81LOe38jUDV6EzdFc_foKVsMxk09q6N5--0M63qya0,6279
2
+ ragger/__version__.py,sha256=YovYgyS1Rxt5rHmXoIuT5lFDUCxkYEVR2lrSZcSCwYg,706
3
+ ragger/error.py,sha256=mmeipucrlUz1g1kkNy15rXpCccpzucnRTGIsKbcOzBo,6528
4
4
  ragger/logger.py,sha256=XF3DsHDLGOHAG7cqVj_7BQlHKj9J8zw8A9soFHIydc8,2457
5
5
  ragger/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
6
  ragger/backend/__init__.py,sha256=IQlMre2Pi5QWyYBTROMTbKuonNRUODKrrhj5UxcqQx4,1930
@@ -14,7 +14,7 @@ ragger/bip/__init__.py,sha256=7gY5V8gkJfct1g4OgaLg8bNpgoITGaqU9gTKC4tHbAM,920
14
14
  ragger/bip/path.py,sha256=uX69L3U8vteIHJy_PE5yPloGaiiYYMq_jLbBSENiRqs,1709
15
15
  ragger/bip/seed.py,sha256=yKGM_fkFCh6hNAl7vOMrEv5kEoQoDmVPhBCIMtO8dNk,1758
16
16
  ragger/conftest/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
- ragger/conftest/base_conftest.py,sha256=I2J0rvBY4W9G9OI3mE-qVeAM5vV3b9m_oSWqrceL-iM,19100
17
+ ragger/conftest/base_conftest.py,sha256=CZxd88vtU1axohRpEK_Uf5IbDa8S0YBX5mOxGjoc_20,20763
18
18
  ragger/conftest/configuration.py,sha256=jE_zbvDWSc7jQQ4VEJBo8m_3kME09i2YXK6PLigPAes,3297
19
19
  ragger/firmware/__init__.py,sha256=3g_-n2b0qEgVlP42lOQiZzBPux6PCUtZnydkQeEn_Vk,687
20
20
  ragger/firmware/structs.py,sha256=pkUzEkq-kiUntWK2mt1Vkalgoe-3tbvBcLfe12L-CNo,1804
@@ -47,11 +47,11 @@ ragger/navigator/navigation_scenario.py,sha256=EY31uNp3hkMm8kVmvQEZvnjcw9ymDxHDZ
47
47
  ragger/navigator/navigator.py,sha256=ZT2smrw0Xz5XXhz2cZ3DJjbG4NwwQnCrQwvarbjZPTc,29146
48
48
  ragger/navigator/touch_navigator.py,sha256=k3PNaQ9sjfz4qFm-QuNPbnIJLXiICb_LeLbqnfjgdGM,5018
49
49
  ragger/utils/__init__.py,sha256=PUabSv1qx0XyKWovIxvGBI71sd3O3bKp3gCsUxlWm1E,997
50
- ragger/utils/misc.py,sha256=_ft_CrwEcZ-VVZCBG-_QjYQuTZn-Fht36k3C6BXhHOs,6930
50
+ ragger/utils/misc.py,sha256=Gx1LbtaOh3ns8C_4sRJAFyym2RcbTEmjNtjRfHT_BYw,6851
51
51
  ragger/utils/packing.py,sha256=2xaRR-FhwVfknP74ZGo-O4JTE6R0HpNqhxKJ9aMrns4,766
52
52
  ragger/utils/structs.py,sha256=JMfuX5u-4gSZfqH0SER05B15-mj0YyHjnxLAgxAYtAM,1413
53
- ragger-1.41.0.dist-info/licenses/LICENSE,sha256=tAkwu8-AdEyGxGoSvJ2gVmQdcicWw3j1ZZueVV74M-E,11357
54
- ragger-1.41.0.dist-info/METADATA,sha256=aW_QcwGG5g4ig6mypqRa7AzL-4-kW1yXoQYEWqRRmQ4,10660
55
- ragger-1.41.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
56
- ragger-1.41.0.dist-info/top_level.txt,sha256=kqJEoAZ6qn0T3iuVa-710gBK7Ik1euCwNwBbyFraRQg,7
57
- ragger-1.41.0.dist-info/RECORD,,
53
+ ragger-1.41.2.dist-info/licenses/LICENSE,sha256=tAkwu8-AdEyGxGoSvJ2gVmQdcicWw3j1ZZueVV74M-E,11357
54
+ ragger-1.41.2.dist-info/METADATA,sha256=F3RzajCILlcstsq8xs3SCFIKIxB8BjHDgtrchfkKn8U,10660
55
+ ragger-1.41.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
56
+ ragger-1.41.2.dist-info/top_level.txt,sha256=kqJEoAZ6qn0T3iuVa-710gBK7Ik1euCwNwBbyFraRQg,7
57
+ ragger-1.41.2.dist-info/RECORD,,