idf-build-apps 2.5.2__py3-none-any.whl → 2.6.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- idf_build_apps/__init__.py +2 -2
- idf_build_apps/args.py +85 -53
- idf_build_apps/finder.py +1 -0
- idf_build_apps/junit/utils.py +1 -1
- idf_build_apps/manifest/soc_header.py +1 -1
- idf_build_apps/py.typed +0 -0
- idf_build_apps/vendors/pydantic_sources.py +51 -34
- {idf_build_apps-2.5.2.dist-info → idf_build_apps-2.6.0.dist-info}/METADATA +4 -3
- {idf_build_apps-2.5.2.dist-info → idf_build_apps-2.6.0.dist-info}/RECORD +12 -11
- {idf_build_apps-2.5.2.dist-info → idf_build_apps-2.6.0.dist-info}/WHEEL +1 -1
- {idf_build_apps-2.5.2.dist-info → idf_build_apps-2.6.0.dist-info}/LICENSE +0 -0
- {idf_build_apps-2.5.2.dist-info → idf_build_apps-2.6.0.dist-info}/entry_points.txt +0 -0
idf_build_apps/__init__.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# SPDX-FileCopyrightText: 2022-
|
|
1
|
+
# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
|
|
2
2
|
# SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
|
|
4
4
|
"""
|
|
@@ -8,7 +8,7 @@ Tools for building ESP-IDF related apps.
|
|
|
8
8
|
# ruff: noqa: E402
|
|
9
9
|
# avoid circular imports
|
|
10
10
|
|
|
11
|
-
__version__ = '2.
|
|
11
|
+
__version__ = '2.6.0'
|
|
12
12
|
|
|
13
13
|
from .session_args import (
|
|
14
14
|
SessionArgs,
|
idf_build_apps/args.py
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
import argparse
|
|
5
5
|
import enum
|
|
6
|
+
import glob
|
|
6
7
|
import inspect
|
|
7
8
|
import logging
|
|
8
9
|
import os
|
|
@@ -26,7 +27,7 @@ from pydantic_settings import (
|
|
|
26
27
|
from typing_extensions import Concatenate, ParamSpec
|
|
27
28
|
|
|
28
29
|
from . import SESSION_ARGS, App, setup_logging
|
|
29
|
-
from .constants import ALL_TARGETS
|
|
30
|
+
from .constants import ALL_TARGETS, IDF_BUILD_APPS_TOML_FN
|
|
30
31
|
from .manifest.manifest import FolderRule, Manifest
|
|
31
32
|
from .utils import InvalidCommand, files_matches_patterns, semicolon_separated_str_to_list, to_absolute_path, to_list
|
|
32
33
|
from .vendors.pydantic_sources import PyprojectTomlConfigSettingsSource, TomlConfigSettingsSource
|
|
@@ -36,6 +37,7 @@ LOGGER = logging.getLogger(__name__)
|
|
|
36
37
|
|
|
37
38
|
class ValidateMethod(str, enum.Enum):
|
|
38
39
|
TO_LIST = 'to_list'
|
|
40
|
+
EXPAND_VARS = 'expand_vars'
|
|
39
41
|
|
|
40
42
|
|
|
41
43
|
@dataclass
|
|
@@ -114,10 +116,11 @@ class BaseArguments(BaseSettings):
|
|
|
114
116
|
"""Base settings class for all settings classes"""
|
|
115
117
|
|
|
116
118
|
model_config = SettingsConfigDict(
|
|
117
|
-
toml_file=
|
|
119
|
+
toml_file=IDF_BUILD_APPS_TOML_FN,
|
|
120
|
+
# these below two are supported in pydantic 2.6
|
|
118
121
|
pyproject_toml_table_header=('tool', 'idf-build-apps'),
|
|
119
122
|
pyproject_toml_depth=sys.maxsize,
|
|
120
|
-
extra='ignore',
|
|
123
|
+
extra='ignore', # we're supporting pydantic <2.6 as well, so we ignore extra fields
|
|
121
124
|
)
|
|
122
125
|
|
|
123
126
|
@classmethod
|
|
@@ -142,8 +145,15 @@ class BaseArguments(BaseSettings):
|
|
|
142
145
|
f = cls.model_fields[info.field_name]
|
|
143
146
|
meta = get_meta(f)
|
|
144
147
|
if meta and meta.validate_method:
|
|
145
|
-
|
|
146
|
-
|
|
148
|
+
for method in meta.validate_method:
|
|
149
|
+
if method == ValidateMethod.TO_LIST:
|
|
150
|
+
v = to_list(v)
|
|
151
|
+
elif method == ValidateMethod.EXPAND_VARS:
|
|
152
|
+
v = os.path.expandvars(v)
|
|
153
|
+
else:
|
|
154
|
+
raise NotImplementedError(f'Unknown validate method: {method}')
|
|
155
|
+
|
|
156
|
+
return v
|
|
147
157
|
|
|
148
158
|
return v
|
|
149
159
|
|
|
@@ -155,19 +165,19 @@ class GlobalArguments(BaseArguments):
|
|
|
155
165
|
action='count',
|
|
156
166
|
),
|
|
157
167
|
description='Verbosity level. By default set to WARNING. Specify -v for INFO, -vv for DEBUG',
|
|
158
|
-
default=0,
|
|
168
|
+
default=0, # type: ignore
|
|
159
169
|
)
|
|
160
170
|
log_file: t.Optional[str] = field(
|
|
161
171
|
None,
|
|
162
172
|
description='Path to the log file, if not specified logs will be printed to stderr',
|
|
163
|
-
default=None,
|
|
173
|
+
default=None, # type: ignore
|
|
164
174
|
)
|
|
165
175
|
no_color: bool = field(
|
|
166
176
|
FieldMetadata(
|
|
167
177
|
action='store_true',
|
|
168
178
|
),
|
|
169
179
|
description='Disable colored output',
|
|
170
|
-
default=False,
|
|
180
|
+
default=False, # type: ignore
|
|
171
181
|
)
|
|
172
182
|
|
|
173
183
|
def model_post_init(self, __context: Any) -> None:
|
|
@@ -189,13 +199,24 @@ class DependencyDrivenBuildArguments(GlobalArguments):
|
|
|
189
199
|
),
|
|
190
200
|
description='Path to the manifest files which contains the build test rules of the apps',
|
|
191
201
|
validation_alias=AliasChoices('manifest_files', 'manifest_file'),
|
|
192
|
-
default=None,
|
|
202
|
+
default=None, # type: ignore
|
|
203
|
+
)
|
|
204
|
+
manifest_filepatterns: t.Optional[t.List[str]] = field(
|
|
205
|
+
FieldMetadata(
|
|
206
|
+
validate_method=[ValidateMethod.TO_LIST],
|
|
207
|
+
nargs='+',
|
|
208
|
+
),
|
|
209
|
+
description='space-separated list of file patterns to search for the manifest files. '
|
|
210
|
+
'The matched files will be loaded as the manifest files.',
|
|
211
|
+
default=None, # type: ignore
|
|
193
212
|
)
|
|
194
213
|
manifest_rootpath: str = field(
|
|
195
|
-
|
|
214
|
+
FieldMetadata(
|
|
215
|
+
validate_method=[ValidateMethod.EXPAND_VARS],
|
|
216
|
+
),
|
|
196
217
|
description='Root path to resolve the relative paths defined in the manifest files. '
|
|
197
|
-
'By default set to the current directory',
|
|
198
|
-
default=os.curdir,
|
|
218
|
+
'By default set to the current directory. Support environment variables.',
|
|
219
|
+
default=os.curdir, # type: ignore
|
|
199
220
|
)
|
|
200
221
|
modified_components: t.Optional[t.List[str]] = field(
|
|
201
222
|
FieldMetadata(
|
|
@@ -205,7 +226,7 @@ class DependencyDrivenBuildArguments(GlobalArguments):
|
|
|
205
226
|
description='semicolon-separated list of modified components. '
|
|
206
227
|
'If set to "", the value would be considered as None. '
|
|
207
228
|
'If set to ";", the value would be considered as an empty list.',
|
|
208
|
-
default=None,
|
|
229
|
+
default=None, # type: ignore
|
|
209
230
|
)
|
|
210
231
|
modified_files: t.Optional[t.List[str]] = field(
|
|
211
232
|
FieldMetadata(
|
|
@@ -215,7 +236,7 @@ class DependencyDrivenBuildArguments(GlobalArguments):
|
|
|
215
236
|
description='semicolon-separated list of modified files. '
|
|
216
237
|
'If set to "", the value would be considered as None. '
|
|
217
238
|
'If set to ";", the value would be considered as an empty list.',
|
|
218
|
-
default=None,
|
|
239
|
+
default=None, # type: ignore
|
|
219
240
|
)
|
|
220
241
|
deactivate_dependency_driven_build_by_components: t.Optional[t.List[str]] = field(
|
|
221
242
|
FieldMetadata(
|
|
@@ -237,7 +258,7 @@ class DependencyDrivenBuildArguments(GlobalArguments):
|
|
|
237
258
|
validation_alias=AliasChoices(
|
|
238
259
|
'deactivate_dependency_driven_build_by_components', 'ignore_app_dependencies_components'
|
|
239
260
|
),
|
|
240
|
-
default=None,
|
|
261
|
+
default=None, # type: ignore
|
|
241
262
|
)
|
|
242
263
|
deactivate_dependency_driven_build_by_filepatterns: t.Optional[t.List[str]] = field(
|
|
243
264
|
FieldMetadata(
|
|
@@ -259,26 +280,37 @@ class DependencyDrivenBuildArguments(GlobalArguments):
|
|
|
259
280
|
validation_alias=AliasChoices(
|
|
260
281
|
'deactivate_dependency_driven_build_by_filepatterns', 'ignore_app_dependencies_filepatterns'
|
|
261
282
|
),
|
|
262
|
-
default=None,
|
|
283
|
+
default=None, # type: ignore
|
|
263
284
|
)
|
|
264
285
|
check_manifest_rules: bool = field(
|
|
265
286
|
FieldMetadata(
|
|
266
287
|
action='store_true',
|
|
267
288
|
),
|
|
268
289
|
description='Check if all folders defined in the manifest files exist. Fail if not',
|
|
269
|
-
default=False,
|
|
290
|
+
default=False, # type: ignore
|
|
270
291
|
)
|
|
271
292
|
compare_manifest_sha_filepath: t.Optional[str] = field(
|
|
272
293
|
None,
|
|
273
294
|
description='Path to the file containing the hash of the manifest rules. '
|
|
274
295
|
'Compare the hash with the current manifest rules. '
|
|
275
296
|
'All matched apps will be built if the corresponding manifest rule is modified',
|
|
276
|
-
default=None,
|
|
297
|
+
default=None, # type: ignore
|
|
277
298
|
)
|
|
278
299
|
|
|
279
300
|
def model_post_init(self, __context: Any) -> None:
|
|
280
301
|
super().model_post_init(__context)
|
|
281
302
|
|
|
303
|
+
if self.manifest_filepatterns:
|
|
304
|
+
matched_paths = set()
|
|
305
|
+
for pat in [to_absolute_path(p, self.manifest_rootpath) for p in self.manifest_filepatterns]:
|
|
306
|
+
matched_paths.update(glob.glob(str(pat), recursive=True))
|
|
307
|
+
|
|
308
|
+
if matched_paths:
|
|
309
|
+
if self.manifest_files:
|
|
310
|
+
self.manifest_files.extend(matched_paths)
|
|
311
|
+
else:
|
|
312
|
+
self.manifest_files = list(matched_paths)
|
|
313
|
+
|
|
282
314
|
Manifest.CHECK_MANIFEST_RULES = self.check_manifest_rules
|
|
283
315
|
if self.manifest_files:
|
|
284
316
|
App.MANIFEST = Manifest.from_files(
|
|
@@ -356,28 +388,28 @@ class FindBuildArguments(DependencyDrivenBuildArguments):
|
|
|
356
388
|
nargs='*',
|
|
357
389
|
),
|
|
358
390
|
description='Paths to the directories containing the apps. By default set to the current directory',
|
|
359
|
-
default=os.curdir,
|
|
391
|
+
default=os.curdir, # type: ignore
|
|
360
392
|
)
|
|
361
393
|
target: str = field(
|
|
362
394
|
FieldMetadata(
|
|
363
395
|
shorthand='-t',
|
|
364
396
|
),
|
|
365
397
|
description='Filter the apps by target. By default set to "all"',
|
|
366
|
-
default='all',
|
|
398
|
+
default='all', # type: ignore
|
|
367
399
|
)
|
|
368
400
|
build_system: t.Union[str, t.Type[App]] = field(
|
|
369
401
|
FieldMetadata(
|
|
370
402
|
choices=['cmake', 'make'],
|
|
371
403
|
),
|
|
372
404
|
description='Filter the apps by build system. By default set to "cmake"',
|
|
373
|
-
default='cmake',
|
|
405
|
+
default='cmake', # type: ignore
|
|
374
406
|
)
|
|
375
407
|
recursive: bool = field(
|
|
376
408
|
FieldMetadata(
|
|
377
409
|
action='store_true',
|
|
378
410
|
),
|
|
379
411
|
description='Search for apps recursively under the specified paths',
|
|
380
|
-
default=False,
|
|
412
|
+
default=False, # type: ignore
|
|
381
413
|
)
|
|
382
414
|
exclude: t.Optional[t.List[str]] = field(
|
|
383
415
|
FieldMetadata(
|
|
@@ -386,20 +418,20 @@ class FindBuildArguments(DependencyDrivenBuildArguments):
|
|
|
386
418
|
),
|
|
387
419
|
description='Ignore the specified directories while searching recursively',
|
|
388
420
|
validation_alias=AliasChoices('exclude', 'exclude_list'),
|
|
389
|
-
default=None,
|
|
421
|
+
default=None, # type: ignore
|
|
390
422
|
)
|
|
391
423
|
work_dir: t.Optional[str] = field(
|
|
392
424
|
None,
|
|
393
425
|
description='Copy the app to this directory before building. '
|
|
394
426
|
'By default set to the app directory. Can expand placeholders',
|
|
395
|
-
default=None,
|
|
427
|
+
default=None, # type: ignore
|
|
396
428
|
)
|
|
397
429
|
build_dir: str = field(
|
|
398
430
|
None,
|
|
399
431
|
description='Build directory for the app. By default set to "build". '
|
|
400
432
|
'When set to relative path, it will be treated as relative to the app directory. '
|
|
401
433
|
'Can expand placeholders',
|
|
402
|
-
default='build',
|
|
434
|
+
default='build', # type: ignore
|
|
403
435
|
)
|
|
404
436
|
build_log_filename: t.Optional[str] = field(
|
|
405
437
|
FieldMetadata(
|
|
@@ -407,7 +439,7 @@ class FindBuildArguments(DependencyDrivenBuildArguments):
|
|
|
407
439
|
),
|
|
408
440
|
description='Log filename under the build directory instead of stdout. Can expand placeholders',
|
|
409
441
|
validation_alias=AliasChoices('build_log_filename', 'build_log'),
|
|
410
|
-
default=None,
|
|
442
|
+
default=None, # type: ignore
|
|
411
443
|
)
|
|
412
444
|
size_json_filename: t.Optional[str] = field(
|
|
413
445
|
FieldMetadata(
|
|
@@ -415,7 +447,7 @@ class FindBuildArguments(DependencyDrivenBuildArguments):
|
|
|
415
447
|
),
|
|
416
448
|
description='`idf.py size` output file under the build directory when specified. ' 'Can expand placeholders',
|
|
417
449
|
validation_alias=AliasChoices('size_json_filename', 'size_file'),
|
|
418
|
-
default=None,
|
|
450
|
+
default=None, # type: ignore
|
|
419
451
|
)
|
|
420
452
|
config_rules: t.Optional[t.List[str]] = field(
|
|
421
453
|
FieldMetadata(
|
|
@@ -433,31 +465,31 @@ class FindBuildArguments(DependencyDrivenBuildArguments):
|
|
|
433
465
|
'FILEPATTERN is the filename of the sdkconfig file with a single wildcard character (*). '
|
|
434
466
|
'The NAME is the value matched by the wildcard',
|
|
435
467
|
validation_alias=AliasChoices('config_rules', 'config_rules_str', 'config'),
|
|
436
|
-
default=None,
|
|
468
|
+
default=None, # type: ignore
|
|
437
469
|
)
|
|
438
470
|
override_sdkconfig_items: t.Optional[str] = field(
|
|
439
471
|
None,
|
|
440
472
|
description='A comma-separated list of key=value pairs to override the sdkconfig items',
|
|
441
|
-
default=None,
|
|
473
|
+
default=None, # type: ignore
|
|
442
474
|
)
|
|
443
475
|
override_sdkconfig_files: t.Optional[str] = field(
|
|
444
476
|
None,
|
|
445
477
|
description='A comma-separated list of sdkconfig files to override the sdkconfig items. '
|
|
446
478
|
'When set to relative path, it will be treated as relative to the current directory',
|
|
447
|
-
default=None,
|
|
479
|
+
default=None, # type: ignore
|
|
448
480
|
)
|
|
449
481
|
sdkconfig_defaults: t.Optional[str] = field(
|
|
450
482
|
None,
|
|
451
483
|
description='A semicolon-separated list of sdkconfig files passed to `idf.py -DSDKCONFIG_DEFAULTS`. '
|
|
452
484
|
'SDKCONFIG_DEFAULTS environment variable is used when not specified',
|
|
453
|
-
default=os.getenv('SDKCONFIG_DEFAULTS', None),
|
|
485
|
+
default=os.getenv('SDKCONFIG_DEFAULTS', None), # type: ignore
|
|
454
486
|
)
|
|
455
487
|
check_warnings: bool = field(
|
|
456
488
|
FieldMetadata(
|
|
457
489
|
action='store_true',
|
|
458
490
|
),
|
|
459
491
|
description='Check for warnings in the build output. Fail if any warnings are found',
|
|
460
|
-
default=False,
|
|
492
|
+
default=False, # type: ignore
|
|
461
493
|
)
|
|
462
494
|
default_build_targets: t.Optional[t.List[str]] = field(
|
|
463
495
|
FieldMetadata(
|
|
@@ -466,7 +498,7 @@ class FindBuildArguments(DependencyDrivenBuildArguments):
|
|
|
466
498
|
),
|
|
467
499
|
description='space-separated list of the default enabled build targets for the apps. '
|
|
468
500
|
'When not specified, the default value is the targets listed by `idf.py --list-targets`',
|
|
469
|
-
default=None,
|
|
501
|
+
default=None, # type: ignore
|
|
470
502
|
)
|
|
471
503
|
enable_preview_targets: bool = field(
|
|
472
504
|
FieldMetadata(
|
|
@@ -474,28 +506,28 @@ class FindBuildArguments(DependencyDrivenBuildArguments):
|
|
|
474
506
|
),
|
|
475
507
|
description='When enabled, the default build targets will be set to all apps, '
|
|
476
508
|
'including the preview targets. As the targets defined in `idf.py --list-targets --preview`',
|
|
477
|
-
default=False,
|
|
509
|
+
default=False, # type: ignore
|
|
478
510
|
)
|
|
479
511
|
include_skipped_apps: bool = field(
|
|
480
512
|
FieldMetadata(
|
|
481
513
|
action='store_true',
|
|
482
514
|
),
|
|
483
515
|
description='Include the skipped apps in the output, together with the enabled ones',
|
|
484
|
-
default=False,
|
|
516
|
+
default=False, # type: ignore
|
|
485
517
|
)
|
|
486
518
|
include_disabled_apps: bool = field(
|
|
487
519
|
FieldMetadata(
|
|
488
520
|
action='store_true',
|
|
489
521
|
),
|
|
490
522
|
description='Include the disabled apps in the output, together with the enabled ones',
|
|
491
|
-
default=False,
|
|
523
|
+
default=False, # type: ignore
|
|
492
524
|
)
|
|
493
525
|
include_all_apps: bool = field(
|
|
494
526
|
FieldMetadata(
|
|
495
527
|
action='store_true',
|
|
496
528
|
),
|
|
497
529
|
description='Include skipped, and disabled apps in the output, together with the enabled ones',
|
|
498
|
-
default=False,
|
|
530
|
+
default=False, # type: ignore
|
|
499
531
|
)
|
|
500
532
|
|
|
501
533
|
def model_post_init(self, __context: Any) -> None:
|
|
@@ -536,7 +568,7 @@ class FindArguments(FindBuildArguments):
|
|
|
536
568
|
shorthand='-o',
|
|
537
569
|
),
|
|
538
570
|
description='Record the found apps to the specified file instead of stdout',
|
|
539
|
-
default=None,
|
|
571
|
+
default=None, # type: ignore
|
|
540
572
|
)
|
|
541
573
|
output_format: str = field(
|
|
542
574
|
FieldMetadata(
|
|
@@ -545,7 +577,7 @@ class FindArguments(FindBuildArguments):
|
|
|
545
577
|
description='Output format of the found apps. '
|
|
546
578
|
'In "raw" format, each line is a json string serialized from the app model. '
|
|
547
579
|
'In "json" format, the output is a json list of the serialized app models',
|
|
548
|
-
default='raw',
|
|
580
|
+
default='raw', # type: ignore
|
|
549
581
|
)
|
|
550
582
|
|
|
551
583
|
def model_post_init(self, __context: Any) -> None:
|
|
@@ -566,7 +598,7 @@ class BuildArguments(FindBuildArguments):
|
|
|
566
598
|
action='store_true',
|
|
567
599
|
),
|
|
568
600
|
description='Enable verbose output of the build system',
|
|
569
|
-
default=False,
|
|
601
|
+
default=False, # type: ignore
|
|
570
602
|
)
|
|
571
603
|
parallel_count: int = field(
|
|
572
604
|
FieldMetadata(
|
|
@@ -576,7 +608,7 @@ class BuildArguments(FindBuildArguments):
|
|
|
576
608
|
'Specified together with --parallel-index. '
|
|
577
609
|
'The given apps will be divided into parallel_count parts, '
|
|
578
610
|
'and the current run will build the parallel_index-th part',
|
|
579
|
-
default=1,
|
|
611
|
+
default=1, # type: ignore
|
|
580
612
|
)
|
|
581
613
|
parallel_index: int = field(
|
|
582
614
|
FieldMetadata(
|
|
@@ -586,28 +618,28 @@ class BuildArguments(FindBuildArguments):
|
|
|
586
618
|
'Specified together with --parallel-count. '
|
|
587
619
|
'The given apps will be divided into parallel_count parts, '
|
|
588
620
|
'and the current run will build the parallel_index-th part',
|
|
589
|
-
default=1,
|
|
621
|
+
default=1, # type: ignore
|
|
590
622
|
)
|
|
591
623
|
dry_run: bool = field(
|
|
592
624
|
FieldMetadata(
|
|
593
625
|
action='store_true',
|
|
594
626
|
),
|
|
595
627
|
description='Skip the actual build, only print the build process',
|
|
596
|
-
default=False,
|
|
628
|
+
default=False, # type: ignore
|
|
597
629
|
)
|
|
598
630
|
keep_going: bool = field(
|
|
599
631
|
FieldMetadata(
|
|
600
632
|
action='store_true',
|
|
601
633
|
),
|
|
602
634
|
description='Continue building the next app when the current build fails',
|
|
603
|
-
default=False,
|
|
635
|
+
default=False, # type: ignore
|
|
604
636
|
)
|
|
605
637
|
no_preserve: bool = field(
|
|
606
638
|
FieldMetadata(
|
|
607
639
|
action='store_true',
|
|
608
640
|
),
|
|
609
641
|
description='Do not preserve the build directory after a successful build',
|
|
610
|
-
default=False,
|
|
642
|
+
default=False, # type: ignore
|
|
611
643
|
)
|
|
612
644
|
ignore_warning_strs: t.Optional[t.List[str]] = field(
|
|
613
645
|
FieldMetadata(
|
|
@@ -620,7 +652,7 @@ class BuildArguments(FindBuildArguments):
|
|
|
620
652
|
description='space-separated list of patterns. '
|
|
621
653
|
'Ignore the warnings in the build output that match the patterns',
|
|
622
654
|
validation_alias=AliasChoices('ignore_warning_strs', 'ignore_warning_str'),
|
|
623
|
-
default=None,
|
|
655
|
+
default=None, # type: ignore
|
|
624
656
|
)
|
|
625
657
|
ignore_warning_files: t.Optional[t.List[t.Union[str, TextIOWrapper]]] = field(
|
|
626
658
|
FieldMetadata(
|
|
@@ -635,14 +667,14 @@ class BuildArguments(FindBuildArguments):
|
|
|
635
667
|
),
|
|
636
668
|
description='Path to the files containing the patterns to ignore the warnings in the build output',
|
|
637
669
|
validation_alias=AliasChoices('ignore_warning_files', 'ignore_warning_file'),
|
|
638
|
-
default=None,
|
|
670
|
+
default=None, # type: ignore
|
|
639
671
|
)
|
|
640
672
|
copy_sdkconfig: bool = field(
|
|
641
673
|
FieldMetadata(
|
|
642
674
|
action='store_true',
|
|
643
675
|
),
|
|
644
676
|
description='Copy the sdkconfig file to the build directory',
|
|
645
|
-
default=False,
|
|
677
|
+
default=False, # type: ignore
|
|
646
678
|
)
|
|
647
679
|
|
|
648
680
|
# Attrs that support placeholders
|
|
@@ -654,7 +686,7 @@ class BuildArguments(FindBuildArguments):
|
|
|
654
686
|
description='Record size json filepath of the built apps to the specified file. '
|
|
655
687
|
'Each line is a json string. Can expand placeholders @p',
|
|
656
688
|
validation_alias=AliasChoices('collect_size_info_filename', 'collect_size_info'),
|
|
657
|
-
default=None,
|
|
689
|
+
default=None, # type: ignore
|
|
658
690
|
exclude=True, # computed field is used
|
|
659
691
|
)
|
|
660
692
|
collect_app_info_filename: t.Optional[str] = field(
|
|
@@ -665,7 +697,7 @@ class BuildArguments(FindBuildArguments):
|
|
|
665
697
|
description='Record serialized app model of the built apps to the specified file. '
|
|
666
698
|
'Each line is a json string. Can expand placeholders @p',
|
|
667
699
|
validation_alias=AliasChoices('collect_app_info_filename', 'collect_app_info'),
|
|
668
|
-
default=None,
|
|
700
|
+
default=None, # type: ignore
|
|
669
701
|
exclude=True, # computed field is used
|
|
670
702
|
)
|
|
671
703
|
junitxml_filename: t.Optional[str] = field(
|
|
@@ -675,7 +707,7 @@ class BuildArguments(FindBuildArguments):
|
|
|
675
707
|
),
|
|
676
708
|
description='Path to the junitxml file to record the build results. Can expand placeholder @p',
|
|
677
709
|
validation_alias=AliasChoices('junitxml_filename', 'junitxml'),
|
|
678
|
-
default=None,
|
|
710
|
+
default=None, # type: ignore
|
|
679
711
|
exclude=True, # computed field is used
|
|
680
712
|
)
|
|
681
713
|
# used for expanding placeholders
|
|
@@ -732,7 +764,7 @@ class DumpManifestShaArguments(GlobalArguments):
|
|
|
732
764
|
required=True,
|
|
733
765
|
),
|
|
734
766
|
description='Path to the manifest files which contains the build test rules of the apps',
|
|
735
|
-
default=None,
|
|
767
|
+
default=None, # type: ignore
|
|
736
768
|
)
|
|
737
769
|
|
|
738
770
|
output: t.Optional[str] = field(
|
|
@@ -741,7 +773,7 @@ class DumpManifestShaArguments(GlobalArguments):
|
|
|
741
773
|
required=True,
|
|
742
774
|
),
|
|
743
775
|
description='Path to the output file to record the sha256 hash of the manifest rules',
|
|
744
|
-
default=None,
|
|
776
|
+
default=None, # type: ignore
|
|
745
777
|
)
|
|
746
778
|
|
|
747
779
|
def model_post_init(self, __context: Any) -> None:
|
idf_build_apps/finder.py
CHANGED
|
@@ -50,6 +50,7 @@ def _get_apps_from_path(
|
|
|
50
50
|
|
|
51
51
|
# for unknown ones, we keep them to the build stage to judge
|
|
52
52
|
if _app.build_status == BuildStatus.SKIPPED:
|
|
53
|
+
LOGGER.debug('=> Skipped. Reason: %s', _app.build_comment or 'Unknown')
|
|
53
54
|
return args.include_skipped_apps
|
|
54
55
|
|
|
55
56
|
return True
|
idf_build_apps/junit/utils.py
CHANGED
|
@@ -42,7 +42,7 @@ _name = Word(alphas, alphas + nums + '_')
|
|
|
42
42
|
# Define value, either a hex, int or a string
|
|
43
43
|
_hex_value = Combine(Literal('0x') + Word(hexnums) + Optional(_literal_suffix).suppress())('hex_value')
|
|
44
44
|
_str_value = QuotedString('"')('str_value')
|
|
45
|
-
_int_value = Word(nums)('int_value') + ~Char('.') + Optional(_literal_suffix)('literal_suffix')
|
|
45
|
+
_int_value = Combine(Optional('-') + Word(nums))('int_value') + ~Char('.') + Optional(_literal_suffix)('literal_suffix')
|
|
46
46
|
|
|
47
47
|
# Remove optional parenthesis around values
|
|
48
48
|
_value = Optional('(').suppress() + MatchFirst([_hex_value, _str_value, _int_value])('value') + Optional(')').suppress()
|
idf_build_apps/py.typed
ADDED
|
File without changes
|
|
@@ -14,6 +14,7 @@ Modifications:
|
|
|
14
14
|
- use toml instead of tomli when python < 3.11
|
|
15
15
|
- stop using global variables
|
|
16
16
|
- fix some warnings
|
|
17
|
+
- recursively find TOML file.
|
|
17
18
|
"""
|
|
18
19
|
|
|
19
20
|
import os
|
|
@@ -25,8 +26,10 @@ from typing import Any, Dict, List, Optional, Tuple, Type, Union
|
|
|
25
26
|
from pydantic_settings import InitSettingsSource
|
|
26
27
|
from pydantic_settings.main import BaseSettings
|
|
27
28
|
|
|
29
|
+
from idf_build_apps.constants import IDF_BUILD_APPS_TOML_FN
|
|
30
|
+
|
|
28
31
|
PathType = Union[Path, str, List[Union[Path, str]], Tuple[Union[Path, str], ...]]
|
|
29
|
-
DEFAULT_PATH
|
|
32
|
+
DEFAULT_PATH = Path('')
|
|
30
33
|
|
|
31
34
|
|
|
32
35
|
class ConfigFileSourceMixin(ABC):
|
|
@@ -43,7 +46,7 @@ class ConfigFileSourceMixin(ABC):
|
|
|
43
46
|
return kwargs
|
|
44
47
|
|
|
45
48
|
@abstractmethod
|
|
46
|
-
def _read_file(self, path: Path) -> Dict[str, Any]:
|
|
49
|
+
def _read_file(self, path: Optional[Path]) -> Dict[str, Any]:
|
|
47
50
|
pass
|
|
48
51
|
|
|
49
52
|
|
|
@@ -55,24 +58,59 @@ class TomlConfigSettingsSource(InitSettingsSource, ConfigFileSourceMixin):
|
|
|
55
58
|
def __init__(
|
|
56
59
|
self,
|
|
57
60
|
settings_cls: Type[BaseSettings],
|
|
58
|
-
toml_file: Optional[
|
|
61
|
+
toml_file: Optional[Path] = DEFAULT_PATH,
|
|
59
62
|
):
|
|
60
|
-
self.toml_file_path =
|
|
63
|
+
self.toml_file_path = self._pick_toml_file(
|
|
64
|
+
toml_file,
|
|
65
|
+
settings_cls.model_config.get('pyproject_toml_depth', sys.maxsize),
|
|
66
|
+
IDF_BUILD_APPS_TOML_FN,
|
|
67
|
+
)
|
|
61
68
|
self.toml_data = self._read_files(self.toml_file_path)
|
|
62
69
|
super().__init__(settings_cls, self.toml_data)
|
|
63
70
|
|
|
64
|
-
def _read_file(self,
|
|
71
|
+
def _read_file(self, path: Optional[Path]) -> Dict[str, Any]:
|
|
72
|
+
if not path or not path.is_file():
|
|
73
|
+
return {}
|
|
74
|
+
|
|
65
75
|
if sys.version_info < (3, 11):
|
|
66
76
|
import toml
|
|
67
77
|
|
|
68
|
-
with open(
|
|
78
|
+
with open(path) as toml_file:
|
|
69
79
|
return toml.load(toml_file)
|
|
70
80
|
else:
|
|
71
81
|
import tomllib
|
|
72
82
|
|
|
73
|
-
with open(
|
|
83
|
+
with open(path, 'rb') as toml_file:
|
|
74
84
|
return tomllib.load(toml_file)
|
|
75
85
|
|
|
86
|
+
@staticmethod
|
|
87
|
+
def _pick_toml_file(provided: Optional[Path], depth: int, filename: str) -> Optional[Path]:
|
|
88
|
+
"""
|
|
89
|
+
Pick a file path to use. If a file path is provided, use it. Otherwise, search up the directory tree for a
|
|
90
|
+
file with the given name.
|
|
91
|
+
|
|
92
|
+
:param provided: Explicit path provided when instantiating this class.
|
|
93
|
+
:param depth: Number of directories up the tree to check of a pyproject.toml.
|
|
94
|
+
"""
|
|
95
|
+
if provided and Path(provided).is_file():
|
|
96
|
+
return provided.resolve()
|
|
97
|
+
|
|
98
|
+
rv = Path.cwd()
|
|
99
|
+
count = -1
|
|
100
|
+
while count < depth:
|
|
101
|
+
if str(rv) == rv.root:
|
|
102
|
+
break
|
|
103
|
+
|
|
104
|
+
fp = rv / filename
|
|
105
|
+
if fp.is_file():
|
|
106
|
+
print(f'Loading config file: {fp}')
|
|
107
|
+
return fp
|
|
108
|
+
|
|
109
|
+
rv = rv.parent
|
|
110
|
+
count += 1
|
|
111
|
+
|
|
112
|
+
return None
|
|
113
|
+
|
|
76
114
|
|
|
77
115
|
class PyprojectTomlConfigSettingsSource(TomlConfigSettingsSource):
|
|
78
116
|
"""
|
|
@@ -84,37 +122,16 @@ class PyprojectTomlConfigSettingsSource(TomlConfigSettingsSource):
|
|
|
84
122
|
settings_cls: Type[BaseSettings],
|
|
85
123
|
toml_file: Optional[Path] = None,
|
|
86
124
|
) -> None:
|
|
87
|
-
self.toml_file_path = self.
|
|
88
|
-
toml_file,
|
|
125
|
+
self.toml_file_path = self._pick_toml_file(
|
|
126
|
+
toml_file,
|
|
127
|
+
settings_cls.model_config.get('pyproject_toml_depth', sys.maxsize),
|
|
128
|
+
'pyproject.toml',
|
|
89
129
|
)
|
|
90
130
|
self.toml_table_header: Tuple[str, ...] = settings_cls.model_config.get(
|
|
91
|
-
'pyproject_toml_table_header',
|
|
131
|
+
'pyproject_toml_table_header',
|
|
132
|
+
('tool', 'idf-build-apps'),
|
|
92
133
|
)
|
|
93
134
|
self.toml_data = self._read_files(self.toml_file_path)
|
|
94
135
|
for key in self.toml_table_header:
|
|
95
136
|
self.toml_data = self.toml_data.get(key, {})
|
|
96
137
|
super(TomlConfigSettingsSource, self).__init__(settings_cls, self.toml_data)
|
|
97
|
-
|
|
98
|
-
@staticmethod
|
|
99
|
-
def _pick_pyproject_toml_file(provided: Optional[Path], depth: int) -> Path:
|
|
100
|
-
"""Pick a `pyproject.toml` file path to use.
|
|
101
|
-
|
|
102
|
-
Args:
|
|
103
|
-
provided: Explicit path provided when instantiating this class.
|
|
104
|
-
depth: Number of directories up the tree to check of a pyproject.toml.
|
|
105
|
-
|
|
106
|
-
"""
|
|
107
|
-
if provided:
|
|
108
|
-
return provided.resolve()
|
|
109
|
-
rv = Path.cwd() / 'pyproject.toml'
|
|
110
|
-
count = 0
|
|
111
|
-
if not rv.is_file():
|
|
112
|
-
child = rv.parent.parent / 'pyproject.toml'
|
|
113
|
-
while count < depth:
|
|
114
|
-
if child.is_file():
|
|
115
|
-
return child
|
|
116
|
-
if str(child.parent) == rv.root:
|
|
117
|
-
break # end discovery after checking system root once
|
|
118
|
-
child = child.parent.parent / 'pyproject.toml'
|
|
119
|
-
count += 1
|
|
120
|
-
return rv
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
2
|
Name: idf-build-apps
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.6.0
|
|
4
4
|
Summary: Tools for building ESP-IDF related apps.
|
|
5
5
|
Author-email: Fu Hanxi <fuhanxi@espressif.com>
|
|
6
6
|
Requires-Python: >=3.7
|
|
@@ -27,9 +27,10 @@ Requires-Dist: sphinx_copybutton ; extra == "doc"
|
|
|
27
27
|
Requires-Dist: myst-parser ; extra == "doc"
|
|
28
28
|
Requires-Dist: sphinxcontrib-mermaid ; extra == "doc"
|
|
29
29
|
Requires-Dist: sphinx-argparse ; extra == "doc"
|
|
30
|
+
Requires-Dist: sphinx-tabs ; extra == "doc"
|
|
30
31
|
Requires-Dist: pytest ; extra == "test"
|
|
31
32
|
Requires-Dist: pytest-cov ; extra == "test"
|
|
32
|
-
Project-URL: changelog, https://github.com/espressif/idf-build-apps/blob/
|
|
33
|
+
Project-URL: changelog, https://github.com/espressif/idf-build-apps/blob/main/CHANGELOG.md
|
|
33
34
|
Project-URL: documentation, https://docs.espressif.com/projects/idf-build-apps
|
|
34
35
|
Project-URL: homepage, https://github.com/espressif/idf-build-apps
|
|
35
36
|
Project-URL: repository, https://github.com/espressif/idf-build-apps
|
|
@@ -1,27 +1,28 @@
|
|
|
1
|
-
idf_build_apps/__init__.py,sha256=
|
|
1
|
+
idf_build_apps/__init__.py,sha256=VMMqqRp30Golk7dqGCARNL8mR9oZaz86HOXoySoXvIY,650
|
|
2
2
|
idf_build_apps/__main__.py,sha256=8E-5xHm2MlRun0L88XJleNh5U50dpE0Q1nK5KqomA7I,182
|
|
3
3
|
idf_build_apps/app.py,sha256=F-MKOsaz7cJ0H2wsEE4gpO4kkkEdkyFmIZBHDoM2qgs,37359
|
|
4
|
-
idf_build_apps/args.py,sha256=
|
|
4
|
+
idf_build_apps/args.py,sha256=7-rphv1hhbjJRfE_agBUyQbJaiUhsjsBo6C3eDmug2k,34101
|
|
5
5
|
idf_build_apps/autocompletions.py,sha256=g-bx0pzXoFKI0VQqftkHyGVWN6MLjuFOdozeuAf45yo,2138
|
|
6
6
|
idf_build_apps/constants.py,sha256=07ve2FtWuLBuc_6LFzbs1XncB1VNi9HJUqGjQQauRNM,3952
|
|
7
|
-
idf_build_apps/finder.py,sha256=
|
|
7
|
+
idf_build_apps/finder.py,sha256=hY6uSMB2s65MqMKIDBSHABOfa93mOLT7x5hlMxC43EQ,5794
|
|
8
8
|
idf_build_apps/log.py,sha256=pyvT7N4MWzGjIXph5mThQCGBiSt53RNPW0WrFfLr0Kw,2650
|
|
9
9
|
idf_build_apps/main.py,sha256=Z_hetbOavgCJZQPaP01_jx57fR1w0DefiFz0J2cCwp0,16498
|
|
10
|
+
idf_build_apps/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
11
|
idf_build_apps/session_args.py,sha256=2WDTy40IFAc0KQ57HaeBcYj_k10eUXRKkDOWLrFCaHY,2985
|
|
11
12
|
idf_build_apps/utils.py,sha256=s4D8P7QA17XcaCUQ_EoiNOW_VpU3cPQgiZVV9KQ8I30,10171
|
|
12
13
|
idf_build_apps/junit/__init__.py,sha256=IxvdaS6eSXp7kZxRuXqyZyGxuA_A1nOW1jF1HMi8Gns,231
|
|
13
14
|
idf_build_apps/junit/report.py,sha256=T7dVU3Sz5tqjfbcFW7wjsb65PDH6C2HFf73ePJqBhMs,6555
|
|
14
|
-
idf_build_apps/junit/utils.py,sha256=
|
|
15
|
+
idf_build_apps/junit/utils.py,sha256=NXZxQD4tdbSVKjKMNx1kO2H3IoEiysXkDoDjLEf1RO8,1303
|
|
15
16
|
idf_build_apps/manifest/__init__.py,sha256=Q2-cb3ngNjnl6_zWhUfzZZB10f_-Rv2JYNck3Lk7UkQ,133
|
|
16
17
|
idf_build_apps/manifest/if_parser.py,sha256=AAEyYPgcBWL2ToCmcvhx3fl8ebYdC5-LMvvDkYtWn8o,6546
|
|
17
18
|
idf_build_apps/manifest/manifest.py,sha256=6F6Nt93eaoBOHlGHZtv2hHT8Zw0HmJf0d_MESlgye6M,14478
|
|
18
|
-
idf_build_apps/manifest/soc_header.py,sha256=
|
|
19
|
+
idf_build_apps/manifest/soc_header.py,sha256=8vlsAjNsTxxb85RFJxVJTe11ealNQ8n5abUdNuC9ULo,4369
|
|
19
20
|
idf_build_apps/vendors/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
20
|
-
idf_build_apps/vendors/pydantic_sources.py,sha256=
|
|
21
|
+
idf_build_apps/vendors/pydantic_sources.py,sha256=2e-zA_aHe7NVXMoPKU_0Z9Lg9lw80TFWQ-2PZf10FMs,4419
|
|
21
22
|
idf_build_apps/yaml/__init__.py,sha256=W-3z5no07RQ6eYKGyOAPA8Z2CLiMPob8DD91I4URjrA,162
|
|
22
23
|
idf_build_apps/yaml/parser.py,sha256=b3LvogO6do-eJPRsYzT-8xk8AT2MnXpLCzQutJqyC7M,2128
|
|
23
|
-
idf_build_apps-2.
|
|
24
|
-
idf_build_apps-2.
|
|
25
|
-
idf_build_apps-2.
|
|
26
|
-
idf_build_apps-2.
|
|
27
|
-
idf_build_apps-2.
|
|
24
|
+
idf_build_apps-2.6.0.dist-info/entry_points.txt,sha256=3pVUirUEsb6jsDRikkQWNUt4hqLK2ci1HvW_Vf8b6uE,59
|
|
25
|
+
idf_build_apps-2.6.0.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
|
|
26
|
+
idf_build_apps-2.6.0.dist-info/WHEEL,sha256=CpUCUxeHQbRN5UGRQHYRJorO5Af-Qy_fHMctcQ8DSGI,82
|
|
27
|
+
idf_build_apps-2.6.0.dist-info/METADATA,sha256=StRvId-xGrePTaC0FjO9O58mazLMSD0EZGrPDSOOxvs,4652
|
|
28
|
+
idf_build_apps-2.6.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|