idf-build-apps 2.12.2__tar.gz → 2.13.0__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.12.2 → idf_build_apps-2.13.0}/.github/workflows/publish-pypi.yml +1 -1
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/.github/workflows/test-build-docs.yml +1 -1
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/.github/workflows/test-build-idf-apps.yml +1 -1
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/.pre-commit-config.yaml +2 -2
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/CHANGELOG.md +18 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/PKG-INFO +1 -1
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/idf_build_apps/__init__.py +1 -1
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/idf_build_apps/app.py +12 -13
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/idf_build_apps/args.py +46 -36
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/idf_build_apps/finder.py +11 -2
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/idf_build_apps/utils.py +3 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/pyproject.toml +10 -2
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/setup.py +1 -1
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/tests/test_args.py +177 -55
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/tests/test_finder.py +1 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/tests/test_utils.py +17 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/.editorconfig +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/.git-blame-ignore-revs +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/.gitattributes +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/.github/dependabot.yml +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/.github/workflows/sync-jira.yml +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/.gitignore +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/.readthedocs.yml +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/CONTRIBUTING.md +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/LICENSE +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/README.md +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/docs/_apidoc_templates/module.rst_t +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/docs/_apidoc_templates/package.rst_t +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/docs/_apidoc_templates/toc.rst_t +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/docs/_static/espressif-logo.svg +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/docs/_static/theme_overrides.css +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/docs/_templates/layout.html +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/docs/conf_common.py +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/docs/en/Makefile +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/docs/en/conf.py +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/docs/en/explanations/build.rst +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/docs/en/explanations/build_status.rst +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/docs/en/explanations/config_rules.rst +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/docs/en/explanations/dependency_driven_build.rst +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/docs/en/explanations/find.rst +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/docs/en/guides/1.x_to_2.x.md +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/docs/en/guides/custom_app.md +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/docs/en/index.rst +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/docs/en/others/CHANGELOG.md +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/docs/en/others/CONTRIBUTING.md +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/docs/en/references/cli.rst +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/docs/en/references/config_file.rst +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/docs/en/references/manifest.rst +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/idf_build_apps/__main__.py +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/idf_build_apps/autocompletions.py +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/idf_build_apps/constants.py +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/idf_build_apps/junit/__init__.py +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/idf_build_apps/junit/report.py +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/idf_build_apps/junit/utils.py +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/idf_build_apps/log.py +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/idf_build_apps/main.py +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/idf_build_apps/manifest/__init__.py +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/idf_build_apps/manifest/manifest.py +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/idf_build_apps/manifest/soc_header.py +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/idf_build_apps/py.typed +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/idf_build_apps/session_args.py +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/idf_build_apps/vendors/__init__.py +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/idf_build_apps/vendors/pydantic_sources.py +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/idf_build_apps/yaml/__init__.py +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/idf_build_apps/yaml/parser.py +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/license_header.txt +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/tests/conftest.py +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/tests/test_app.py +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/tests/test_build.py +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/tests/test_cmd.py +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/tests/test_disable_reasons.py +0 -0
- {idf_build_apps-2.12.2 → idf_build_apps-2.13.0}/tests/test_manifest.py +0 -0
|
@@ -17,13 +17,13 @@ repos:
|
|
|
17
17
|
- --use-current-year
|
|
18
18
|
exclude: 'idf_build_apps/vendors/'
|
|
19
19
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
20
|
-
rev: 'v0.
|
|
20
|
+
rev: 'v0.13.0'
|
|
21
21
|
hooks:
|
|
22
22
|
- id: ruff
|
|
23
23
|
args: ['--fix']
|
|
24
24
|
- id: ruff-format
|
|
25
25
|
- repo: https://github.com/pre-commit/mirrors-mypy
|
|
26
|
-
rev: 'v1.
|
|
26
|
+
rev: 'v1.18.1'
|
|
27
27
|
hooks:
|
|
28
28
|
- id: mypy
|
|
29
29
|
args: ['--warn-unused-ignores']
|
|
@@ -2,6 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## v2.13.0 (2025-09-26)
|
|
6
|
+
|
|
7
|
+
### ✨ New Features
|
|
8
|
+
|
|
9
|
+
- support `--additional-build-targets` *(Fu Hanxi - dbbd8d3)*
|
|
10
|
+
|
|
11
|
+
### 🐛 Bug Fixes
|
|
12
|
+
|
|
13
|
+
- **find_apps**: ignore target-specific sdkconfig files even without setting CONFIG_IDF_TARGET *(Fu Hanxi - 1861a7a)*
|
|
14
|
+
- record `checked_should_build` *(Fu Hanxi - f37fff1)*
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
## v2.12.3 (2025-09-16)
|
|
18
|
+
|
|
19
|
+
### Fix
|
|
20
|
+
|
|
21
|
+
- app behaves normally in set
|
|
22
|
+
|
|
5
23
|
## v2.12.2 (2025-08-27)
|
|
6
24
|
|
|
7
25
|
### Fix
|
|
@@ -109,6 +109,7 @@ class App(BaseModel):
|
|
|
109
109
|
build_status: BuildStatus = BuildStatus.UNKNOWN
|
|
110
110
|
build_comment: t.Optional[str] = None
|
|
111
111
|
test_comment: t.Optional[str] = None
|
|
112
|
+
checked_should_build: bool = False
|
|
112
113
|
|
|
113
114
|
_build_duration: float = 0
|
|
114
115
|
_build_timestamp: t.Optional[datetime] = None
|
|
@@ -116,6 +117,7 @@ class App(BaseModel):
|
|
|
116
117
|
__EQ_IGNORE_FIELDS__ = [
|
|
117
118
|
'build_comment',
|
|
118
119
|
'test_comment',
|
|
120
|
+
'checked_should_build',
|
|
119
121
|
]
|
|
120
122
|
__EQ_TUNE_FIELDS__ = {
|
|
121
123
|
'app_dir': lambda x: (os.path.realpath(os.path.expanduser(x))),
|
|
@@ -163,9 +165,6 @@ class App(BaseModel):
|
|
|
163
165
|
self._kwargs = kwargs
|
|
164
166
|
self._initialize_hook(**kwargs)
|
|
165
167
|
|
|
166
|
-
# private attrs, won't be dumped to json
|
|
167
|
-
self._checked_should_build = False
|
|
168
|
-
|
|
169
168
|
self._sdkconfig_files, self._sdkconfig_files_defined_target = self._process_sdkconfig_files()
|
|
170
169
|
|
|
171
170
|
@classmethod
|
|
@@ -750,12 +749,12 @@ class App(BaseModel):
|
|
|
750
749
|
self.build_comment += '\n'.join(f'- {clause}' for clause in rule.enable)
|
|
751
750
|
|
|
752
751
|
self.build_status = BuildStatus.DISABLED
|
|
753
|
-
self.
|
|
752
|
+
self.checked_should_build = True
|
|
754
753
|
return
|
|
755
754
|
|
|
756
755
|
if not check_app_dependencies:
|
|
757
756
|
self.build_status = BuildStatus.SHOULD_BE_BUILT
|
|
758
|
-
self.
|
|
757
|
+
self.checked_should_build = True
|
|
759
758
|
return
|
|
760
759
|
|
|
761
760
|
if (
|
|
@@ -765,26 +764,26 @@ class App(BaseModel):
|
|
|
765
764
|
):
|
|
766
765
|
self.build_status = BuildStatus.SHOULD_BE_BUILT
|
|
767
766
|
self.build_comment = 'current build modifies the related manifest rules'
|
|
768
|
-
self.
|
|
767
|
+
self.checked_should_build = True
|
|
769
768
|
return
|
|
770
769
|
|
|
771
770
|
if self.is_modified(modified_files):
|
|
772
771
|
self.build_status = BuildStatus.SHOULD_BE_BUILT
|
|
773
772
|
self.build_comment = 'current build modifies this app'
|
|
774
|
-
self.
|
|
773
|
+
self.checked_should_build = True
|
|
775
774
|
return
|
|
776
775
|
|
|
777
776
|
# if didn't modify any components, and no `depends_filepatterns` defined, skip
|
|
778
777
|
if modified_components == [] and not self.depends_filepatterns:
|
|
779
778
|
self.build_status = BuildStatus.SKIPPED
|
|
780
779
|
self.build_comment = 'current build does not modify any components'
|
|
781
|
-
self.
|
|
780
|
+
self.checked_should_build = True
|
|
782
781
|
return
|
|
783
782
|
|
|
784
783
|
# if no special rules defined, we left it unknown and decide with idf.py reconfigure
|
|
785
784
|
if not self.depends_components and not self.depends_filepatterns:
|
|
786
785
|
# keep unknown
|
|
787
|
-
self.
|
|
786
|
+
self.checked_should_build = True
|
|
788
787
|
self.build_comment = 'no special rules defined, run idf.py reconfigure to decide'
|
|
789
788
|
return
|
|
790
789
|
|
|
@@ -795,7 +794,7 @@ class App(BaseModel):
|
|
|
795
794
|
# depends components?
|
|
796
795
|
if self.depends_components and modified_components is not None:
|
|
797
796
|
if set(self.depends_components).intersection(set(modified_components)):
|
|
798
|
-
self.
|
|
797
|
+
self.checked_should_build = True
|
|
799
798
|
self.build_status = BuildStatus.SHOULD_BE_BUILT
|
|
800
799
|
self.build_comment = (
|
|
801
800
|
f'Requires components: {", ".join(self.depends_components)}. '
|
|
@@ -806,7 +805,7 @@ class App(BaseModel):
|
|
|
806
805
|
# or depends file patterns?
|
|
807
806
|
if self.depends_filepatterns and modified_files is not None:
|
|
808
807
|
if files_matches_patterns(modified_files, self.depends_filepatterns, manifest_rootpath):
|
|
809
|
-
self.
|
|
808
|
+
self.checked_should_build = True
|
|
810
809
|
self.build_status = BuildStatus.SHOULD_BE_BUILT
|
|
811
810
|
self.build_comment = (
|
|
812
811
|
f'Requires file patterns: {", ".join(self.depends_filepatterns)}. '
|
|
@@ -817,7 +816,7 @@ class App(BaseModel):
|
|
|
817
816
|
# special rules defined, but not matched
|
|
818
817
|
self.build_status = BuildStatus.SKIPPED
|
|
819
818
|
self.build_comment = 'current build does not modify any components or files required by this app'
|
|
820
|
-
self.
|
|
819
|
+
self.checked_should_build = True
|
|
821
820
|
|
|
822
821
|
def check_should_test(self) -> None:
|
|
823
822
|
"""Check if testing is disabled for this app and set test_disable_reason."""
|
|
@@ -955,7 +954,7 @@ class CMakeApp(App):
|
|
|
955
954
|
check_app_dependencies=check_app_dependencies,
|
|
956
955
|
)
|
|
957
956
|
|
|
958
|
-
if not self.
|
|
957
|
+
if not self.checked_should_build:
|
|
959
958
|
self.check_should_build(
|
|
960
959
|
manifest_rootpath=manifest_rootpath,
|
|
961
960
|
modified_components=modified_components,
|
|
@@ -29,7 +29,7 @@ from pydantic_settings import (
|
|
|
29
29
|
from typing_extensions import Concatenate, ParamSpec
|
|
30
30
|
|
|
31
31
|
from . import SESSION_ARGS, App, CMakeApp, MakeApp, setup_logging
|
|
32
|
-
from .constants import ALL_TARGETS, IDF_BUILD_APPS_TOML_FN
|
|
32
|
+
from .constants import ALL_TARGETS, IDF_BUILD_APPS_TOML_FN, PREVIEW_TARGETS, SUPPORTED_TARGETS
|
|
33
33
|
from .manifest.manifest import DEFAULT_BUILD_TARGETS, Manifest, reset_default_build_targets
|
|
34
34
|
from .utils import InvalidCommand, files_matches_patterns, semicolon_separated_str_to_list, to_absolute_path, to_list
|
|
35
35
|
from .vendors.pydantic_sources import PyprojectTomlConfigSettingsSource, TomlConfigSettingsSource
|
|
@@ -563,17 +563,22 @@ class FindBuildArguments(DependencyDrivenBuildArguments):
|
|
|
563
563
|
nargs='+',
|
|
564
564
|
),
|
|
565
565
|
description='space-separated list of the default enabled build targets for the apps. '
|
|
566
|
-
'When not specified, the default value is the targets listed by `idf.py --list-targets`.
|
|
567
|
-
|
|
566
|
+
'When not specified, the default value is the targets listed by `idf.py --list-targets`.',
|
|
567
|
+
default=None, # type: ignore
|
|
568
|
+
)
|
|
569
|
+
additional_build_targets: t.Optional[t.List[str]] = field(
|
|
570
|
+
FieldMetadata(
|
|
571
|
+
validate_method=[ValidateMethod.TO_LIST],
|
|
572
|
+
nargs='+',
|
|
573
|
+
),
|
|
574
|
+
description='space-separated list of additional build targets to add to the default enabled build targets',
|
|
568
575
|
default=None, # type: ignore
|
|
569
576
|
)
|
|
570
577
|
enable_preview_targets: bool = field(
|
|
571
578
|
FieldMetadata(
|
|
572
579
|
action='store_true',
|
|
573
580
|
),
|
|
574
|
-
description='When enabled,
|
|
575
|
-
'including the preview targets. As the targets defined in `idf.py --list-targets --preview`. '
|
|
576
|
-
'Cannot be used together with --default-build-targets',
|
|
581
|
+
description='When enabled, PREVIEW_TARGETS will be added to the default enabled build targets',
|
|
577
582
|
default=False, # type: ignore
|
|
578
583
|
)
|
|
579
584
|
disable_targets: t.Optional[t.List[str]] = field(
|
|
@@ -616,39 +621,44 @@ class FindBuildArguments(DependencyDrivenBuildArguments):
|
|
|
616
621
|
LOGGER.debug('--target is missing. Set --target as "all".')
|
|
617
622
|
self.target = 'all'
|
|
618
623
|
|
|
619
|
-
# Validate mutual exclusivity of enable_preview_targets and default_build_targets
|
|
620
|
-
if self.enable_preview_targets and self.default_build_targets:
|
|
621
|
-
raise InvalidCommand(
|
|
622
|
-
'Cannot specify both --enable-preview-targets and --default-build-targets at the same time. '
|
|
623
|
-
'Please use only one of these options.'
|
|
624
|
-
)
|
|
625
|
-
|
|
626
624
|
reset_default_build_targets() # reset first then judge again
|
|
625
|
+
|
|
626
|
+
# Build the target set by combining the options
|
|
627
|
+
default_build_targets: t.List[str] = []
|
|
628
|
+
# Step 1: Determine base targets
|
|
627
629
|
if self.default_build_targets:
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
630
|
+
LOGGER.info('--default-build-targets is set, using `%s`', self.default_build_targets)
|
|
631
|
+
default_build_targets = deepcopy(self.default_build_targets)
|
|
632
|
+
elif SUPPORTED_TARGETS:
|
|
633
|
+
LOGGER.info('Using default SUPPORTED_TARGETS: %s', SUPPORTED_TARGETS)
|
|
634
|
+
default_build_targets = deepcopy(SUPPORTED_TARGETS)
|
|
635
|
+
|
|
636
|
+
if self.enable_preview_targets:
|
|
637
|
+
LOGGER.info('--enable-preview-targets is set, adding preview targets `%s`', PREVIEW_TARGETS)
|
|
638
|
+
default_build_targets.extend(PREVIEW_TARGETS)
|
|
639
|
+
|
|
640
|
+
if self.additional_build_targets:
|
|
641
|
+
LOGGER.info('--additional-build-targets is set, adding `%s`', self.additional_build_targets)
|
|
642
|
+
default_build_targets.extend(self.additional_build_targets)
|
|
643
|
+
|
|
644
|
+
res = []
|
|
645
|
+
for _t in set(default_build_targets):
|
|
646
|
+
if _t not in ALL_TARGETS:
|
|
647
|
+
LOGGER.warning(
|
|
648
|
+
f'Ignoring... Unrecognizable target {_t} specified. '
|
|
649
|
+
f'Current ESP-IDF available targets: {ALL_TARGETS}'
|
|
650
|
+
)
|
|
651
|
+
continue
|
|
652
|
+
|
|
653
|
+
if self.disable_targets and _t in self.disable_targets:
|
|
654
|
+
LOGGER.info(f'Ignoring... Target {_t} is in the disabled targets list.')
|
|
655
|
+
continue
|
|
656
|
+
|
|
657
|
+
res.append(_t)
|
|
658
|
+
self.default_build_targets = sorted(res)
|
|
659
|
+
DEFAULT_BUILD_TARGETS.set(self.default_build_targets)
|
|
651
660
|
|
|
661
|
+
# Override sdkconfig files/items
|
|
652
662
|
if self.override_sdkconfig_files or self.override_sdkconfig_items:
|
|
653
663
|
SESSION_ARGS.set(self)
|
|
654
664
|
|
|
@@ -16,6 +16,7 @@ from .app import (
|
|
|
16
16
|
)
|
|
17
17
|
from .args import FindArguments
|
|
18
18
|
from .constants import (
|
|
19
|
+
ALL_TARGETS,
|
|
19
20
|
BuildStatus,
|
|
20
21
|
)
|
|
21
22
|
from .utils import (
|
|
@@ -26,6 +27,14 @@ from .utils import (
|
|
|
26
27
|
LOGGER = logging.getLogger(__name__)
|
|
27
28
|
|
|
28
29
|
|
|
30
|
+
def _is_target_specific(filepath: str) -> bool:
|
|
31
|
+
for target in ALL_TARGETS:
|
|
32
|
+
if filepath.endswith(f'.{target}'):
|
|
33
|
+
return True
|
|
34
|
+
|
|
35
|
+
return False
|
|
36
|
+
|
|
37
|
+
|
|
29
38
|
def _get_apps_from_path(
|
|
30
39
|
path: str,
|
|
31
40
|
target: str,
|
|
@@ -55,8 +64,8 @@ def _get_apps_from_path(
|
|
|
55
64
|
sdkconfig_paths_matched = True # skip the next block for no wildcard config rules
|
|
56
65
|
|
|
57
66
|
for sdkconfig_path in sdkconfig_paths:
|
|
58
|
-
if sdkconfig_path
|
|
59
|
-
LOGGER.debug('=> Skipping sdkconfig
|
|
67
|
+
if _is_target_specific(sdkconfig_path):
|
|
68
|
+
LOGGER.debug('=> Skipping sdkconfig file `%s` which is target-specific', sdkconfig_path)
|
|
60
69
|
continue
|
|
61
70
|
|
|
62
71
|
# Figure out the config name
|
|
@@ -386,6 +386,9 @@ class BaseModel(_BaseModel):
|
|
|
386
386
|
hash_list = []
|
|
387
387
|
|
|
388
388
|
self_model_dump = self.model_dump()
|
|
389
|
+
for _field in self.__EQ_IGNORE_FIELDS__:
|
|
390
|
+
self_model_dump.pop(_field, None)
|
|
391
|
+
|
|
389
392
|
for _field in self.__EQ_TUNE_FIELDS__:
|
|
390
393
|
self_model_dump[_field] = self.__EQ_TUNE_FIELDS__[_field](self_model_dump[_field])
|
|
391
394
|
|
|
@@ -64,9 +64,17 @@ changelog = "https://github.com/espressif/idf-build-apps/blob/main/CHANGELOG.md"
|
|
|
64
64
|
idf-build-apps = "idf_build_apps:main.main"
|
|
65
65
|
|
|
66
66
|
[tool.commitizen]
|
|
67
|
-
name = "
|
|
68
|
-
version = "2.
|
|
67
|
+
name = "czespressif"
|
|
68
|
+
version = "2.13.0"
|
|
69
|
+
|
|
69
70
|
tag_format = "v$version"
|
|
71
|
+
version_scheme = "pep440"
|
|
72
|
+
|
|
73
|
+
update_changelog_on_bump = true
|
|
74
|
+
changelog_merge_prerelease = true
|
|
75
|
+
|
|
76
|
+
types_in_changelog = ["BREAKING CHANGE", "feat", "fix", "refactor", "change", "perf", "docs"]
|
|
77
|
+
|
|
70
78
|
version_files = [
|
|
71
79
|
"idf_build_apps/__init__.py",
|
|
72
80
|
]
|
|
@@ -38,7 +38,7 @@ entry_points = \
|
|
|
38
38
|
{'console_scripts': ['idf-build-apps = idf_build_apps:main.main']}
|
|
39
39
|
|
|
40
40
|
setup(name='idf-build-apps',
|
|
41
|
-
version='2.
|
|
41
|
+
version='2.13.0',
|
|
42
42
|
description='Tools for building ESP-IDF related apps.',
|
|
43
43
|
author=None,
|
|
44
44
|
author_email='Fu Hanxi <fuhanxi@espressif.com>',
|
|
@@ -17,10 +17,9 @@ from idf_build_apps.args import (
|
|
|
17
17
|
FindBuildArguments,
|
|
18
18
|
expand_vars,
|
|
19
19
|
)
|
|
20
|
-
from idf_build_apps.constants import
|
|
20
|
+
from idf_build_apps.constants import IDF_BUILD_APPS_TOML_FN, PREVIEW_TARGETS, SUPPORTED_TARGETS
|
|
21
21
|
from idf_build_apps.main import main
|
|
22
|
-
from idf_build_apps.manifest.manifest import DEFAULT_BUILD_TARGETS, FolderRule
|
|
23
|
-
from idf_build_apps.utils import InvalidCommand
|
|
22
|
+
from idf_build_apps.manifest.manifest import DEFAULT_BUILD_TARGETS, FolderRule, reset_default_build_targets
|
|
24
23
|
|
|
25
24
|
|
|
26
25
|
def test_init_attr_deprecated_by():
|
|
@@ -171,13 +170,42 @@ modified_files = [
|
|
|
171
170
|
assert args.deactivate_dependency_driven_build_by_components == ['baz']
|
|
172
171
|
|
|
173
172
|
|
|
174
|
-
def
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
173
|
+
def test_combination_validation():
|
|
174
|
+
"""Test that target options can now be combined"""
|
|
175
|
+
# Mock targets for consistent testing
|
|
176
|
+
mock_supported = ['esp32', 'esp32s2']
|
|
177
|
+
mock_preview = ['esp32h2']
|
|
178
|
+
mock_all = mock_supported + mock_preview
|
|
178
179
|
|
|
179
|
-
|
|
180
|
-
|
|
180
|
+
import idf_build_apps.args
|
|
181
|
+
import idf_build_apps.constants
|
|
182
|
+
|
|
183
|
+
original_supported = idf_build_apps.constants.SUPPORTED_TARGETS
|
|
184
|
+
original_preview = idf_build_apps.constants.PREVIEW_TARGETS
|
|
185
|
+
original_all = idf_build_apps.constants.ALL_TARGETS
|
|
186
|
+
|
|
187
|
+
try:
|
|
188
|
+
idf_build_apps.constants.SUPPORTED_TARGETS = mock_supported
|
|
189
|
+
idf_build_apps.constants.PREVIEW_TARGETS = mock_preview
|
|
190
|
+
idf_build_apps.constants.ALL_TARGETS = mock_all
|
|
191
|
+
idf_build_apps.args.SUPPORTED_TARGETS = mock_supported
|
|
192
|
+
idf_build_apps.args.PREVIEW_TARGETS = mock_preview
|
|
193
|
+
idf_build_apps.args.ALL_TARGETS = mock_all
|
|
194
|
+
|
|
195
|
+
# Test combination: default + preview
|
|
196
|
+
args = FindBuildArguments(enable_preview_targets=True, default_build_targets=['esp32'], paths=['.'])
|
|
197
|
+
|
|
198
|
+
# Should combine: ['esp32'] + ['esp32h2'] = ['esp32', 'esp32h2']
|
|
199
|
+
expected = ['esp32', 'esp32h2']
|
|
200
|
+
assert args.default_build_targets == expected
|
|
201
|
+
|
|
202
|
+
finally:
|
|
203
|
+
idf_build_apps.constants.SUPPORTED_TARGETS = original_supported
|
|
204
|
+
idf_build_apps.constants.PREVIEW_TARGETS = original_preview
|
|
205
|
+
idf_build_apps.constants.ALL_TARGETS = original_all
|
|
206
|
+
idf_build_apps.args.SUPPORTED_TARGETS = original_supported
|
|
207
|
+
idf_build_apps.args.PREVIEW_TARGETS = original_preview
|
|
208
|
+
idf_build_apps.args.ALL_TARGETS = original_all
|
|
181
209
|
|
|
182
210
|
|
|
183
211
|
def test_build_targets_cli(tmp_path, monkeypatch):
|
|
@@ -430,9 +458,34 @@ dry_run = false
|
|
|
430
458
|
|
|
431
459
|
|
|
432
460
|
class TestDefaultBuildTargetsContextVar:
|
|
461
|
+
SUPPORTED_TARGETS = ['esp32', 'esp32s2']
|
|
462
|
+
PREVIEW_TARGETS = ['esp32h2', 'esp32p4']
|
|
463
|
+
ALL_TARGETS = SUPPORTED_TARGETS + PREVIEW_TARGETS + ['esp32s3', 'esp32c3']
|
|
464
|
+
|
|
465
|
+
@pytest.fixture(autouse=True)
|
|
466
|
+
def setup(self, monkeypatch):
|
|
467
|
+
import idf_build_apps.args
|
|
468
|
+
import idf_build_apps.constants
|
|
469
|
+
import idf_build_apps.manifest.manifest
|
|
470
|
+
|
|
471
|
+
# reset_default_build_targets() need .manifest.manifest
|
|
472
|
+
monkeypatch.setattr(idf_build_apps.manifest.manifest, 'SUPPORTED_TARGETS', self.SUPPORTED_TARGETS)
|
|
473
|
+
monkeypatch.setattr(idf_build_apps.constants, 'SUPPORTED_TARGETS', self.SUPPORTED_TARGETS)
|
|
474
|
+
monkeypatch.setattr(idf_build_apps.args, 'SUPPORTED_TARGETS', self.SUPPORTED_TARGETS)
|
|
475
|
+
|
|
476
|
+
monkeypatch.setattr(idf_build_apps.constants, 'PREVIEW_TARGETS', self.PREVIEW_TARGETS)
|
|
477
|
+
monkeypatch.setattr(idf_build_apps.args, 'PREVIEW_TARGETS', self.PREVIEW_TARGETS)
|
|
478
|
+
|
|
479
|
+
monkeypatch.setattr(idf_build_apps.manifest.manifest, 'ALL_TARGETS', self.SUPPORTED_TARGETS)
|
|
480
|
+
monkeypatch.setattr(idf_build_apps.constants, 'ALL_TARGETS', self.ALL_TARGETS)
|
|
481
|
+
monkeypatch.setattr(idf_build_apps.args, 'ALL_TARGETS', self.ALL_TARGETS)
|
|
482
|
+
|
|
483
|
+
reset_default_build_targets()
|
|
484
|
+
|
|
485
|
+
yield
|
|
486
|
+
|
|
433
487
|
def test_direct_contextvar_access(self):
|
|
434
|
-
|
|
435
|
-
assert DEFAULT_BUILD_TARGETS.get() == SUPPORTED_TARGETS
|
|
488
|
+
assert DEFAULT_BUILD_TARGETS.get() == self.SUPPORTED_TARGETS
|
|
436
489
|
|
|
437
490
|
# Test setting new values
|
|
438
491
|
test_targets = ['esp32', 'esp32s2']
|
|
@@ -440,14 +493,10 @@ class TestDefaultBuildTargetsContextVar:
|
|
|
440
493
|
assert DEFAULT_BUILD_TARGETS.get() == test_targets
|
|
441
494
|
|
|
442
495
|
# Test setting to ALL_TARGETS
|
|
443
|
-
DEFAULT_BUILD_TARGETS.set(ALL_TARGETS)
|
|
444
|
-
assert DEFAULT_BUILD_TARGETS.get() == ALL_TARGETS
|
|
445
|
-
assert len(DEFAULT_BUILD_TARGETS.get()) == len(SUPPORTED_TARGETS) + len(PREVIEW_TARGETS)
|
|
496
|
+
DEFAULT_BUILD_TARGETS.set(self.ALL_TARGETS)
|
|
497
|
+
assert DEFAULT_BUILD_TARGETS.get() == self.ALL_TARGETS
|
|
446
498
|
|
|
447
499
|
def test_folder_rule_backward_compatibility(self):
|
|
448
|
-
# Test initial access
|
|
449
|
-
assert FolderRule.DEFAULT_BUILD_TARGETS == SUPPORTED_TARGETS
|
|
450
|
-
|
|
451
500
|
# Test setting via contextvar
|
|
452
501
|
other_targets = ['esp32h2', 'esp32p4']
|
|
453
502
|
DEFAULT_BUILD_TARGETS.set(other_targets)
|
|
@@ -460,37 +509,29 @@ class TestDefaultBuildTargetsContextVar:
|
|
|
460
509
|
assert DEFAULT_BUILD_TARGETS.get() == test_targets
|
|
461
510
|
assert FolderRule.DEFAULT_BUILD_TARGETS == test_targets
|
|
462
511
|
|
|
463
|
-
def
|
|
464
|
-
|
|
465
|
-
|
|
512
|
+
def test_default_behavior(self):
|
|
513
|
+
args = FindBuildArguments(paths=['.'])
|
|
514
|
+
|
|
515
|
+
assert args.enable_preview_targets is False
|
|
516
|
+
assert args.default_build_targets == self.SUPPORTED_TARGETS
|
|
517
|
+
assert DEFAULT_BUILD_TARGETS.get() == self.SUPPORTED_TARGETS
|
|
466
518
|
|
|
519
|
+
def test_default_build_targets_option(self):
|
|
520
|
+
test_targets = ['esp32', 'esp32c3', 'esp32s2']
|
|
467
521
|
args = FindBuildArguments(default_build_targets=test_targets, paths=['.'])
|
|
468
522
|
|
|
469
523
|
assert args.default_build_targets == test_targets
|
|
470
524
|
assert DEFAULT_BUILD_TARGETS.get() == test_targets
|
|
471
|
-
assert FolderRule.DEFAULT_BUILD_TARGETS == test_targets
|
|
472
525
|
|
|
473
526
|
def test_enable_preview_targets_option(self):
|
|
474
|
-
"""Test that --enable-preview-targets option works correctly"""
|
|
475
527
|
args = FindBuildArguments(enable_preview_targets=True, paths=['.'])
|
|
476
528
|
|
|
477
529
|
assert args.enable_preview_targets is True
|
|
478
|
-
|
|
479
|
-
assert
|
|
480
|
-
assert
|
|
481
|
-
assert len(DEFAULT_BUILD_TARGETS.get()) == len(SUPPORTED_TARGETS) + len(PREVIEW_TARGETS)
|
|
482
|
-
|
|
483
|
-
def test_default_behavior(self):
|
|
484
|
-
"""Test default behavior when no special options are provided"""
|
|
485
|
-
args = FindBuildArguments(paths=['.'])
|
|
486
|
-
|
|
487
|
-
assert args.enable_preview_targets is False
|
|
488
|
-
assert args.default_build_targets is None
|
|
489
|
-
assert DEFAULT_BUILD_TARGETS.get() == SUPPORTED_TARGETS
|
|
490
|
-
assert FolderRule.DEFAULT_BUILD_TARGETS == SUPPORTED_TARGETS
|
|
530
|
+
expected_targets = sorted(self.SUPPORTED_TARGETS + self.PREVIEW_TARGETS)
|
|
531
|
+
assert args.default_build_targets == expected_targets
|
|
532
|
+
assert DEFAULT_BUILD_TARGETS.get() == expected_targets
|
|
491
533
|
|
|
492
534
|
def test_disable_targets_with_default_build_targets(self):
|
|
493
|
-
"""Test --disable-targets option works with --default-build-targets"""
|
|
494
535
|
args = FindBuildArguments(
|
|
495
536
|
default_build_targets=['esp32', 'esp32s2', 'esp32c3'], disable_targets=['esp32s2'], paths=['.']
|
|
496
537
|
)
|
|
@@ -498,23 +539,19 @@ class TestDefaultBuildTargetsContextVar:
|
|
|
498
539
|
expected_targets = ['esp32', 'esp32c3']
|
|
499
540
|
assert args.default_build_targets == expected_targets
|
|
500
541
|
assert DEFAULT_BUILD_TARGETS.get() == expected_targets
|
|
501
|
-
assert FolderRule.DEFAULT_BUILD_TARGETS == expected_targets
|
|
502
542
|
|
|
503
543
|
def test_disable_targets_with_enable_preview_targets(self):
|
|
504
|
-
|
|
505
|
-
disabled_target = PREVIEW_TARGETS[0] # Disable first preview target
|
|
506
|
-
|
|
544
|
+
disabled_target = 'esp32h2'
|
|
507
545
|
args = FindBuildArguments(enable_preview_targets=True, disable_targets=[disabled_target], paths=['.'])
|
|
508
546
|
|
|
509
|
-
expected_targets =
|
|
547
|
+
expected_targets = sorted(
|
|
548
|
+
[_t for _t in [*self.SUPPORTED_TARGETS, *self.PREVIEW_TARGETS] if _t != disabled_target]
|
|
549
|
+
)
|
|
510
550
|
assert args.default_build_targets == expected_targets
|
|
511
551
|
assert DEFAULT_BUILD_TARGETS.get() == expected_targets
|
|
512
|
-
assert len(DEFAULT_BUILD_TARGETS.get()) == len(ALL_TARGETS) - 1
|
|
513
552
|
|
|
514
553
|
def test_invalid_targets_filtering(self):
|
|
515
|
-
"""Test that invalid targets are filtered out and warnings are logged"""
|
|
516
554
|
invalid_targets = ['esp32', 'invalid_target', 'esp32s2', 'another_invalid']
|
|
517
|
-
|
|
518
555
|
args = FindBuildArguments(default_build_targets=invalid_targets, paths=['.'])
|
|
519
556
|
|
|
520
557
|
# Only valid targets should remain
|
|
@@ -525,25 +562,110 @@ class TestDefaultBuildTargetsContextVar:
|
|
|
525
562
|
def test_contextvar_isolation_between_instances(self):
|
|
526
563
|
"""Test that the contextvar behaves correctly across multiple argument instances"""
|
|
527
564
|
# First instance sets default_build_targets
|
|
528
|
-
FindBuildArguments(default_build_targets=['esp32', 'esp32s2'])
|
|
565
|
+
FindBuildArguments(default_build_targets=['esp32', 'esp32s2'], paths=['.'])
|
|
529
566
|
assert DEFAULT_BUILD_TARGETS.get() == ['esp32', 'esp32s2']
|
|
530
567
|
|
|
531
|
-
# Second instance sets enable_preview_targets
|
|
532
|
-
FindBuildArguments(enable_preview_targets=True)
|
|
533
|
-
assert DEFAULT_BUILD_TARGETS.get() ==
|
|
568
|
+
# Second instance sets enable_preview_targets (should combine with SUPPORTED_TARGETS)
|
|
569
|
+
FindBuildArguments(enable_preview_targets=True, paths=['.'])
|
|
570
|
+
assert DEFAULT_BUILD_TARGETS.get() == sorted(self.SUPPORTED_TARGETS + self.PREVIEW_TARGETS)
|
|
534
571
|
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
assert DEFAULT_BUILD_TARGETS.get() == SUPPORTED_TARGETS
|
|
572
|
+
FindBuildArguments(paths=['.'])
|
|
573
|
+
assert DEFAULT_BUILD_TARGETS.get() == self.SUPPORTED_TARGETS
|
|
538
574
|
|
|
539
575
|
def test_empty_default_build_targets(self):
|
|
540
|
-
"""Test behavior with empty default_build_targets list"""
|
|
541
576
|
args = FindBuildArguments(default_build_targets=[])
|
|
542
577
|
|
|
543
578
|
# Empty list is treated as falsy, so it falls back to default behavior
|
|
544
|
-
assert args.default_build_targets ==
|
|
545
|
-
assert DEFAULT_BUILD_TARGETS.get() == SUPPORTED_TARGETS
|
|
546
|
-
|
|
579
|
+
assert args.default_build_targets == self.SUPPORTED_TARGETS
|
|
580
|
+
assert DEFAULT_BUILD_TARGETS.get() == self.SUPPORTED_TARGETS
|
|
581
|
+
|
|
582
|
+
def test_additional_build_targets_option(self):
|
|
583
|
+
"""Test that --additional-build-targets option works correctly"""
|
|
584
|
+
additional_targets = ['esp32h2', 'esp32p4']
|
|
585
|
+
args = FindBuildArguments(additional_build_targets=additional_targets, paths=['.'])
|
|
586
|
+
|
|
587
|
+
expected_targets = sorted(self.SUPPORTED_TARGETS + additional_targets)
|
|
588
|
+
assert args.additional_build_targets == additional_targets
|
|
589
|
+
assert args.default_build_targets == expected_targets
|
|
590
|
+
assert DEFAULT_BUILD_TARGETS.get() == expected_targets
|
|
591
|
+
|
|
592
|
+
def test_additional_build_targets_with_existing_target(self):
|
|
593
|
+
existing_target = 'esp32' # From self.SUPPORTED_TARGETS
|
|
594
|
+
new_target = 'esp32h2' # From self.ALL_TARGETS but not in self.SUPPORTED_TARGETS
|
|
595
|
+
additional_targets = [existing_target, new_target]
|
|
596
|
+
|
|
597
|
+
args = FindBuildArguments(additional_build_targets=additional_targets, paths=['.'])
|
|
598
|
+
|
|
599
|
+
# Should only add the new target, not duplicate the existing one
|
|
600
|
+
expected_targets = sorted([*self.SUPPORTED_TARGETS, new_target])
|
|
601
|
+
assert args.additional_build_targets == additional_targets
|
|
602
|
+
assert args.default_build_targets == expected_targets
|
|
603
|
+
assert DEFAULT_BUILD_TARGETS.get() == expected_targets
|
|
604
|
+
|
|
605
|
+
def test_additional_build_targets_with_invalid_target(self):
|
|
606
|
+
invalid_targets = [
|
|
607
|
+
'esp32',
|
|
608
|
+
'invalid_target',
|
|
609
|
+
'esp32h2',
|
|
610
|
+
] # esp32 is already supported, invalid_target doesn't exist
|
|
611
|
+
|
|
612
|
+
args = FindBuildArguments(additional_build_targets=invalid_targets, paths=['.'])
|
|
613
|
+
|
|
614
|
+
# Should only add valid targets not already in SUPPORTED_TARGETS
|
|
615
|
+
expected_targets = sorted([*self.SUPPORTED_TARGETS, 'esp32h2'])
|
|
616
|
+
assert args.additional_build_targets == invalid_targets
|
|
617
|
+
assert args.default_build_targets == expected_targets
|
|
618
|
+
assert DEFAULT_BUILD_TARGETS.get() == expected_targets
|
|
619
|
+
|
|
620
|
+
def test_disable_targets_with_additional_build_targets(self):
|
|
621
|
+
additional_target = 'esp32h2' # From self.ALL_TARGETS but not in self.SUPPORTED_TARGETS
|
|
622
|
+
disabled_target = 'esp32' # From self.SUPPORTED_TARGETS
|
|
623
|
+
|
|
624
|
+
args = FindBuildArguments(
|
|
625
|
+
additional_build_targets=[additional_target], disable_targets=[disabled_target], paths=['.']
|
|
626
|
+
)
|
|
627
|
+
|
|
628
|
+
expected_targets = ['esp32h2', 'esp32s2']
|
|
629
|
+
assert args.default_build_targets == expected_targets
|
|
630
|
+
assert DEFAULT_BUILD_TARGETS.get() == expected_targets
|
|
631
|
+
|
|
632
|
+
def test_combination_default_and_additional(self):
|
|
633
|
+
args = FindBuildArguments(
|
|
634
|
+
default_build_targets=['esp32', 'esp32s2'], additional_build_targets=['esp32h2'], paths=['.']
|
|
635
|
+
)
|
|
636
|
+
|
|
637
|
+
expected_targets = ['esp32', 'esp32h2', 'esp32s2']
|
|
638
|
+
assert args.default_build_targets == expected_targets
|
|
639
|
+
assert DEFAULT_BUILD_TARGETS.get() == expected_targets
|
|
640
|
+
|
|
641
|
+
def test_combination_preview_and_additional(self):
|
|
642
|
+
args = FindBuildArguments(enable_preview_targets=True, additional_build_targets=['esp32p4'], paths=['.'])
|
|
643
|
+
|
|
644
|
+
# Should combine: SUPPORTED_TARGETS + PREVIEW_TARGETS + additional
|
|
645
|
+
# self.PREVIEW_TARGETS contains 'esp32p4', so it's not really additional
|
|
646
|
+
expected_targets = sorted(self.SUPPORTED_TARGETS + self.PREVIEW_TARGETS)
|
|
647
|
+
assert args.default_build_targets == expected_targets
|
|
648
|
+
assert DEFAULT_BUILD_TARGETS.get() == expected_targets
|
|
649
|
+
|
|
650
|
+
def test_combination_all_three_options(self):
|
|
651
|
+
args = FindBuildArguments(
|
|
652
|
+
default_build_targets=['esp32'],
|
|
653
|
+
enable_preview_targets=True,
|
|
654
|
+
additional_build_targets=['esp32p4', 'esp32c3'],
|
|
655
|
+
paths=['.'],
|
|
656
|
+
)
|
|
657
|
+
|
|
658
|
+
# Should combine: ['esp32'] + PREVIEW_TARGETS + ['esp32p4', 'esp32c3']
|
|
659
|
+
expected_targets = sorted({'esp32', *self.PREVIEW_TARGETS, 'esp32p4', 'esp32c3'})
|
|
660
|
+
assert args.default_build_targets == expected_targets
|
|
661
|
+
assert DEFAULT_BUILD_TARGETS.get() == expected_targets
|
|
662
|
+
|
|
663
|
+
def test_empty_additional_build_targets(self):
|
|
664
|
+
args = FindBuildArguments(additional_build_targets=[], paths=['.'])
|
|
665
|
+
|
|
666
|
+
assert args.additional_build_targets == []
|
|
667
|
+
assert args.default_build_targets == self.SUPPORTED_TARGETS
|
|
668
|
+
assert DEFAULT_BUILD_TARGETS.get() == self.SUPPORTED_TARGETS
|
|
547
669
|
|
|
548
670
|
|
|
549
671
|
def test_expand_vars(monkeypatch):
|
|
@@ -504,6 +504,7 @@ class TestFindWithSdkconfigFiles:
|
|
|
504
504
|
(tmp_path / 'test1' / 'sdkconfig.defaults').touch()
|
|
505
505
|
(tmp_path / 'test1' / 'sdkconfig.defaults_new').touch()
|
|
506
506
|
(tmp_path / 'test1' / 'sdkconfig.ci.foo').touch()
|
|
507
|
+
(tmp_path / 'test1' / 'sdkconfig.ci.foo.esp32p4').touch()
|
|
507
508
|
|
|
508
509
|
apps = find_apps(str(tmp_path / 'test1'), 'esp32', recursive=True, config_rules_str='sdkconfig.ci.*=')
|
|
509
510
|
assert len(apps) == 1
|
|
@@ -8,6 +8,7 @@ from pathlib import (
|
|
|
8
8
|
import pytest
|
|
9
9
|
|
|
10
10
|
from idf_build_apps.utils import (
|
|
11
|
+
BaseModel,
|
|
11
12
|
files_matches_patterns,
|
|
12
13
|
get_parallel_start_stop,
|
|
13
14
|
rmdir,
|
|
@@ -142,3 +143,19 @@ def test_files_matches_patterns(tmp_path):
|
|
|
142
143
|
os.chdir(temp_dir)
|
|
143
144
|
for f in matched_files:
|
|
144
145
|
assert files_matches_patterns(f, abs_pat)
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def test_base_model_hashable():
|
|
149
|
+
class Foo(BaseModel):
|
|
150
|
+
foo: str
|
|
151
|
+
bar: str
|
|
152
|
+
|
|
153
|
+
__EQ_IGNORE_FIELDS__ = ['bar']
|
|
154
|
+
|
|
155
|
+
a = Foo(foo='foo', bar='bar')
|
|
156
|
+
b = Foo(foo='foo', bar='rab')
|
|
157
|
+
|
|
158
|
+
assert a == b
|
|
159
|
+
assert hash(a) == hash(b)
|
|
160
|
+
s = {a, b}
|
|
161
|
+
assert len(s) == 1
|
|
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.12.2 → idf_build_apps-2.13.0}/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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|