ledgered 0.7.2.dev6__tar.gz → 0.7.2.dev8__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.7.2.dev8/.github/workflows/fast-checks.yml +41 -0
- {ledgered-0.7.2.dev6 → ledgered-0.7.2.dev8}/.gitignore +0 -1
- ledgered-0.7.2.dev8/.pre-commit-config.yaml +28 -0
- {ledgered-0.7.2.dev6/src/ledgered.egg-info → ledgered-0.7.2.dev8}/PKG-INFO +1 -1
- {ledgered-0.7.2.dev6 → ledgered-0.7.2.dev8}/pyproject.toml +2 -9
- {ledgered-0.7.2.dev6 → ledgered-0.7.2.dev8}/src/ledgered/__version__.py +2 -2
- {ledgered-0.7.2.dev6 → ledgered-0.7.2.dev8}/src/ledgered/binary.py +10 -11
- {ledgered-0.7.2.dev6 → ledgered-0.7.2.dev8}/src/ledgered/github.py +15 -14
- {ledgered-0.7.2.dev6 → ledgered-0.7.2.dev8}/src/ledgered/manifest/cli.py +89 -72
- {ledgered-0.7.2.dev6 → ledgered-0.7.2.dev8}/src/ledgered/manifest/manifest.py +11 -7
- {ledgered-0.7.2.dev6 → ledgered-0.7.2.dev8}/src/ledgered/manifest/tests.py +9 -6
- {ledgered-0.7.2.dev6 → ledgered-0.7.2.dev8}/src/ledgered/manifest/use_cases.py +4 -2
- {ledgered-0.7.2.dev6 → ledgered-0.7.2.dev8}/src/ledgered/manifest/utils.py +1 -1
- {ledgered-0.7.2.dev6 → ledgered-0.7.2.dev8}/src/ledgered/serializers.py +1 -5
- {ledgered-0.7.2.dev6 → ledgered-0.7.2.dev8/src/ledgered.egg-info}/PKG-INFO +1 -1
- {ledgered-0.7.2.dev6 → ledgered-0.7.2.dev8}/src/ledgered.egg-info/SOURCES.txt +1 -0
- {ledgered-0.7.2.dev6 → ledgered-0.7.2.dev8}/tests/_data/minimal.toml +1 -1
- {ledgered-0.7.2.dev6 → ledgered-0.7.2.dev8}/tests/functional/conftest.py +7 -3
- {ledgered-0.7.2.dev6 → ledgered-0.7.2.dev8}/tests/functional/manifest/test_cli.py +22 -26
- {ledgered-0.7.2.dev6 → ledgered-0.7.2.dev8}/tests/functional/test_github.py +4 -3
- {ledgered-0.7.2.dev6 → ledgered-0.7.2.dev8}/tests/unit/manifest/test_app.py +0 -1
- {ledgered-0.7.2.dev6 → ledgered-0.7.2.dev8}/tests/unit/manifest/test_manifest.py +2 -2
- {ledgered-0.7.2.dev6 → ledgered-0.7.2.dev8}/tests/unit/manifest/test_tests.py +44 -17
- {ledgered-0.7.2.dev6 → ledgered-0.7.2.dev8}/tests/unit/manifest/test_use_cases.py +1 -4
- {ledgered-0.7.2.dev6 → ledgered-0.7.2.dev8}/tests/unit/test_binary.py +8 -9
- {ledgered-0.7.2.dev6 → ledgered-0.7.2.dev8}/tests/unit/test_github.py +1 -4
- {ledgered-0.7.2.dev6 → ledgered-0.7.2.dev8}/tests/unit/test_serializers.py +15 -15
- ledgered-0.7.2.dev6/.github/workflows/fast-checks.yml +0 -64
- {ledgered-0.7.2.dev6 → ledgered-0.7.2.dev8}/.github/workflows/build_and_tests.yml +0 -0
- {ledgered-0.7.2.dev6 → ledgered-0.7.2.dev8}/.github/workflows/codeql-analysis.yml +0 -0
- {ledgered-0.7.2.dev6 → ledgered-0.7.2.dev8}/CHANGELOG.md +0 -0
- {ledgered-0.7.2.dev6 → ledgered-0.7.2.dev8}/LICENSE +0 -0
- {ledgered-0.7.2.dev6 → ledgered-0.7.2.dev8}/README.md +0 -0
- {ledgered-0.7.2.dev6 → ledgered-0.7.2.dev8}/doc/binary.md +0 -0
- {ledgered-0.7.2.dev6 → ledgered-0.7.2.dev8}/doc/manifest.md +0 -0
- {ledgered-0.7.2.dev6 → ledgered-0.7.2.dev8}/setup.cfg +0 -0
- {ledgered-0.7.2.dev6 → ledgered-0.7.2.dev8}/src/ledgered/__init__.py +0 -0
- {ledgered-0.7.2.dev6 → ledgered-0.7.2.dev8}/src/ledgered/manifest/__init__.py +0 -0
- {ledgered-0.7.2.dev6 → ledgered-0.7.2.dev8}/src/ledgered/manifest/app.py +0 -0
- {ledgered-0.7.2.dev6 → ledgered-0.7.2.dev8}/src/ledgered/manifest/constants.py +0 -0
- {ledgered-0.7.2.dev6 → ledgered-0.7.2.dev8}/src/ledgered/manifest/errors.py +0 -0
- {ledgered-0.7.2.dev6 → ledgered-0.7.2.dev8}/src/ledgered/utils/__init__.py +0 -0
- {ledgered-0.7.2.dev6 → ledgered-0.7.2.dev8}/src/ledgered.egg-info/dependency_links.txt +0 -0
- {ledgered-0.7.2.dev6 → ledgered-0.7.2.dev8}/src/ledgered.egg-info/entry_points.txt +0 -0
- {ledgered-0.7.2.dev6 → ledgered-0.7.2.dev8}/src/ledgered.egg-info/requires.txt +0 -0
- {ledgered-0.7.2.dev6 → ledgered-0.7.2.dev8}/src/ledgered.egg-info/top_level.txt +0 -0
- {ledgered-0.7.2.dev6 → ledgered-0.7.2.dev8}/tests/_data/Cargo.toml +0 -0
- {ledgered-0.7.2.dev6 → ledgered-0.7.2.dev8}/tests/_data/Makefile +0 -0
- {ledgered-0.7.2.dev6 → ledgered-0.7.2.dev8}/tests/_data/full_correct.toml +0 -0
- {ledgered-0.7.2.dev6 → ledgered-0.7.2.dev8}/tests/_data/ledger_app.toml +0 -0
- {ledgered-0.7.2.dev6 → ledgered-0.7.2.dev8}/tests/_data/one_leaf.toml +0 -0
- {ledgered-0.7.2.dev6 → ledgered-0.7.2.dev8}/tests/functional/__init__.py +0 -0
- {ledgered-0.7.2.dev6 → ledgered-0.7.2.dev8}/tests/functional/manifest/__init__.py +0 -0
- {ledgered-0.7.2.dev6 → ledgered-0.7.2.dev8}/tests/unit/__init__.py +0 -0
- {ledgered-0.7.2.dev6 → ledgered-0.7.2.dev8}/tests/unit/manifest/__init__.py +0 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
name: Fast checks
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
push:
|
|
6
|
+
branches:
|
|
7
|
+
- develop
|
|
8
|
+
- master
|
|
9
|
+
pull_request:
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
ruff:
|
|
13
|
+
name: Checks & format
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
- name: Ruff - lint check
|
|
18
|
+
uses: astral-sh/ruff-action@v3
|
|
19
|
+
- name: Ruff - format check
|
|
20
|
+
run: ruff format --check
|
|
21
|
+
|
|
22
|
+
mypy:
|
|
23
|
+
name: Type checking
|
|
24
|
+
runs-on: ubuntu-latest
|
|
25
|
+
steps:
|
|
26
|
+
- uses: actions/checkout@v4
|
|
27
|
+
- run: pip install mypy types-toml
|
|
28
|
+
- name: Mypy type checking
|
|
29
|
+
run: mypy src
|
|
30
|
+
|
|
31
|
+
misspell:
|
|
32
|
+
name: Check misspellings
|
|
33
|
+
runs-on: ubuntu-latest
|
|
34
|
+
steps:
|
|
35
|
+
- uses: actions/checkout@v4
|
|
36
|
+
- name: Check misspellings
|
|
37
|
+
uses: codespell-project/actions-codespell@v1
|
|
38
|
+
with:
|
|
39
|
+
builtin: clear,rare
|
|
40
|
+
check_filenames: true
|
|
41
|
+
ignore_words_list: assertIn,crate,
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# To install hooks, run:
|
|
2
|
+
# pre-commit install --hook-type pre-commit
|
|
3
|
+
# pre-commit install --hook-type commit-msg
|
|
4
|
+
|
|
5
|
+
repos:
|
|
6
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
7
|
+
rev: v5.0.0
|
|
8
|
+
hooks:
|
|
9
|
+
- id: trailing-whitespace
|
|
10
|
+
- id: end-of-file-fixer
|
|
11
|
+
- id: check-yaml
|
|
12
|
+
- id: check-toml
|
|
13
|
+
- id: check-added-large-files
|
|
14
|
+
|
|
15
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
16
|
+
rev: v0.9.3
|
|
17
|
+
hooks:
|
|
18
|
+
- id: ruff-format
|
|
19
|
+
args: ["--check"]
|
|
20
|
+
- id: ruff
|
|
21
|
+
|
|
22
|
+
- repo: https://github.com/pre-commit/mirrors-mypy
|
|
23
|
+
rev: v1.14.1
|
|
24
|
+
hooks:
|
|
25
|
+
- id: mypy
|
|
26
|
+
additional_dependencies:
|
|
27
|
+
- types-toml
|
|
28
|
+
- types-requests
|
|
@@ -55,10 +55,6 @@ local_scheme = "no-local-version"
|
|
|
55
55
|
[tool.mypy]
|
|
56
56
|
ignore_missing_imports = true
|
|
57
57
|
|
|
58
|
-
[tool.yapf]
|
|
59
|
-
based_on_style = "pep8"
|
|
60
|
-
column_limit = 100
|
|
61
|
-
|
|
62
58
|
[tool.coverage.report]
|
|
63
59
|
show_missing = true
|
|
64
60
|
exclude_lines = [
|
|
@@ -66,8 +62,5 @@ exclude_lines = [
|
|
|
66
62
|
"pragma: no cover"
|
|
67
63
|
]
|
|
68
64
|
|
|
69
|
-
[tool.
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
[tool.flake8]
|
|
73
|
-
max-line-length = 100
|
|
65
|
+
[tool.ruff]
|
|
66
|
+
line-length = 100
|
|
@@ -12,5 +12,5 @@ __version__: str
|
|
|
12
12
|
__version_tuple__: VERSION_TUPLE
|
|
13
13
|
version_tuple: VERSION_TUPLE
|
|
14
14
|
|
|
15
|
-
__version__ = version = '0.7.2.
|
|
16
|
-
__version_tuple__ = version_tuple = (0, 7, 2, '
|
|
15
|
+
__version__ = version = '0.7.2.dev8'
|
|
16
|
+
__version_tuple__ = version_tuple = (0, 7, 2, 'dev8')
|
|
@@ -32,7 +32,6 @@ class Sections(Jsonable):
|
|
|
32
32
|
|
|
33
33
|
|
|
34
34
|
class LedgerBinaryApp:
|
|
35
|
-
|
|
36
35
|
def __init__(self, binary_path: Union[str, Path]):
|
|
37
36
|
if isinstance(binary_path, str):
|
|
38
37
|
binary_path = Path(binary_path)
|
|
@@ -41,7 +40,8 @@ class LedgerBinaryApp:
|
|
|
41
40
|
with self._path.open("rb") as filee:
|
|
42
41
|
sections = {
|
|
43
42
|
s.name.replace(LEDGER_PREFIX, ""): s.data().decode().strip()
|
|
44
|
-
for s in ELFFile(filee).iter_sections()
|
|
43
|
+
for s in ELFFile(filee).iter_sections()
|
|
44
|
+
if LEDGER_PREFIX in s.name
|
|
45
45
|
}
|
|
46
46
|
self._sections = Sections(**sections)
|
|
47
47
|
|
|
@@ -51,16 +51,15 @@ class LedgerBinaryApp:
|
|
|
51
51
|
|
|
52
52
|
|
|
53
53
|
def set_parser() -> ArgumentParser:
|
|
54
|
-
parser = ArgumentParser(
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
54
|
+
parser = ArgumentParser(
|
|
55
|
+
prog="ledger-binary",
|
|
56
|
+
description="Utilitary to parse Ledger embedded application ELF file and output metadatas",
|
|
57
|
+
)
|
|
58
|
+
parser.add_argument("-v", "--verbose", action="count", default=0)
|
|
58
59
|
parser.add_argument("binary", type=Path, help="The ledger embedded application ELF file")
|
|
59
|
-
parser.add_argument(
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
action="store_true",
|
|
63
|
-
help="outputs as JSON rather than text")
|
|
60
|
+
parser.add_argument(
|
|
61
|
+
"-j", "--json", required=False, action="store_true", help="outputs as JSON rather than text"
|
|
62
|
+
)
|
|
64
63
|
return parser
|
|
65
64
|
|
|
66
65
|
|
|
@@ -17,14 +17,14 @@ class Condition(IntEnum):
|
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
class NoManifestException(FileNotFoundError):
|
|
20
|
-
|
|
21
20
|
def __init__(self, repository: "AppRepository"):
|
|
22
|
-
super().__init__(
|
|
23
|
-
|
|
21
|
+
super().__init__(
|
|
22
|
+
f"`ledger_app.toml` manifest not found in repository '{repository.url}', "
|
|
23
|
+
f"branch '{repository.current_branch}'."
|
|
24
|
+
)
|
|
24
25
|
|
|
25
26
|
|
|
26
27
|
class AppRepository(PyRepository.Repository):
|
|
27
|
-
|
|
28
28
|
def __init__(self, *args, **kwargs) -> None:
|
|
29
29
|
super().__init__(*args, **kwargs)
|
|
30
30
|
self._manifest: Optional[Manifest] = None
|
|
@@ -60,8 +60,9 @@ class AppRepository(PyRepository.Repository):
|
|
|
60
60
|
def makefile(self) -> str:
|
|
61
61
|
if self._makefile is None:
|
|
62
62
|
# paths on Windows contain "\" which are not compatible with GitHub remote paths
|
|
63
|
-
makefile = self.get_contents(
|
|
64
|
-
|
|
63
|
+
makefile = self.get_contents(
|
|
64
|
+
str(self.makefile_path).replace("\\", "/"), ref=self.current_branch
|
|
65
|
+
)
|
|
65
66
|
# `get_contents` can return a list, but here there can only be one Makefile / Cargo.toml
|
|
66
67
|
assert isinstance(makefile, PyContentFile.ContentFile)
|
|
67
68
|
self._makefile = makefile.decoded_content.decode()
|
|
@@ -72,9 +73,9 @@ class AppRepository(PyRepository.Repository):
|
|
|
72
73
|
variants = []
|
|
73
74
|
for line in self.makefile.splitlines():
|
|
74
75
|
if "VARIANTS" in line:
|
|
75
|
-
variants.extend(line.split(
|
|
76
|
+
variants.extend(line.split(" ")[3:])
|
|
76
77
|
elif "VARIANT_VALUES = " in line:
|
|
77
|
-
variants.extend(line.split(" = ")[1].split(
|
|
78
|
+
variants.extend(line.split(" = ")[1].split(" "))
|
|
78
79
|
return variants
|
|
79
80
|
|
|
80
81
|
@property
|
|
@@ -90,14 +91,15 @@ class AppRepository(PyRepository.Repository):
|
|
|
90
91
|
|
|
91
92
|
|
|
92
93
|
class GitHubApps(list):
|
|
93
|
-
|
|
94
94
|
def __init__(self, apps: List[AppRepository]):
|
|
95
95
|
super().__init__([r for r in apps if r.name.startswith("app-")])
|
|
96
96
|
|
|
97
|
-
def filter(
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
97
|
+
def filter(
|
|
98
|
+
self,
|
|
99
|
+
name: Optional[str] = None,
|
|
100
|
+
archived: Condition = Condition.WITH,
|
|
101
|
+
private: Condition = Condition.WITH,
|
|
102
|
+
) -> "GitHubApps":
|
|
101
103
|
new_list = [i for i in self]
|
|
102
104
|
# archived filtering
|
|
103
105
|
if archived == Condition.WITHOUT:
|
|
@@ -120,7 +122,6 @@ class GitHubApps(list):
|
|
|
120
122
|
|
|
121
123
|
|
|
122
124
|
class GitHubLedgerHQ(PyGithub):
|
|
123
|
-
|
|
124
125
|
def __init__(self, *args, **kwargs) -> None:
|
|
125
126
|
super().__init__(*args, **kwargs)
|
|
126
127
|
self._org = self.get_organization(LEDGER_ORG_NAME)
|
|
@@ -37,81 +37,99 @@ def text_output(content: Dict, indent: int = 0) -> None:
|
|
|
37
37
|
|
|
38
38
|
|
|
39
39
|
def set_parser() -> ArgumentParser:
|
|
40
|
-
parser = ArgumentParser(
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
parser = ArgumentParser(
|
|
41
|
+
prog="ledger-manifest",
|
|
42
|
+
description="Utilitary to parse and check an application 'ledger_app.toml' manifest",
|
|
43
|
+
)
|
|
43
44
|
|
|
44
45
|
# generic options
|
|
45
46
|
parser.add_argument("-v", "--verbose", action="count", default=0)
|
|
46
|
-
parser.add_argument(
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
47
|
+
parser.add_argument(
|
|
48
|
+
"-c",
|
|
49
|
+
"--check",
|
|
50
|
+
required=False,
|
|
51
|
+
type=Path,
|
|
52
|
+
default=None,
|
|
53
|
+
help="Check the manifest content against the provided directory.",
|
|
54
|
+
)
|
|
52
55
|
|
|
53
56
|
# display options
|
|
54
|
-
parser.add_argument(
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
57
|
+
parser.add_argument(
|
|
58
|
+
"manifest",
|
|
59
|
+
type=Path,
|
|
60
|
+
help=f"The manifest file (generally '{MANIFEST_FILE_NAME}' at the root of "
|
|
61
|
+
"the application's repository), or the name of the app if the `--url` "
|
|
62
|
+
"option is activated",
|
|
63
|
+
)
|
|
64
|
+
parser.add_argument(
|
|
65
|
+
"-u",
|
|
66
|
+
"--url",
|
|
67
|
+
action="store_true",
|
|
68
|
+
default=False,
|
|
69
|
+
help="Tells if the `manifest` is a repository HTTP URL rather than a file",
|
|
70
|
+
)
|
|
71
|
+
parser.add_argument(
|
|
72
|
+
"-os",
|
|
73
|
+
"--output-sdk",
|
|
74
|
+
required=False,
|
|
75
|
+
action="store_true",
|
|
76
|
+
default=False,
|
|
77
|
+
help="outputs the SDK type",
|
|
78
|
+
)
|
|
79
|
+
parser.add_argument(
|
|
80
|
+
"-ob",
|
|
81
|
+
"--output-build-directory",
|
|
82
|
+
required=False,
|
|
83
|
+
action="store_true",
|
|
84
|
+
default=False,
|
|
85
|
+
help="outputs the build directory (where the Makefile in C app, or the "
|
|
86
|
+
"Cargo.toml in Rust app is expected to be)",
|
|
87
|
+
)
|
|
88
|
+
parser.add_argument(
|
|
89
|
+
"-od",
|
|
90
|
+
"--output-devices",
|
|
91
|
+
required=False,
|
|
92
|
+
action="store_true",
|
|
93
|
+
default=False,
|
|
94
|
+
help="outputs the list of devices supported by the application",
|
|
95
|
+
)
|
|
96
|
+
parser.add_argument(
|
|
97
|
+
"-otu",
|
|
98
|
+
"--output-tests-unit-directory",
|
|
99
|
+
required=False,
|
|
100
|
+
action="store_true",
|
|
101
|
+
default=False,
|
|
102
|
+
help="outputs the directory of the unit tests. Fails if none",
|
|
103
|
+
)
|
|
104
|
+
parser.add_argument(
|
|
105
|
+
"-otp",
|
|
106
|
+
"--output-tests-pytest-directory",
|
|
107
|
+
required=False,
|
|
108
|
+
action="store_true",
|
|
109
|
+
default=False,
|
|
110
|
+
help="outputs the directory of the pytest (functional) tests. Fails if none",
|
|
111
|
+
)
|
|
112
|
+
parser.add_argument(
|
|
113
|
+
"-otd",
|
|
114
|
+
"--output-tests-dependencies",
|
|
115
|
+
required=False,
|
|
116
|
+
action="store",
|
|
117
|
+
default=None,
|
|
118
|
+
nargs="*",
|
|
119
|
+
help="outputs the given use cases. Fails if none",
|
|
120
|
+
)
|
|
121
|
+
parser.add_argument(
|
|
122
|
+
"-ouc",
|
|
123
|
+
"--output-use-cases",
|
|
124
|
+
required=False,
|
|
125
|
+
default=None,
|
|
126
|
+
action="store",
|
|
127
|
+
nargs="*",
|
|
128
|
+
help="outputs the given use cases. Fails if none",
|
|
129
|
+
)
|
|
130
|
+
parser.add_argument(
|
|
131
|
+
"-j", "--json", required=False, action="store_true", help="outputs as JSON rather than text"
|
|
132
|
+
)
|
|
115
133
|
return parser
|
|
116
134
|
|
|
117
135
|
|
|
@@ -170,8 +188,7 @@ def main() -> None: # pragma: no cover
|
|
|
170
188
|
non_empty = len(dependencies) > 0
|
|
171
189
|
if len(args.output_tests_dependencies) != 0:
|
|
172
190
|
dependencies = {
|
|
173
|
-
k: v
|
|
174
|
-
for (k, v) in dependencies.items() if k in args.output_tests_dependencies
|
|
191
|
+
k: v for (k, v) in dependencies.items() if k in args.output_tests_dependencies
|
|
175
192
|
}
|
|
176
193
|
if not len(dependencies) and non_empty:
|
|
177
194
|
logger.error("No use case match these ones: '%s'", args.output_tests_dependencies)
|
|
@@ -17,10 +17,9 @@ class Manifest(Jsonable):
|
|
|
17
17
|
tests: Optional[TestsConfig]
|
|
18
18
|
use_cases: Optional[UseCasesConfig]
|
|
19
19
|
|
|
20
|
-
def __init__(
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
use_cases: Optional[Dict] = None) -> None:
|
|
20
|
+
def __init__(
|
|
21
|
+
self, app: Dict, tests: Optional[Dict] = None, use_cases: Optional[Dict] = None
|
|
22
|
+
) -> None:
|
|
24
23
|
self.app = AppConfig(**app)
|
|
25
24
|
self.tests = None if tests is None else TestsConfig(**tests)
|
|
26
25
|
self.use_cases = None if use_cases is None else UseCasesConfig(**use_cases)
|
|
@@ -43,8 +42,13 @@ class Manifest(Jsonable):
|
|
|
43
42
|
def check(self, base_directory: Union[str, Path]) -> None:
|
|
44
43
|
base_directory = Path(base_directory)
|
|
45
44
|
assert base_directory.is_dir(), f"Given '{base_directory}' must be a directory"
|
|
46
|
-
build_file =
|
|
47
|
-
|
|
45
|
+
build_file = (
|
|
46
|
+
base_directory
|
|
47
|
+
/ self.app.build_directory
|
|
48
|
+
/ ("Cargo.toml" if self.app.is_rust else "Makefile")
|
|
49
|
+
)
|
|
48
50
|
logging.info("Checking existence of file %s", build_file)
|
|
49
|
-
assert build_file.is_file(),
|
|
51
|
+
assert build_file.is_file(), (
|
|
52
|
+
f"No file '{build_file}' (from the given base directory "
|
|
50
53
|
f"'{base_directory}' + the manifest path '{self.app.build_directory}') was found"
|
|
54
|
+
)
|
|
@@ -33,8 +33,9 @@ class TestsDependencyConfig(Jsonable):
|
|
|
33
33
|
|
|
34
34
|
@property
|
|
35
35
|
def dir(self) -> Path:
|
|
36
|
-
return (
|
|
37
|
-
|
|
36
|
+
return (
|
|
37
|
+
self._base_dir / APPLICATION_DIRECTORY_NAME / f"{self._name}-{self.ref}-{self.use_case}"
|
|
38
|
+
)
|
|
38
39
|
|
|
39
40
|
def __eq__(self, other: object) -> bool:
|
|
40
41
|
if not isinstance(other, TestsDependencyConfig):
|
|
@@ -81,10 +82,12 @@ class TestsConfig(Jsonable):
|
|
|
81
82
|
pytest_directory: Optional[Path]
|
|
82
83
|
dependencies: Optional[JsonDict]
|
|
83
84
|
|
|
84
|
-
def __init__(
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
85
|
+
def __init__(
|
|
86
|
+
self,
|
|
87
|
+
pytest_directory: Optional[Union[str, Path]] = None,
|
|
88
|
+
unit_directory: Optional[Union[str, Path]] = None,
|
|
89
|
+
dependencies: Optional[Dict[str, List]] = None,
|
|
90
|
+
) -> None:
|
|
88
91
|
logger = getLogger()
|
|
89
92
|
logger.debug("Parsing test dependencies")
|
|
90
93
|
self.unit_directory = None if unit_directory is None else Path(unit_directory)
|
|
@@ -12,8 +12,10 @@ class UseCasesConfig(Jsonable):
|
|
|
12
12
|
def __init__(self, **cases: Optional[Dict]) -> None:
|
|
13
13
|
for key, value in cases.items():
|
|
14
14
|
if not isinstance(value, str):
|
|
15
|
-
raise ValueError(
|
|
16
|
-
|
|
15
|
+
raise ValueError(
|
|
16
|
+
f"Use case '{key} = {value}' should have '{value}' as a string, "
|
|
17
|
+
f"not a {type(value)}"
|
|
18
|
+
)
|
|
17
19
|
if key == DEFAULT_USE_CASE:
|
|
18
20
|
raise ValueError(f"'{key}' use case is reserved and cannot be overridden")
|
|
19
21
|
self.cases = JsonDict(cases)
|
|
@@ -6,12 +6,11 @@ def to_str_int(value: Any) -> Union[int, str]:
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class Jsonable:
|
|
9
|
-
|
|
10
9
|
@property
|
|
11
10
|
def json(self) -> Union[Dict, List]:
|
|
12
11
|
output: Dict[Union[str, int], Any] = dict()
|
|
13
12
|
for key, value in self.__dict__.items():
|
|
14
|
-
if key.startswith(
|
|
13
|
+
if key.startswith("_"):
|
|
15
14
|
# 'hidden' properties are not to be included into the output
|
|
16
15
|
continue
|
|
17
16
|
if isinstance(value, Jsonable):
|
|
@@ -22,7 +21,6 @@ class Jsonable:
|
|
|
22
21
|
|
|
23
22
|
|
|
24
23
|
class JsonList(list, Jsonable):
|
|
25
|
-
|
|
26
24
|
@property
|
|
27
25
|
def json(self) -> List:
|
|
28
26
|
output: List[Any] = list()
|
|
@@ -35,7 +33,6 @@ class JsonList(list, Jsonable):
|
|
|
35
33
|
|
|
36
34
|
|
|
37
35
|
class JsonSet(set, Jsonable):
|
|
38
|
-
|
|
39
36
|
@property
|
|
40
37
|
def json(self) -> List:
|
|
41
38
|
output: List[Any] = list()
|
|
@@ -48,7 +45,6 @@ class JsonSet(set, Jsonable):
|
|
|
48
45
|
|
|
49
46
|
|
|
50
47
|
class JsonDict(dict, Jsonable):
|
|
51
|
-
|
|
52
48
|
@property
|
|
53
49
|
def json(self) -> Dict:
|
|
54
50
|
output: Dict[Union[str, int], Any] = dict()
|
|
@@ -6,9 +6,13 @@ from ledgered.github import GitHubLedgerHQ
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
def pytest_addoption(parser):
|
|
9
|
-
parser.addoption(
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
parser.addoption(
|
|
10
|
+
"--token",
|
|
11
|
+
required=False,
|
|
12
|
+
default=None,
|
|
13
|
+
help="Provide a GitHub token so that functional test won't trigger API "
|
|
14
|
+
"restrictions too fast",
|
|
15
|
+
)
|
|
12
16
|
|
|
13
17
|
|
|
14
18
|
@pytest.fixture(scope="session")
|
|
@@ -4,13 +4,11 @@ from unittest import TestCase
|
|
|
4
4
|
from unittest.mock import MagicMock, patch
|
|
5
5
|
|
|
6
6
|
from ledgered.manifest.cli import main, set_parser
|
|
7
|
-
from ledgered.manifest.tests import APPLICATION_DIRECTORY_KEY, APPLICATION_DIRECTORY_NAME
|
|
8
7
|
|
|
9
8
|
from .. import TEST_MANIFEST_DIRECTORY
|
|
10
9
|
|
|
11
10
|
|
|
12
11
|
class PrintMock(MagicMock):
|
|
13
|
-
|
|
14
12
|
def get(self):
|
|
15
13
|
result = list()
|
|
16
14
|
for call_args in self.call_args_list:
|
|
@@ -18,6 +16,7 @@ class PrintMock(MagicMock):
|
|
|
18
16
|
self.reset_mock()
|
|
19
17
|
return "\n".join(result)
|
|
20
18
|
|
|
19
|
+
|
|
21
20
|
FULL_EXPECTED_TEXT = """build_directory: .
|
|
22
21
|
sdk: c
|
|
23
22
|
devices:
|
|
@@ -33,14 +32,8 @@ FULL_EXPECTED_JSON = {
|
|
|
33
32
|
"build_directory": ".",
|
|
34
33
|
"sdk": "c",
|
|
35
34
|
"devices": ["nanox"],
|
|
36
|
-
"use_cases": {
|
|
37
|
-
|
|
38
|
-
"test": "DEBUG=1"
|
|
39
|
-
},
|
|
40
|
-
"tests": {
|
|
41
|
-
"unit_directory": "tests/unit",
|
|
42
|
-
"pytest_directory": "tests/functional"
|
|
43
|
-
}
|
|
35
|
+
"use_cases": {"debug": "DEBUG=1", "test": "DEBUG=1"},
|
|
36
|
+
"tests": {"unit_directory": "tests/unit", "pytest_directory": "tests/functional"},
|
|
44
37
|
}
|
|
45
38
|
|
|
46
39
|
UC_D_EXPECTED_TEXT_CHUNKS = [
|
|
@@ -50,7 +43,7 @@ UC_D_EXPECTED_TEXT_CHUNKS = [
|
|
|
50
43
|
tests:
|
|
51
44
|
dependencies:
|
|
52
45
|
testing_develop:""",
|
|
53
|
-
|
|
46
|
+
"""
|
|
54
47
|
url: https://github.com/<owner>/<app-repository>
|
|
55
48
|
ref: develop
|
|
56
49
|
use_case: debug
|
|
@@ -59,12 +52,12 @@ tests:
|
|
|
59
52
|
url: https://github.com/<owner>/<other-app-repository>
|
|
60
53
|
ref: develop
|
|
61
54
|
use_case: default
|
|
62
|
-
application_directory: tests/functional/.dependencies/<other-app-repository>-develop-default"""
|
|
55
|
+
application_directory: tests/functional/.dependencies/<other-app-repository>-develop-default""",
|
|
63
56
|
]
|
|
64
57
|
|
|
65
58
|
UC_D_EXPECTED_JSON = {
|
|
66
|
-
"use_cases": {
|
|
67
|
-
"tests": {
|
|
59
|
+
"use_cases": {"debug": "DEBUG=1", "test": "DEBUG=1"},
|
|
60
|
+
"tests": {"dependencies": {}},
|
|
68
61
|
}
|
|
69
62
|
|
|
70
63
|
EXPECTED_DEPENDENCIES_JSON = [
|
|
@@ -72,14 +65,14 @@ EXPECTED_DEPENDENCIES_JSON = [
|
|
|
72
65
|
"url": "https://github.com/<owner>/<app-repository>",
|
|
73
66
|
"ref": "develop",
|
|
74
67
|
"use_case": "debug",
|
|
75
|
-
"application_directory": "tests/functional/.dependencies/<app-repository>-develop-debug"
|
|
76
|
-
|
|
68
|
+
"application_directory": "tests/functional/.dependencies/<app-repository>-develop-debug",
|
|
69
|
+
},
|
|
77
70
|
{
|
|
78
71
|
"url": "https://github.com/<owner>/<other-app-repository>",
|
|
79
72
|
"ref": "develop",
|
|
80
73
|
"use_case": "default",
|
|
81
|
-
"application_directory": "tests/functional/.dependencies/<other-app-repository>-develop-default"
|
|
82
|
-
}
|
|
74
|
+
"application_directory": "tests/functional/.dependencies/<other-app-repository>-develop-default",
|
|
75
|
+
},
|
|
83
76
|
]
|
|
84
77
|
|
|
85
78
|
|
|
@@ -132,7 +125,7 @@ class TestCLIMain(TestCase):
|
|
|
132
125
|
def test_cases_and_dependencies_json(self):
|
|
133
126
|
self.args.output_use_cases = list()
|
|
134
127
|
self.args.output_tests_dependencies = list()
|
|
135
|
-
self.args.json=True
|
|
128
|
+
self.args.json = True
|
|
136
129
|
self.assertIsNone(main())
|
|
137
130
|
# like before, the output needs to be divided and the lists compared
|
|
138
131
|
# separately as they may have been re-ordered
|
|
@@ -180,12 +173,16 @@ class TestCLIMain(TestCase):
|
|
|
180
173
|
ref: develop
|
|
181
174
|
use_case: debug
|
|
182
175
|
application_directory: some/dir/.dependencies/<app-repository>-develop-debug"""
|
|
183
|
-
expected_json = {
|
|
184
|
-
"
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
176
|
+
expected_json = {
|
|
177
|
+
"testing_develop": [
|
|
178
|
+
{
|
|
179
|
+
"url": "https://github.com/<owner>/<app-repository>",
|
|
180
|
+
"ref": "develop",
|
|
181
|
+
"use_case": "debug",
|
|
182
|
+
"application_directory": "some/dir/.dependencies/<app-repository>-develop-debug",
|
|
183
|
+
}
|
|
184
|
+
]
|
|
185
|
+
}
|
|
189
186
|
self.assertIsNone(main())
|
|
190
187
|
self.assertEqual(self.text, expected_text)
|
|
191
188
|
|
|
@@ -224,7 +221,6 @@ class TestCLIMain(TestCase):
|
|
|
224
221
|
|
|
225
222
|
|
|
226
223
|
class TestCLIset_parser(TestCase):
|
|
227
|
-
|
|
228
224
|
diffMax = None
|
|
229
225
|
|
|
230
226
|
def test_set_parser(self):
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import pytest
|
|
2
2
|
import requests
|
|
3
3
|
from pathlib import Path
|
|
4
|
-
from unittest import TestCase
|
|
5
4
|
|
|
6
5
|
from github.GithubException import GithubException
|
|
7
|
-
from ledgered.github import AppRepository,
|
|
6
|
+
from ledgered.github import AppRepository, GitHubApps
|
|
8
7
|
|
|
9
8
|
|
|
10
9
|
def test_apps(gh):
|
|
@@ -29,7 +28,9 @@ def test_exchange_makefile_path(exchange):
|
|
|
29
28
|
|
|
30
29
|
|
|
31
30
|
def test_exchange_makefile(exchange):
|
|
32
|
-
makefile = requests.get(
|
|
31
|
+
makefile = requests.get(
|
|
32
|
+
"https://raw.githubusercontent.com/LedgerHQ/app-exchange/develop/Makefile"
|
|
33
|
+
).content.decode()
|
|
33
34
|
assert exchange.makefile == makefile
|
|
34
35
|
|
|
35
36
|
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
2
|
from unittest import TestCase
|
|
3
3
|
|
|
4
|
-
from ledgered.manifest.manifest import Manifest, MANIFEST_FILE_NAME
|
|
4
|
+
from ledgered.manifest.manifest import Manifest, MANIFEST_FILE_NAME, TestsConfig
|
|
5
5
|
|
|
6
6
|
from .. import TEST_MANIFEST_DIRECTORY
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
class TestManifest(TestCase):
|
|
10
|
-
|
|
11
10
|
def check_ledger_app_toml(self, manifest: Manifest) -> None:
|
|
12
11
|
self.assertEqual(manifest.app.sdk, "rust")
|
|
13
12
|
self.assertEqual(manifest.app.devices, {"nanos", "stax", "flex"})
|
|
@@ -15,6 +14,7 @@ class TestManifest(TestCase):
|
|
|
15
14
|
self.assertTrue(manifest.app.is_rust)
|
|
16
15
|
self.assertFalse(manifest.app.is_c)
|
|
17
16
|
|
|
17
|
+
self.assertIsInstance(manifest.tests, TestsConfig)
|
|
18
18
|
self.assertEqual(manifest.tests.unit_directory, Path("unit"))
|
|
19
19
|
self.assertEqual(manifest.tests.pytest_directory, Path("pytest"))
|
|
20
20
|
|
|
@@ -3,12 +3,17 @@ from unittest import TestCase
|
|
|
3
3
|
|
|
4
4
|
from ledgered.manifest.constants import DEFAULT_USE_CASE
|
|
5
5
|
from ledgered.manifest.errors import MissingField
|
|
6
|
-
from ledgered.manifest.tests import
|
|
7
|
-
|
|
6
|
+
from ledgered.manifest.tests import (
|
|
7
|
+
DuplicateDependencyError,
|
|
8
|
+
TestsConfig,
|
|
9
|
+
TestsDependencyConfig,
|
|
10
|
+
TestsDependenciesConfig,
|
|
11
|
+
APPLICATION_DIRECTORY_KEY,
|
|
12
|
+
APPLICATION_DIRECTORY_NAME,
|
|
13
|
+
)
|
|
8
14
|
|
|
9
15
|
|
|
10
16
|
class TestTestsDependencyConfig(TestCase):
|
|
11
|
-
|
|
12
17
|
def setUp(self):
|
|
13
18
|
self.n, self.r, self.bd, self.uc = "name", "ref", Path("base_dir"), "use_case"
|
|
14
19
|
self.url = "/".join(["some url", self.n])
|
|
@@ -43,26 +48,38 @@ class TestTestsDependencyConfig(TestCase):
|
|
|
43
48
|
|
|
44
49
|
|
|
45
50
|
class TestTestsDependenciesConfig(TestCase):
|
|
46
|
-
|
|
47
51
|
def setUp(self):
|
|
48
52
|
self.bd = Path("test")
|
|
49
53
|
self.u1, self.r1, self.uc1 = "url1", "ref1", "use_case1"
|
|
50
54
|
self.u2, self.r2, self.uc2 = "url2", "ref2", "use_case2"
|
|
51
|
-
self.input = [
|
|
52
|
-
|
|
55
|
+
self.input = [
|
|
56
|
+
{"url": self.u1, "ref": self.r1, "use_case": self.uc1},
|
|
57
|
+
{"url": self.u2, "ref": self.r2, "use_case": self.uc2},
|
|
58
|
+
]
|
|
53
59
|
self.tdc = TestsDependenciesConfig(self.input, self.bd)
|
|
54
60
|
|
|
55
61
|
def test___init__ok(self):
|
|
56
|
-
self.assertSetEqual(
|
|
57
|
-
|
|
62
|
+
self.assertSetEqual(
|
|
63
|
+
self.tdc.dependencies,
|
|
64
|
+
{
|
|
65
|
+
TestsDependencyConfig(self.u1, self.r1, self.bd, self.uc1),
|
|
66
|
+
TestsDependencyConfig(self.u2, self.r2, self.bd, self.uc2),
|
|
67
|
+
},
|
|
68
|
+
)
|
|
58
69
|
|
|
59
70
|
def test___init__nok(self):
|
|
60
71
|
with self.assertRaises(DuplicateDependencyError):
|
|
61
|
-
TestsDependenciesConfig(
|
|
72
|
+
TestsDependenciesConfig(
|
|
73
|
+
[{"url": self.u1, "ref": self.r1, "use_case": self.uc1}] * 2, base_dir="something"
|
|
74
|
+
)
|
|
62
75
|
|
|
63
76
|
def test_json(self):
|
|
64
|
-
self.input[0][APPLICATION_DIRECTORY_KEY] = str(
|
|
65
|
-
|
|
77
|
+
self.input[0][APPLICATION_DIRECTORY_KEY] = str(
|
|
78
|
+
self.bd / APPLICATION_DIRECTORY_NAME / f"{self.u1}-{self.r1}-{self.uc1}"
|
|
79
|
+
)
|
|
80
|
+
self.input[1][APPLICATION_DIRECTORY_KEY] = str(
|
|
81
|
+
self.bd / APPLICATION_DIRECTORY_NAME / f"{self.u2}-{self.r2}-{self.uc2}"
|
|
82
|
+
)
|
|
66
83
|
# CountEqual rather than ListEqual, as the list is managed as a set and the content can
|
|
67
84
|
# be reordered when serialized back to list
|
|
68
85
|
self.assertCountEqual(self.tdc.json, self.input)
|
|
@@ -74,9 +91,13 @@ class TestTestsConfig(TestCase):
|
|
|
74
91
|
def test____init___ok_complete(self):
|
|
75
92
|
ud = Path("")
|
|
76
93
|
pd = Path("something")
|
|
77
|
-
deps = {
|
|
78
|
-
|
|
79
|
-
|
|
94
|
+
deps = {
|
|
95
|
+
"first": [{"url": "url", "ref": "ref"}],
|
|
96
|
+
"second": [
|
|
97
|
+
{"url": "u1", "ref": "r1", "use_case": "uc1"},
|
|
98
|
+
{"url": "u2", "ref": "r2", "use_case": "uc2"},
|
|
99
|
+
],
|
|
100
|
+
}
|
|
80
101
|
config = TestsConfig(unit_directory=str(ud), pytest_directory=str(pd), dependencies=deps)
|
|
81
102
|
self.assertIsNotNone(config.unit_directory)
|
|
82
103
|
self.assertEqual(config.unit_directory, ud)
|
|
@@ -90,9 +111,15 @@ class TestTestsConfig(TestCase):
|
|
|
90
111
|
result_json = config.json
|
|
91
112
|
result_deps = result_json.pop("dependencies")
|
|
92
113
|
self.assertEqual(len(result_deps), len(deps))
|
|
93
|
-
deps["first"][0][APPLICATION_DIRECTORY_KEY] = str(
|
|
94
|
-
|
|
95
|
-
|
|
114
|
+
deps["first"][0][APPLICATION_DIRECTORY_KEY] = str(
|
|
115
|
+
pd / APPLICATION_DIRECTORY_NAME / "url-ref-default"
|
|
116
|
+
)
|
|
117
|
+
deps["second"][0][APPLICATION_DIRECTORY_KEY] = str(
|
|
118
|
+
pd / APPLICATION_DIRECTORY_NAME / "u1-r1-uc1"
|
|
119
|
+
)
|
|
120
|
+
deps["second"][1][APPLICATION_DIRECTORY_KEY] = str(
|
|
121
|
+
pd / APPLICATION_DIRECTORY_NAME / "u2-r2-uc2"
|
|
122
|
+
)
|
|
96
123
|
for k, v in result_deps.items():
|
|
97
124
|
self.assertIn(k, deps)
|
|
98
125
|
self.assertCountEqual(v, deps[k])
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
from pathlib import Path
|
|
2
1
|
from unittest import TestCase
|
|
3
2
|
|
|
4
3
|
from ledgered.manifest.constants import DEFAULT_USE_CASE
|
|
@@ -6,11 +5,9 @@ from ledgered.manifest.use_cases import UseCasesConfig
|
|
|
6
5
|
|
|
7
6
|
|
|
8
7
|
class TestUseCaseConfig(TestCase):
|
|
9
|
-
|
|
10
8
|
def setUp(self):
|
|
11
9
|
self.key = "first"
|
|
12
|
-
self.cases = {self.key: "something",
|
|
13
|
-
"other": "something else"}
|
|
10
|
+
self.cases = {self.key: "something", "other": "something else"}
|
|
14
11
|
self.uc = UseCasesConfig(**self.cases)
|
|
15
12
|
|
|
16
13
|
def test___init__empty(self):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from dataclasses import dataclass
|
|
2
2
|
from unittest import TestCase
|
|
3
|
-
from unittest.mock import
|
|
3
|
+
from unittest.mock import patch
|
|
4
4
|
from pathlib import Path
|
|
5
5
|
from typing import Any
|
|
6
6
|
|
|
@@ -8,7 +8,6 @@ from ledgered import binary as B
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
class TestSections(TestCase):
|
|
11
|
-
|
|
12
11
|
def setUp(self):
|
|
13
12
|
self.inputs = {
|
|
14
13
|
"api_level": "api_level",
|
|
@@ -44,26 +43,26 @@ class TestSections(TestCase):
|
|
|
44
43
|
|
|
45
44
|
def test___str__(self):
|
|
46
45
|
sections = B.Sections(**self.inputs)
|
|
47
|
-
self.assertEqual(
|
|
48
|
-
|
|
49
|
-
|
|
46
|
+
self.assertEqual(
|
|
47
|
+
"\n".join(f"{k} {v}" for k, v in sorted(self.inputs.items())), str(sections)
|
|
48
|
+
)
|
|
50
49
|
|
|
51
50
|
def test_json(self):
|
|
52
51
|
sections = B.Sections(**self.inputs)
|
|
53
52
|
# explicit `str(v)` as None values needs to be converted to 'None'
|
|
54
|
-
self.assertDictEqual({k: str(v) for k,v in self.inputs.items()}, sections.json)
|
|
53
|
+
self.assertDictEqual({k: str(v) for k, v in self.inputs.items()}, sections.json)
|
|
55
54
|
|
|
56
55
|
|
|
57
56
|
@dataclass
|
|
58
57
|
class Section:
|
|
59
58
|
name: str
|
|
60
59
|
_data: Any
|
|
60
|
+
|
|
61
61
|
def data(self) -> Any:
|
|
62
62
|
return self._data
|
|
63
63
|
|
|
64
64
|
|
|
65
65
|
class TestLedgerBinaryApp(TestCase):
|
|
66
|
-
|
|
67
66
|
def test___init__(self):
|
|
68
67
|
path = Path("/dev/urandom")
|
|
69
68
|
api_level, sdk_hash = "something", "some hash"
|
|
@@ -73,12 +72,12 @@ class TestLedgerBinaryApp(TestCase):
|
|
|
73
72
|
Section("unused", 1),
|
|
74
73
|
Section("ledger.api_level", api_level.encode()),
|
|
75
74
|
Section("ledger.sdk_hash", sdk_hash.encode()),
|
|
76
|
-
Section("still not used", b"some data")
|
|
75
|
+
Section("still not used", b"some data"),
|
|
77
76
|
]
|
|
78
77
|
bin = B.LedgerBinaryApp(path)
|
|
79
78
|
self.assertEqual(bin.sections, expected)
|
|
80
79
|
|
|
81
80
|
def test___init__from_str(self):
|
|
82
81
|
path = "/dev/urandom"
|
|
83
|
-
with patch("ledgered.binary.ELFFile")
|
|
82
|
+
with patch("ledgered.binary.ELFFile"):
|
|
84
83
|
B.LedgerBinaryApp(path)
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
from dataclasses import dataclass
|
|
2
2
|
from unittest import TestCase
|
|
3
|
-
from unittest.mock import patch, MagicMock
|
|
4
3
|
|
|
5
|
-
from ledgered.github import
|
|
4
|
+
from ledgered.github import Condition, GitHubApps, GitHubLedgerHQ
|
|
6
5
|
|
|
7
6
|
|
|
8
7
|
@dataclass
|
|
@@ -13,7 +12,6 @@ class AppRepositoryMock:
|
|
|
13
12
|
|
|
14
13
|
|
|
15
14
|
class TestGitHubApps(TestCase):
|
|
16
|
-
|
|
17
15
|
def setUp(self):
|
|
18
16
|
self.app1 = AppRepositoryMock("app-1")
|
|
19
17
|
self.app2 = AppRepositoryMock("not-app")
|
|
@@ -39,7 +37,6 @@ class TestGitHubApps(TestCase):
|
|
|
39
37
|
|
|
40
38
|
|
|
41
39
|
class TestGitHubLedgerHQ(TestCase):
|
|
42
|
-
|
|
43
40
|
def setUp(self):
|
|
44
41
|
self.g = GitHubLedgerHQ()
|
|
45
42
|
|
|
@@ -11,6 +11,7 @@ class JsonableTest1(Jsonable):
|
|
|
11
11
|
def __hash__(self):
|
|
12
12
|
return 1
|
|
13
13
|
|
|
14
|
+
|
|
14
15
|
@dataclass
|
|
15
16
|
class JsonableTest2(Jsonable):
|
|
16
17
|
one: str
|
|
@@ -18,7 +19,6 @@ class JsonableTest2(Jsonable):
|
|
|
18
19
|
|
|
19
20
|
|
|
20
21
|
class TestTypesModule(TestCase):
|
|
21
|
-
|
|
22
22
|
def setUp(self):
|
|
23
23
|
self.jt1 = JsonableTest1("base")
|
|
24
24
|
|
|
@@ -30,30 +30,30 @@ class TestTypesModule(TestCase):
|
|
|
30
30
|
def test_JsonList_json(self):
|
|
31
31
|
integer = 4
|
|
32
32
|
string = "str"
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
j_list = JsonList()
|
|
34
|
+
j_list.append(integer)
|
|
35
|
+
j_list.append(string)
|
|
36
|
+
j_list.append(self.jt1)
|
|
37
37
|
expected = [integer, string, {"base": "base"}]
|
|
38
|
-
self.assertEqual(
|
|
38
|
+
self.assertEqual(j_list.json, expected)
|
|
39
39
|
|
|
40
40
|
def test_JsonSet_json(self):
|
|
41
41
|
integer = 4
|
|
42
42
|
string = "str"
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
43
|
+
j_set = JsonSet()
|
|
44
|
+
j_set.add(integer)
|
|
45
|
+
j_set.add(string)
|
|
46
|
+
j_set.add(self.jt1)
|
|
47
47
|
expected = [integer, string, {"base": "base"}]
|
|
48
|
-
result =
|
|
48
|
+
result = j_set.json
|
|
49
49
|
# the JsonSet.json returns a list, but the set may have broken the order so we can't
|
|
50
50
|
# directly compare the two lists.
|
|
51
51
|
self.assertIsInstance(result, list)
|
|
52
52
|
self.assertCountEqual(result, expected)
|
|
53
53
|
|
|
54
54
|
def test_JsonDict_json(self):
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
j_dict = JsonDict()
|
|
56
|
+
j_dict[4] = 5
|
|
57
|
+
j_dict["base"] = self.jt1
|
|
58
58
|
expected = {4: 5, "base": {"base": "base"}}
|
|
59
|
-
self.assertEqual(
|
|
59
|
+
self.assertEqual(j_dict.json, expected)
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
name: Fast checks
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
workflow_dispatch:
|
|
5
|
-
push:
|
|
6
|
-
branches:
|
|
7
|
-
- develop
|
|
8
|
-
- master
|
|
9
|
-
pull_request:
|
|
10
|
-
|
|
11
|
-
jobs:
|
|
12
|
-
lint:
|
|
13
|
-
name: Linting
|
|
14
|
-
runs-on: ubuntu-latest
|
|
15
|
-
steps:
|
|
16
|
-
- name: Clone
|
|
17
|
-
uses: actions/checkout@v4
|
|
18
|
-
- run: pip install flake8 flake8-pyproject
|
|
19
|
-
- name: Flake8 lint Python code
|
|
20
|
-
run: flake8 src/
|
|
21
|
-
|
|
22
|
-
yapf:
|
|
23
|
-
name: Formatting
|
|
24
|
-
runs-on: ubuntu-latest
|
|
25
|
-
steps:
|
|
26
|
-
- name: Clone
|
|
27
|
-
uses: actions/checkout@v4
|
|
28
|
-
- run: pip install yapf toml
|
|
29
|
-
- name: Yapf source formatting
|
|
30
|
-
run: |
|
|
31
|
-
yapf src/ --recursive -d
|
|
32
|
-
|
|
33
|
-
mypy:
|
|
34
|
-
name: Type checking
|
|
35
|
-
runs-on: ubuntu-latest
|
|
36
|
-
steps:
|
|
37
|
-
- name: Clone
|
|
38
|
-
uses: actions/checkout@v4
|
|
39
|
-
- run: pip install mypy types-toml
|
|
40
|
-
- name: Mypy type checking
|
|
41
|
-
run: mypy src
|
|
42
|
-
|
|
43
|
-
bandit:
|
|
44
|
-
name: Security checking
|
|
45
|
-
runs-on: ubuntu-latest
|
|
46
|
-
steps:
|
|
47
|
-
- name: Clone
|
|
48
|
-
uses: actions/checkout@v4
|
|
49
|
-
- run: pip install bandit
|
|
50
|
-
- name: Bandit security checking
|
|
51
|
-
run: bandit -r src -ll
|
|
52
|
-
|
|
53
|
-
misspell:
|
|
54
|
-
name: Check misspellings
|
|
55
|
-
runs-on: ubuntu-latest
|
|
56
|
-
steps:
|
|
57
|
-
- name: Clone
|
|
58
|
-
uses: actions/checkout@v4
|
|
59
|
-
- name: Check misspellings
|
|
60
|
-
uses: codespell-project/actions-codespell@v1
|
|
61
|
-
with:
|
|
62
|
-
builtin: clear,rare
|
|
63
|
-
check_filenames: true
|
|
64
|
-
ignore_words_list: assertIn,crate,
|
|
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
|