idf-build-apps 2.5.0rc2__tar.gz → 2.5.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.
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/CHANGELOG.md +13 -21
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/PKG-INFO +1 -1
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/idf_build_apps/__init__.py +1 -1
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/idf_build_apps/args.py +60 -13
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/idf_build_apps/main.py +14 -2
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/idf_build_apps/manifest/if_parser.py +20 -11
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/idf_build_apps/manifest/manifest.py +14 -3
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/pyproject.toml +1 -1
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/setup.py +1 -1
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/tests/conftest.py +13 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/tests/test_args.py +67 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/tests/test_cmd.py +7 -8
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/tests/test_finder.py +1 -1
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/tests/test_manifest.py +9 -2
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/.editorconfig +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/.git-blame-ignore-revs +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/.gitattributes +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/.github/dependabot.yml +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/.github/workflows/check-pre-commit.yml +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/.github/workflows/issue_comment.yml +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/.github/workflows/new_issues.yml +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/.github/workflows/new_prs.yml +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/.github/workflows/publish-pypi.yml +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/.github/workflows/test-build-docs.yml +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/.github/workflows/test-build-idf-apps.yml +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/.gitignore +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/.pre-commit-config.yaml +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/.readthedocs.yml +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/CONTRIBUTING.md +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/LICENSE +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/README.md +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/docs/_apidoc_templates/module.rst_t +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/docs/_apidoc_templates/package.rst_t +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/docs/_apidoc_templates/toc.rst_t +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/docs/_static/espressif-logo.svg +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/docs/_static/theme_overrides.css +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/docs/_templates/layout.html +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/docs/conf_common.py +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/docs/en/Makefile +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/docs/en/conf.py +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/docs/en/explanations/build.rst +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/docs/en/explanations/config_rules.rst +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/docs/en/explanations/dependency_driven_build.rst +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/docs/en/explanations/find.rst +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/docs/en/guides/1.x_to_2.x.md +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/docs/en/index.rst +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/docs/en/others/CHANGELOG.md +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/docs/en/others/CONTRIBUTING.md +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/docs/en/references/cli.rst +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/docs/en/references/config_file.md +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/docs/en/references/manifest.rst +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/idf_build_apps/__main__.py +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/idf_build_apps/app.py +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/idf_build_apps/autocompletions.py +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/idf_build_apps/constants.py +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/idf_build_apps/finder.py +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/idf_build_apps/junit/__init__.py +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/idf_build_apps/junit/report.py +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/idf_build_apps/junit/utils.py +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/idf_build_apps/log.py +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/idf_build_apps/manifest/__init__.py +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/idf_build_apps/manifest/soc_header.py +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/idf_build_apps/session_args.py +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/idf_build_apps/utils.py +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/idf_build_apps/vendors/__init__.py +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/idf_build_apps/vendors/pydantic_sources.py +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/idf_build_apps/yaml/__init__.py +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/idf_build_apps/yaml/parser.py +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/license_header.txt +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/tests/test_app.py +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/tests/test_build.py +0 -0
- {idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/tests/test_utils.py +0 -0
|
@@ -2,43 +2,35 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
-
## v2.5.
|
|
5
|
+
## v2.5.1 (2024-09-26)
|
|
6
6
|
|
|
7
7
|
### Fix
|
|
8
8
|
|
|
9
|
-
-
|
|
10
|
-
- load config before cli args and func args
|
|
11
|
-
- pickle dump default protocal different in python 3.7
|
|
12
|
-
- keep backward compatibility in build_apps function
|
|
9
|
+
- stop using lambda functions since they cannot be pickled
|
|
13
10
|
|
|
14
|
-
## v2.5.
|
|
15
|
-
|
|
16
|
-
### Fix
|
|
17
|
-
|
|
18
|
-
- build_arguments expand @p placeholders
|
|
19
|
-
|
|
20
|
-
### Refactor
|
|
21
|
-
|
|
22
|
-
- rename BuildArguments.ignore_warning_strings to ignore_warning_strs
|
|
23
|
-
|
|
24
|
-
## v2.5.0rc0 (2024-09-10)
|
|
11
|
+
## v2.5.0 (2024-09-26)
|
|
25
12
|
|
|
26
13
|
### Feat
|
|
27
14
|
|
|
28
|
-
-
|
|
15
|
+
- raise exception when chaining `or`/`and` in manifest file if statements
|
|
16
|
+
- support `idf-build-apps find` with checking modified manifest files
|
|
29
17
|
- support `idf-build-apps dump-manifest-sha`
|
|
30
18
|
|
|
31
19
|
### Fix
|
|
32
20
|
|
|
33
|
-
-
|
|
34
|
-
-
|
|
21
|
+
- stop calling `sys.exit` when return code is 0
|
|
22
|
+
- load config file before cli arguments and func arguments
|
|
23
|
+
- pickle dump default protocol different in python 3.7
|
|
24
|
+
- loose env var requirements. `IDF_PATH` not required
|
|
25
|
+
- stop print build log as error when build failed due to `--warning-as-error`
|
|
35
26
|
- requires typing-extensions below 3.11
|
|
36
|
-
-
|
|
27
|
+
- stop wrongly created/deleted temporary build log file
|
|
37
28
|
|
|
38
29
|
### Refactor
|
|
39
30
|
|
|
40
31
|
- declare argument once. used in both function, cli, and docs
|
|
41
|
-
- move Manifest.ROOTPATH to
|
|
32
|
+
- move Manifest.ROOTPATH to arguments
|
|
33
|
+
- expand @p placeholders in `BuildArguments`
|
|
42
34
|
|
|
43
35
|
## v2.4.3 (2024-08-07)
|
|
44
36
|
|
|
@@ -11,6 +11,7 @@ import sys
|
|
|
11
11
|
import typing as t
|
|
12
12
|
from copy import deepcopy
|
|
13
13
|
from dataclasses import dataclass
|
|
14
|
+
from io import TextIOWrapper
|
|
14
15
|
from pathlib import Path
|
|
15
16
|
from typing import Any
|
|
16
17
|
|
|
@@ -51,6 +52,8 @@ class FieldMetadata:
|
|
|
51
52
|
:param choices: choices for the argument, used in argparse
|
|
52
53
|
:param type: type for the argument, used in argparse
|
|
53
54
|
:param required: whether the argument is required, used in argparse
|
|
55
|
+
:param default: default value for the argument, used in argparse
|
|
56
|
+
:param hidden: whether the argument is hidden, used in argparse
|
|
54
57
|
"""
|
|
55
58
|
|
|
56
59
|
# validate method
|
|
@@ -66,6 +69,8 @@ class FieldMetadata:
|
|
|
66
69
|
required: bool = False
|
|
67
70
|
# usually default is not needed. only set it when different from the default value of the field
|
|
68
71
|
default: t.Any = None
|
|
72
|
+
# hidden field, use deprecated instead, or hide it in the argparse
|
|
73
|
+
hidden: bool = False
|
|
69
74
|
|
|
70
75
|
|
|
71
76
|
P = ParamSpec('P')
|
|
@@ -195,7 +200,9 @@ class DependencyDrivenBuildArguments(GlobalArguments):
|
|
|
195
200
|
validate_method=[ValidateMethod.TO_LIST],
|
|
196
201
|
type=semicolon_separated_str_to_list,
|
|
197
202
|
),
|
|
198
|
-
description='semicolon-separated list of modified components'
|
|
203
|
+
description='semicolon-separated list of modified components. '
|
|
204
|
+
'If set to "", the value would be considered as None. '
|
|
205
|
+
'If set to ";", the value would be considered as an empty list.',
|
|
199
206
|
default=None,
|
|
200
207
|
)
|
|
201
208
|
modified_files: t.Optional[t.List[str]] = field(
|
|
@@ -203,7 +210,9 @@ class DependencyDrivenBuildArguments(GlobalArguments):
|
|
|
203
210
|
validate_method=[ValidateMethod.TO_LIST],
|
|
204
211
|
type=semicolon_separated_str_to_list,
|
|
205
212
|
),
|
|
206
|
-
description='semicolon-separated list of modified files'
|
|
213
|
+
description='semicolon-separated list of modified files. '
|
|
214
|
+
'If set to "", the value would be considered as None. '
|
|
215
|
+
'If set to ";", the value would be considered as an empty list.',
|
|
207
216
|
default=None,
|
|
208
217
|
)
|
|
209
218
|
deactivate_dependency_driven_build_by_components: t.Optional[t.List[str]] = field(
|
|
@@ -219,7 +228,10 @@ class DependencyDrivenBuildArguments(GlobalArguments):
|
|
|
219
228
|
shorthand='-dc',
|
|
220
229
|
),
|
|
221
230
|
description='semicolon-separated list of components. '
|
|
222
|
-
'dependency-driven build feature will be deactivated when any of these components are modified'
|
|
231
|
+
'dependency-driven build feature will be deactivated when any of these components are modified. '
|
|
232
|
+
'Must be specified together with --modified-components. '
|
|
233
|
+
'If set to "", the value would be considered as None. '
|
|
234
|
+
'If set to ";", the value would be considered as an empty list.',
|
|
223
235
|
validation_alias=AliasChoices(
|
|
224
236
|
'deactivate_dependency_driven_build_by_components', 'ignore_app_dependencies_components'
|
|
225
237
|
),
|
|
@@ -238,7 +250,10 @@ class DependencyDrivenBuildArguments(GlobalArguments):
|
|
|
238
250
|
shorthand='-df',
|
|
239
251
|
),
|
|
240
252
|
description='semicolon-separated list of file patterns. '
|
|
241
|
-
'dependency-driven build feature will be deactivated when any of matched files are modified'
|
|
253
|
+
'dependency-driven build feature will be deactivated when any of matched files are modified. '
|
|
254
|
+
'Must be specified together with --modified-files. '
|
|
255
|
+
'If set to "", the value would be considered as None. '
|
|
256
|
+
'If set to ";", the value would be considered as an empty list.',
|
|
242
257
|
validation_alias=AliasChoices(
|
|
243
258
|
'deactivate_dependency_driven_build_by_filepatterns', 'ignore_app_dependencies_filepatterns'
|
|
244
259
|
),
|
|
@@ -443,7 +458,10 @@ class FindBuildArguments(DependencyDrivenBuildArguments):
|
|
|
443
458
|
default=False,
|
|
444
459
|
)
|
|
445
460
|
default_build_targets: t.Optional[t.List[str]] = field(
|
|
446
|
-
|
|
461
|
+
FieldMetadata(
|
|
462
|
+
validate_method=[ValidateMethod.TO_LIST],
|
|
463
|
+
nargs='+',
|
|
464
|
+
),
|
|
447
465
|
description='space-separated list of the default enabled build targets for the apps. '
|
|
448
466
|
'When not specified, the default value is the targets listed by `idf.py --list-targets`',
|
|
449
467
|
default=None,
|
|
@@ -602,10 +620,16 @@ class BuildArguments(FindBuildArguments):
|
|
|
602
620
|
validation_alias=AliasChoices('ignore_warning_strs', 'ignore_warning_str'),
|
|
603
621
|
default=None,
|
|
604
622
|
)
|
|
605
|
-
ignore_warning_files: t.Optional[t.List[str]] = field(
|
|
623
|
+
ignore_warning_files: t.Optional[t.List[t.Union[str, TextIOWrapper]]] = field(
|
|
606
624
|
FieldMetadata(
|
|
607
|
-
|
|
625
|
+
validate_method=[ValidateMethod.TO_LIST],
|
|
626
|
+
deprecates={
|
|
627
|
+
'ignore_warning_file': {
|
|
628
|
+
'type': argparse.FileType('r'),
|
|
629
|
+
}
|
|
630
|
+
},
|
|
608
631
|
nargs='+',
|
|
632
|
+
type=argparse.FileType('r'),
|
|
609
633
|
),
|
|
610
634
|
description='Path to the files containing the patterns to ignore the warnings in the build output',
|
|
611
635
|
validation_alias=AliasChoices('ignore_warning_files', 'ignore_warning_file'),
|
|
@@ -621,7 +645,10 @@ class BuildArguments(FindBuildArguments):
|
|
|
621
645
|
|
|
622
646
|
# Attrs that support placeholders
|
|
623
647
|
collect_size_info_filename: t.Optional[str] = field(
|
|
624
|
-
|
|
648
|
+
FieldMetadata(
|
|
649
|
+
deprecates={'collect_size_info': {}},
|
|
650
|
+
hidden=True,
|
|
651
|
+
),
|
|
625
652
|
description='Record size json filepath of the built apps to the specified file. '
|
|
626
653
|
'Each line is a json string. Can expand placeholders @p',
|
|
627
654
|
validation_alias=AliasChoices('collect_size_info_filename', 'collect_size_info'),
|
|
@@ -629,7 +656,10 @@ class BuildArguments(FindBuildArguments):
|
|
|
629
656
|
exclude=True, # computed field is used
|
|
630
657
|
)
|
|
631
658
|
collect_app_info_filename: t.Optional[str] = field(
|
|
632
|
-
|
|
659
|
+
FieldMetadata(
|
|
660
|
+
deprecates={'collect_app_info': {}},
|
|
661
|
+
hidden=True,
|
|
662
|
+
),
|
|
633
663
|
description='Record serialized app model of the built apps to the specified file. '
|
|
634
664
|
'Each line is a json string. Can expand placeholders @p',
|
|
635
665
|
validation_alias=AliasChoices('collect_app_info_filename', 'collect_app_info'),
|
|
@@ -637,7 +667,10 @@ class BuildArguments(FindBuildArguments):
|
|
|
637
667
|
exclude=True, # computed field is used
|
|
638
668
|
)
|
|
639
669
|
junitxml_filename: t.Optional[str] = field(
|
|
640
|
-
|
|
670
|
+
FieldMetadata(
|
|
671
|
+
deprecates={'junitxml': {}},
|
|
672
|
+
hidden=True,
|
|
673
|
+
),
|
|
641
674
|
description='Path to the junitxml file to record the build results. Can expand placeholder @p',
|
|
642
675
|
validation_alias=AliasChoices('junitxml_filename', 'junitxml'),
|
|
643
676
|
default=None,
|
|
@@ -654,8 +687,14 @@ class BuildArguments(FindBuildArguments):
|
|
|
654
687
|
for s in self.ignore_warning_strs:
|
|
655
688
|
ignore_warnings_regexes.append(re.compile(s))
|
|
656
689
|
if self.ignore_warning_files:
|
|
657
|
-
for
|
|
658
|
-
|
|
690
|
+
for f in self.ignore_warning_files:
|
|
691
|
+
if isinstance(f, str):
|
|
692
|
+
with open(f) as fr:
|
|
693
|
+
for s in fr:
|
|
694
|
+
ignore_warnings_regexes.append(re.compile(s.strip()))
|
|
695
|
+
else:
|
|
696
|
+
for s in f:
|
|
697
|
+
ignore_warnings_regexes.append(re.compile(s.strip()))
|
|
659
698
|
App.IGNORE_WARNS_REGEXES = ignore_warnings_regexes
|
|
660
699
|
|
|
661
700
|
@computed_field # type: ignore
|
|
@@ -734,12 +773,20 @@ def add_args_to_parser(argument_cls: t.Type[BaseArguments], parser: argparse.Arg
|
|
|
734
773
|
if _shorthand:
|
|
735
774
|
_names.append(_shorthand)
|
|
736
775
|
|
|
776
|
+
if f_meta.hidden: # f is hidden, use deprecated field instead
|
|
777
|
+
help_msg = f.description
|
|
778
|
+
else:
|
|
779
|
+
help_msg = f'[Deprecated] Use {_snake_case_to_cli_arg_name(f_name)} instead'
|
|
780
|
+
|
|
737
781
|
parser.add_argument(
|
|
738
782
|
*_names,
|
|
739
783
|
**dep_f_kwargs,
|
|
740
|
-
help=
|
|
784
|
+
help=help_msg,
|
|
741
785
|
)
|
|
742
786
|
|
|
787
|
+
if f_meta and f_meta.hidden:
|
|
788
|
+
continue
|
|
789
|
+
|
|
743
790
|
names = [_snake_case_to_cli_arg_name(f_name)]
|
|
744
791
|
if f_meta and f_meta.shorthand:
|
|
745
792
|
names.append(f_meta.shorthand)
|
|
@@ -70,6 +70,15 @@ def find_apps(
|
|
|
70
70
|
"""
|
|
71
71
|
apply_config_file(config_file)
|
|
72
72
|
|
|
73
|
+
# compatible with old usage
|
|
74
|
+
## `preserve`
|
|
75
|
+
if 'preserve' in kwargs:
|
|
76
|
+
LOGGER.warning(
|
|
77
|
+
'Passing "preserve" directly is deprecated. '
|
|
78
|
+
'Pass "no_preserve" instead to disable preserving the build directory'
|
|
79
|
+
)
|
|
80
|
+
kwargs['no_preserve'] = not kwargs.pop('preserve')
|
|
81
|
+
|
|
73
82
|
if find_arguments is None:
|
|
74
83
|
find_arguments = FindArguments(
|
|
75
84
|
paths=to_list(paths), # type: ignore
|
|
@@ -125,7 +134,8 @@ def build_apps(
|
|
|
125
134
|
"""
|
|
126
135
|
apply_config_file(config_file)
|
|
127
136
|
|
|
128
|
-
|
|
137
|
+
# compatible with old usage
|
|
138
|
+
## `check_app_dependencies`
|
|
129
139
|
if 'check_app_dependencies' in kwargs:
|
|
130
140
|
LOGGER.warning(
|
|
131
141
|
'Passing "check_app_dependencies" directly is deprecated. '
|
|
@@ -138,6 +148,7 @@ def build_apps(
|
|
|
138
148
|
**kwargs,
|
|
139
149
|
)
|
|
140
150
|
|
|
151
|
+
apps = to_list(apps)
|
|
141
152
|
if apps is None:
|
|
142
153
|
apps = find_apps(
|
|
143
154
|
find_arguments=FindArguments(
|
|
@@ -431,7 +442,8 @@ def main():
|
|
|
431
442
|
for app in failed_apps:
|
|
432
443
|
print(f' {app}')
|
|
433
444
|
|
|
434
|
-
|
|
445
|
+
if ret_code != 0:
|
|
446
|
+
sys.exit(ret_code)
|
|
435
447
|
|
|
436
448
|
|
|
437
449
|
def json_to_app(json_str: str, extra_classes: t.Optional[t.List[t.Type[App]]] = None) -> App:
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
|
2
2
|
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
-
|
|
4
3
|
import operator
|
|
5
4
|
import os
|
|
6
5
|
from ast import (
|
|
@@ -16,6 +15,7 @@ from packaging.version import (
|
|
|
16
15
|
from pyparsing import (
|
|
17
16
|
Keyword,
|
|
18
17
|
Literal,
|
|
18
|
+
MatchFirst,
|
|
19
19
|
ParseResults,
|
|
20
20
|
QuotedString,
|
|
21
21
|
Suppress,
|
|
@@ -35,6 +35,7 @@ from ..constants import (
|
|
|
35
35
|
IDF_VERSION_PATCH,
|
|
36
36
|
)
|
|
37
37
|
from ..utils import (
|
|
38
|
+
InvalidIfClause,
|
|
38
39
|
InvalidInput,
|
|
39
40
|
to_version,
|
|
40
41
|
)
|
|
@@ -177,22 +178,31 @@ class BoolExpr(Stmt):
|
|
|
177
178
|
pass
|
|
178
179
|
|
|
179
180
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
self.left: BoolStmt = t[0][0]
|
|
183
|
-
self.right: BoolStmt = t[0][2]
|
|
181
|
+
def _and(_l, _r):
|
|
182
|
+
return _l and _r
|
|
184
183
|
|
|
185
|
-
|
|
186
|
-
|
|
184
|
+
|
|
185
|
+
def _or(_l, _r):
|
|
186
|
+
return _l or _r
|
|
187
187
|
|
|
188
188
|
|
|
189
|
-
class
|
|
189
|
+
class BoolOrAnd(BoolExpr):
|
|
190
190
|
def __init__(self, t: ParseResults):
|
|
191
|
+
if len(t[0]) > 3:
|
|
192
|
+
raise InvalidIfClause(
|
|
193
|
+
'Chaining "and"/"or" is not allowed. Please use paratheses instead. '
|
|
194
|
+
'For example: "a and b and c" should be "(a and b) and c".'
|
|
195
|
+
)
|
|
191
196
|
self.left: BoolStmt = t[0][0]
|
|
192
197
|
self.right: BoolStmt = t[0][2]
|
|
193
198
|
|
|
199
|
+
if t[0][1] == 'and':
|
|
200
|
+
self.operation = _and
|
|
201
|
+
if t[0][1] == 'or':
|
|
202
|
+
self.operation = _or
|
|
203
|
+
|
|
194
204
|
def get_value(self, target: str, config_name: str) -> Any:
|
|
195
|
-
return self.left.get_value(target, config_name)
|
|
205
|
+
return self.operation(self.left.get_value(target, config_name), self.right.get_value(target, config_name))
|
|
196
206
|
|
|
197
207
|
|
|
198
208
|
CAP_WORD = Word(alphas.upper(), nums + alphas.upper() + '_').setParseAction(ChipAttr)
|
|
@@ -225,7 +235,6 @@ OR = Keyword('or')
|
|
|
225
235
|
BOOL_EXPR = infixNotation(
|
|
226
236
|
BOOL_STMT,
|
|
227
237
|
[
|
|
228
|
-
(AND, 2, opAssoc.LEFT,
|
|
229
|
-
(OR, 2, opAssoc.LEFT, BoolOr),
|
|
238
|
+
(MatchFirst((AND, OR)), 2, opAssoc.LEFT, BoolOrAnd),
|
|
230
239
|
],
|
|
231
240
|
)
|
|
@@ -35,14 +35,21 @@ class IfClause:
|
|
|
35
35
|
def __init__(self, stmt: str, temporary: bool = False, reason: t.Optional[str] = None) -> None:
|
|
36
36
|
try:
|
|
37
37
|
self.stmt: BoolStmt = BOOL_EXPR.parseString(stmt)[0]
|
|
38
|
-
except ParseException:
|
|
39
|
-
raise InvalidIfClause(f'Invalid if
|
|
38
|
+
except (ParseException, InvalidIfClause) as ex:
|
|
39
|
+
raise InvalidIfClause(f'Invalid if clause: {stmt}. {ex}')
|
|
40
40
|
|
|
41
41
|
self.temporary = temporary
|
|
42
42
|
self.reason = reason
|
|
43
43
|
|
|
44
44
|
if self.temporary is True and not self.reason:
|
|
45
|
-
raise InvalidIfClause(
|
|
45
|
+
raise InvalidIfClause(
|
|
46
|
+
f'Invalid if clause "{stmt}". '
|
|
47
|
+
f'"reason" must be set when "temporary: true". '
|
|
48
|
+
f'For example:\n'
|
|
49
|
+
f' - if: {stmt}\n'
|
|
50
|
+
f' temporary: true\n'
|
|
51
|
+
f' reason: lack of ci runners'
|
|
52
|
+
)
|
|
46
53
|
|
|
47
54
|
def get_value(self, target: str, config_name: str) -> t.Any:
|
|
48
55
|
return self.stmt.get_value(target, config_name)
|
|
@@ -249,6 +256,7 @@ class Manifest:
|
|
|
249
256
|
|
|
250
257
|
rules: t.List[FolderRule] = []
|
|
251
258
|
for path in paths:
|
|
259
|
+
LOGGER.debug('Loading manifest file %s', path)
|
|
252
260
|
_manifest = cls.from_file(path, root_path=root_path)
|
|
253
261
|
|
|
254
262
|
for rule in _manifest.rules:
|
|
@@ -344,11 +352,14 @@ class Manifest:
|
|
|
344
352
|
return x
|
|
345
353
|
|
|
346
354
|
for folder, sha_value in recorded__rel_folder__sha__dict.items():
|
|
355
|
+
# removed
|
|
347
356
|
if folder not in self__rel_folder__sha__dict:
|
|
348
357
|
diff_folders.add(_path(folder))
|
|
358
|
+
# modified
|
|
349
359
|
elif sha_value != self__rel_folder__sha__dict[folder]:
|
|
350
360
|
diff_folders.add(_path(folder))
|
|
351
361
|
|
|
362
|
+
# new
|
|
352
363
|
for folder in self__rel_folder__sha__dict:
|
|
353
364
|
if folder not in recorded__rel_folder__sha__dict:
|
|
354
365
|
diff_folders.add(_path(folder))
|
|
@@ -35,7 +35,7 @@ entry_points = \
|
|
|
35
35
|
{'console_scripts': ['idf-build-apps = idf_build_apps:main.main']}
|
|
36
36
|
|
|
37
37
|
setup(name='idf-build-apps',
|
|
38
|
-
version='2.5.
|
|
38
|
+
version='2.5.1',
|
|
39
39
|
description='Tools for building ESP-IDF related apps.',
|
|
40
40
|
author=None,
|
|
41
41
|
author_email='Fu Hanxi <fuhanxi@espressif.com>',
|
|
@@ -66,3 +66,16 @@ def sha_of_enable_only_esp32():
|
|
|
66
66
|
)
|
|
67
67
|
|
|
68
68
|
return sha
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@pytest.fixture
|
|
72
|
+
def sha_of_enable_esp32_or_esp32s2():
|
|
73
|
+
sha = FolderRule('test1', enable=[{'if': 'IDF_TARGET == "esp32" or IDF_TARGET == "esp32s2"'}]).sha
|
|
74
|
+
|
|
75
|
+
# !!! ONLY CHANGE IT WHEN NECESSARY !!!
|
|
76
|
+
assert (
|
|
77
|
+
sha
|
|
78
|
+
== 'f3408e9bf1d6b9a9e14559e6567917986678a3414229b29f96493aec4dc1bc3e6d0ecc4f79adced0d5c26bc1cd80a4d15fe6aaefa5d1e7033a58290374f4fc7f' # noqa: E501
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
return sha
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
import pytest
|
|
5
5
|
|
|
6
|
+
from idf_build_apps import App
|
|
6
7
|
from idf_build_apps.args import (
|
|
7
8
|
BuildArguments,
|
|
8
9
|
DependencyDrivenBuildArguments,
|
|
@@ -10,6 +11,7 @@ from idf_build_apps.args import (
|
|
|
10
11
|
FindBuildArguments,
|
|
11
12
|
)
|
|
12
13
|
from idf_build_apps.constants import IDF_BUILD_APPS_TOML_FN
|
|
14
|
+
from idf_build_apps.main import main
|
|
13
15
|
|
|
14
16
|
|
|
15
17
|
def test_init_attr_deprecated_by():
|
|
@@ -123,3 +125,68 @@ modified_files = [
|
|
|
123
125
|
assert args.modified_files == ['file1']
|
|
124
126
|
assert args.verbose == 3
|
|
125
127
|
assert args.deactivate_dependency_driven_build_by_components == ['baz']
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
class TestIgnoreWarningFile:
|
|
131
|
+
def test_deprecated_cli(self, monkeypatch, capsys):
|
|
132
|
+
with open('foo.txt', 'w') as fw:
|
|
133
|
+
fw.write('warning:xxx')
|
|
134
|
+
|
|
135
|
+
with monkeypatch.context() as m:
|
|
136
|
+
m.setattr('sys.argv', ['idf-build-apps', 'build', '--ignore-warning-file', 'foo.txt'])
|
|
137
|
+
main()
|
|
138
|
+
|
|
139
|
+
assert len(App.IGNORE_WARNS_REGEXES) == 1
|
|
140
|
+
assert App.IGNORE_WARNS_REGEXES[0].pattern == 'warning:xxx'
|
|
141
|
+
|
|
142
|
+
with open('bar.txt', 'w') as fw:
|
|
143
|
+
fw.write('warning:yyy')
|
|
144
|
+
|
|
145
|
+
with monkeypatch.context() as m:
|
|
146
|
+
m.setattr('sys.argv', ['idf-build-apps', 'build', '--ignore-warning-file', 'foo.txt', 'bar.txt'])
|
|
147
|
+
with pytest.raises(SystemExit):
|
|
148
|
+
main()
|
|
149
|
+
|
|
150
|
+
assert 'unrecognized arguments: bar.txt' in capsys.readouterr().err
|
|
151
|
+
|
|
152
|
+
def test_new_cli(self, monkeypatch):
|
|
153
|
+
with open('foo.txt', 'w') as fw:
|
|
154
|
+
fw.write('warning:xxx')
|
|
155
|
+
with open('bar.txt', 'w') as fw:
|
|
156
|
+
fw.write('warning:yyy')
|
|
157
|
+
|
|
158
|
+
with monkeypatch.context() as m:
|
|
159
|
+
m.setattr('sys.argv', ['idf-build-apps', 'build', '--ignore-warning-files', 'foo.txt', 'bar.txt'])
|
|
160
|
+
main()
|
|
161
|
+
|
|
162
|
+
assert len(App.IGNORE_WARNS_REGEXES) == 2
|
|
163
|
+
assert App.IGNORE_WARNS_REGEXES[0].pattern == 'warning:xxx'
|
|
164
|
+
assert App.IGNORE_WARNS_REGEXES[1].pattern == 'warning:yyy'
|
|
165
|
+
|
|
166
|
+
def test_func_with_str(self):
|
|
167
|
+
with open('foo.txt', 'w') as fw:
|
|
168
|
+
fw.write('warning:xxx')
|
|
169
|
+
with open('bar.txt', 'w') as fw:
|
|
170
|
+
fw.write('warning:yyy')
|
|
171
|
+
|
|
172
|
+
BuildArguments(
|
|
173
|
+
ignore_warning_files=['foo.txt', 'bar.txt'],
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
assert len(App.IGNORE_WARNS_REGEXES) == 2
|
|
177
|
+
assert App.IGNORE_WARNS_REGEXES[0].pattern == 'warning:xxx'
|
|
178
|
+
assert App.IGNORE_WARNS_REGEXES[1].pattern == 'warning:yyy'
|
|
179
|
+
|
|
180
|
+
def test_func_with_fs(self):
|
|
181
|
+
with open('foo.txt', 'w') as fw:
|
|
182
|
+
fw.write('warning:xxx')
|
|
183
|
+
with open('bar.txt', 'w') as fw:
|
|
184
|
+
fw.write('warning:yyy')
|
|
185
|
+
|
|
186
|
+
BuildArguments(
|
|
187
|
+
ignore_warning_file=[open('foo.txt'), open('bar.txt')],
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
assert len(App.IGNORE_WARNS_REGEXES) == 2
|
|
191
|
+
assert App.IGNORE_WARNS_REGEXES[0].pattern == 'warning:xxx'
|
|
192
|
+
assert App.IGNORE_WARNS_REGEXES[1].pattern == 'warning:yyy'
|
|
@@ -10,13 +10,6 @@ from idf_build_apps.main import main
|
|
|
10
10
|
from idf_build_apps.utils import InvalidCommand
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
class FakeArgs:
|
|
14
|
-
"""like what argparse.Namespace does"""
|
|
15
|
-
|
|
16
|
-
def __init__(self, **kwargs):
|
|
17
|
-
self.__dict__.update(kwargs)
|
|
18
|
-
|
|
19
|
-
|
|
20
13
|
@pytest.mark.parametrize(
|
|
21
14
|
'args, expected_error',
|
|
22
15
|
[
|
|
@@ -26,7 +19,9 @@ class FakeArgs:
|
|
|
26
19
|
(['--manifest-files', 'test.yml', '--output', 'test.sha1'], None),
|
|
27
20
|
],
|
|
28
21
|
)
|
|
29
|
-
def test_manifest_dump_sha_values(
|
|
22
|
+
def test_manifest_dump_sha_values(
|
|
23
|
+
args, expected_error, sha_of_enable_only_esp32, sha_of_enable_esp32_or_esp32s2, capsys, monkeypatch
|
|
24
|
+
):
|
|
30
25
|
Path('test.yml').write_text(
|
|
31
26
|
"""
|
|
32
27
|
foo:
|
|
@@ -38,6 +33,9 @@ bar:
|
|
|
38
33
|
baz:
|
|
39
34
|
enable:
|
|
40
35
|
- if: IDF_TARGET == "esp32"
|
|
36
|
+
foobar:
|
|
37
|
+
enable:
|
|
38
|
+
- if: IDF_TARGET == "esp32" or IDF_TARGET == "esp32s2"
|
|
41
39
|
""",
|
|
42
40
|
encoding='utf8',
|
|
43
41
|
)
|
|
@@ -67,4 +65,5 @@ baz:
|
|
|
67
65
|
f'bar:{sha_of_enable_only_esp32}\n'
|
|
68
66
|
f'baz:{sha_of_enable_only_esp32}\n'
|
|
69
67
|
f'foo:{sha_of_enable_only_esp32}\n'
|
|
68
|
+
f'foobar:{sha_of_enable_esp32_or_esp32s2}\n'
|
|
70
69
|
)
|
|
@@ -102,7 +102,7 @@ get-started:
|
|
|
102
102
|
"""
|
|
103
103
|
examples/get-started:
|
|
104
104
|
enable:
|
|
105
|
-
- if: IDF_VERSION_MAJOR > 0 and IDF_VERSION_MINOR < 999
|
|
105
|
+
- if: IDF_VERSION_MAJOR > 0 and IDF_VERSION_MINOR < 999
|
|
106
106
|
""",
|
|
107
107
|
encoding='utf8',
|
|
108
108
|
)
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
|
2
2
|
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
-
|
|
4
3
|
import os
|
|
5
4
|
|
|
6
5
|
import pytest
|
|
@@ -522,9 +521,17 @@ class TestIfParser:
|
|
|
522
521
|
|
|
523
522
|
def test_invalid_if_statement(self):
|
|
524
523
|
statement = '1'
|
|
525
|
-
with pytest.raises(InvalidIfClause, match='Invalid if
|
|
524
|
+
with pytest.raises(InvalidIfClause, match='Invalid if clause: 1'):
|
|
526
525
|
IfClause(statement)
|
|
527
526
|
|
|
528
527
|
def test_temporary_must_with_reason(self):
|
|
529
528
|
with pytest.raises(InvalidIfClause, match='"reason" must be set when "temporary: true"'):
|
|
530
529
|
IfClause(stmt='IDF_TARGET == "esp32"', temporary=True)
|
|
530
|
+
|
|
531
|
+
|
|
532
|
+
def test_consecutive_or_and_stml_manifest():
|
|
533
|
+
with pytest.raises(InvalidIfClause, match='Chaining "and"/"or" is not allowed'):
|
|
534
|
+
IfClause(stmt='IDF_TARGET == "esp32" or IDF_TARGET == "esp32c3" or IDF_TARGET == "esp32s3"')
|
|
535
|
+
|
|
536
|
+
with pytest.raises(InvalidIfClause, match='Chaining "and"/"or" is not allowed'):
|
|
537
|
+
IfClause(stmt='IDF_TARGET == "esp32" or IDF_TARGET == "esp32c3" and IDF_TARGET == "esp32s3"')
|
|
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
|
{idf_build_apps-2.5.0rc2 → idf_build_apps-2.5.1}/docs/en/explanations/dependency_driven_build.rst
RENAMED
|
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
|