idf-build-apps 2.6.0__py3-none-any.whl → 2.6.1__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 +1 -1
- idf_build_apps/args.py +25 -12
- idf_build_apps/constants.py +11 -56
- idf_build_apps/main.py +7 -5
- idf_build_apps/manifest/__init__.py +12 -1
- idf_build_apps/manifest/manifest.py +16 -8
- idf_build_apps/manifest/soc_header.py +3 -138
- idf_build_apps/vendors/pydantic_sources.py +3 -1
- {idf_build_apps-2.6.0.dist-info → idf_build_apps-2.6.1.dist-info}/METADATA +2 -1
- {idf_build_apps-2.6.0.dist-info → idf_build_apps-2.6.1.dist-info}/RECORD +13 -14
- idf_build_apps/manifest/if_parser.py +0 -240
- {idf_build_apps-2.6.0.dist-info → idf_build_apps-2.6.1.dist-info}/LICENSE +0 -0
- {idf_build_apps-2.6.0.dist-info → idf_build_apps-2.6.1.dist-info}/WHEEL +0 -0
- {idf_build_apps-2.6.0.dist-info → idf_build_apps-2.6.1.dist-info}/entry_points.txt +0 -0
idf_build_apps/__init__.py
CHANGED
idf_build_apps/args.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
|
1
|
+
# SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
|
|
2
2
|
# SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
|
|
4
4
|
import argparse
|
|
@@ -115,8 +115,9 @@ def get_meta(f: FieldInfo) -> t.Optional[FieldMetadata]:
|
|
|
115
115
|
class BaseArguments(BaseSettings):
|
|
116
116
|
"""Base settings class for all settings classes"""
|
|
117
117
|
|
|
118
|
+
CONFIG_FILE_PATH: t.ClassVar[t.Optional[Path]] = None
|
|
119
|
+
|
|
118
120
|
model_config = SettingsConfigDict(
|
|
119
|
-
toml_file=IDF_BUILD_APPS_TOML_FN,
|
|
120
121
|
# these below two are supported in pydantic 2.6
|
|
121
122
|
pyproject_toml_table_header=('tool', 'idf-build-apps'),
|
|
122
123
|
pyproject_toml_depth=sys.maxsize,
|
|
@@ -132,11 +133,15 @@ class BaseArguments(BaseSettings):
|
|
|
132
133
|
dotenv_settings: PydanticBaseSettingsSource, # noqa: ARG003
|
|
133
134
|
file_secret_settings: PydanticBaseSettingsSource, # noqa: ARG003
|
|
134
135
|
) -> t.Tuple[PydanticBaseSettingsSource, ...]:
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
TomlConfigSettingsSource(settings_cls),
|
|
138
|
-
PyprojectTomlConfigSettingsSource(settings_cls),
|
|
139
|
-
|
|
136
|
+
sources: t.Tuple[PydanticBaseSettingsSource, ...] = (init_settings,)
|
|
137
|
+
if cls.CONFIG_FILE_PATH is None:
|
|
138
|
+
sources += (TomlConfigSettingsSource(settings_cls, toml_file=Path(IDF_BUILD_APPS_TOML_FN)),)
|
|
139
|
+
sources += (PyprojectTomlConfigSettingsSource(settings_cls, toml_file=Path('pyproject.toml')),)
|
|
140
|
+
else:
|
|
141
|
+
sources += (TomlConfigSettingsSource(settings_cls, toml_file=Path(cls.CONFIG_FILE_PATH)),)
|
|
142
|
+
sources += (PyprojectTomlConfigSettingsSource(settings_cls, toml_file=Path(cls.CONFIG_FILE_PATH)),)
|
|
143
|
+
|
|
144
|
+
return sources
|
|
140
145
|
|
|
141
146
|
@field_validator('*', mode='before')
|
|
142
147
|
@classmethod
|
|
@@ -874,12 +879,20 @@ def add_args_to_obj_doc_as_params(argument_cls: t.Type[GlobalArguments], obj: t.
|
|
|
874
879
|
_obj.__doc__ = _doc_str
|
|
875
880
|
|
|
876
881
|
|
|
877
|
-
def apply_config_file(config_file: t.Optional[str]) -> None:
|
|
882
|
+
def apply_config_file(config_file: t.Optional[str] = None, reset: bool = False) -> None:
|
|
878
883
|
def _subclasses(klass: t.Type[T]) -> t.Set[t.Type[T]]:
|
|
879
884
|
return set(klass.__subclasses__()).union([s for c in klass.__subclasses__() for s in _subclasses(c)])
|
|
880
885
|
|
|
881
|
-
if
|
|
882
|
-
BaseArguments.
|
|
883
|
-
# modify all subclasses
|
|
886
|
+
if reset:
|
|
887
|
+
BaseArguments.CONFIG_FILE_PATH = None
|
|
884
888
|
for cls in _subclasses(BaseArguments):
|
|
885
|
-
cls.
|
|
889
|
+
cls.CONFIG_FILE_PATH = None
|
|
890
|
+
|
|
891
|
+
if config_file:
|
|
892
|
+
if os.path.isfile(config_file):
|
|
893
|
+
p = Path(config_file)
|
|
894
|
+
BaseArguments.CONFIG_FILE_PATH = p
|
|
895
|
+
for cls in _subclasses(BaseArguments):
|
|
896
|
+
cls.CONFIG_FILE_PATH = p
|
|
897
|
+
else:
|
|
898
|
+
LOGGER.warning(f'Config file {config_file} does not exist. Ignoring...')
|
idf_build_apps/constants.py
CHANGED
|
@@ -1,70 +1,25 @@
|
|
|
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
|
import enum
|
|
5
|
-
import importlib
|
|
6
|
-
import logging
|
|
7
5
|
import os
|
|
8
|
-
import re
|
|
9
|
-
import sys
|
|
10
|
-
import typing as t
|
|
11
6
|
|
|
12
|
-
|
|
13
|
-
to_version,
|
|
14
|
-
)
|
|
7
|
+
import esp_bool_parser
|
|
15
8
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
_idf_env = os.getenv('IDF_PATH') or ''
|
|
19
|
-
if not _idf_env:
|
|
20
|
-
LOGGER.warning('IDF_PATH environment variable is not set. Entering test mode...')
|
|
21
|
-
LOGGER.warning('- Setting IDF_PATH to current directory...')
|
|
22
|
-
IDF_PATH = os.path.abspath(_idf_env)
|
|
9
|
+
IDF_PATH = esp_bool_parser.IDF_PATH
|
|
23
10
|
IDF_PY = os.path.join(IDF_PATH, 'tools', 'idf.py')
|
|
24
11
|
IDF_SIZE_PY = os.path.join(IDF_PATH, 'tools', 'idf_size.py')
|
|
12
|
+
|
|
25
13
|
PROJECT_DESCRIPTION_JSON = 'project_description.json'
|
|
26
14
|
DEFAULT_SDKCONFIG = 'sdkconfig.defaults'
|
|
27
15
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
'- Set supported/preview targets to empty list... (ESP-IDF constants.py module not found under %s)',
|
|
36
|
-
_idf_py_actions,
|
|
37
|
-
)
|
|
38
|
-
_idf_py_constant_py = object() # type: ignore
|
|
39
|
-
SUPPORTED_TARGETS = getattr(_idf_py_constant_py, 'SUPPORTED_TARGETS', [])
|
|
40
|
-
PREVIEW_TARGETS = getattr(_idf_py_constant_py, 'PREVIEW_TARGETS', [])
|
|
41
|
-
ALL_TARGETS = SUPPORTED_TARGETS + PREVIEW_TARGETS
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
def _idf_version_from_cmake() -> t.Tuple[int, int, int]:
|
|
45
|
-
version_path = os.path.join(IDF_PATH, 'tools', 'cmake', 'version.cmake')
|
|
46
|
-
if not os.path.isfile(version_path):
|
|
47
|
-
LOGGER.warning('- Setting ESP-IDF version to 1.0.0... (ESP-IDF version.cmake not exists at %s)', version_path)
|
|
48
|
-
return 1, 0, 0
|
|
49
|
-
|
|
50
|
-
regex = re.compile(r'^\s*set\s*\(\s*IDF_VERSION_([A-Z]{5})\s+(\d+)')
|
|
51
|
-
ver = {}
|
|
52
|
-
try:
|
|
53
|
-
with open(version_path) as f:
|
|
54
|
-
for line in f:
|
|
55
|
-
m = regex.match(line)
|
|
56
|
-
|
|
57
|
-
if m:
|
|
58
|
-
ver[m.group(1)] = m.group(2)
|
|
59
|
-
|
|
60
|
-
return int(ver['MAJOR']), int(ver['MINOR']), int(ver['PATCH'])
|
|
61
|
-
except (KeyError, OSError):
|
|
62
|
-
raise ValueError(f'Cannot find ESP-IDF version in {version_path}')
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
IDF_VERSION_MAJOR, IDF_VERSION_MINOR, IDF_VERSION_PATCH = _idf_version_from_cmake()
|
|
66
|
-
|
|
67
|
-
IDF_VERSION = to_version(f'{IDF_VERSION_MAJOR}.{IDF_VERSION_MINOR}.{IDF_VERSION_PATCH}')
|
|
16
|
+
SUPPORTED_TARGETS = esp_bool_parser.SUPPORTED_TARGETS
|
|
17
|
+
PREVIEW_TARGETS = esp_bool_parser.PREVIEW_TARGETS
|
|
18
|
+
ALL_TARGETS = esp_bool_parser.ALL_TARGETS
|
|
19
|
+
IDF_VERSION_MAJOR = esp_bool_parser.IDF_VERSION_MAJOR
|
|
20
|
+
IDF_VERSION_MINOR = esp_bool_parser.IDF_VERSION_MINOR
|
|
21
|
+
IDF_VERSION_PATCH = esp_bool_parser.IDF_VERSION_PATCH
|
|
22
|
+
IDF_VERSION = esp_bool_parser.IDF_VERSION
|
|
68
23
|
|
|
69
24
|
|
|
70
25
|
class BuildStatus(str, enum.Enum):
|
idf_build_apps/main.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# PYTHON_ARGCOMPLETE_OK
|
|
2
2
|
|
|
3
|
-
# SPDX-FileCopyrightText: 2022-
|
|
3
|
+
# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
|
|
4
4
|
# SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
|
|
6
6
|
import argparse
|
|
@@ -68,7 +68,8 @@ def find_apps(
|
|
|
68
68
|
|
|
69
69
|
:return: list of found apps
|
|
70
70
|
"""
|
|
71
|
-
|
|
71
|
+
if config_file:
|
|
72
|
+
apply_config_file(config_file)
|
|
72
73
|
|
|
73
74
|
# compatible with old usage
|
|
74
75
|
## `preserve`
|
|
@@ -132,7 +133,8 @@ def build_apps(
|
|
|
132
133
|
|
|
133
134
|
:return: exit code
|
|
134
135
|
"""
|
|
135
|
-
|
|
136
|
+
if config_file:
|
|
137
|
+
apply_config_file(config_file)
|
|
136
138
|
|
|
137
139
|
# compatible with old usage
|
|
138
140
|
## `check_app_dependencies`
|
|
@@ -385,8 +387,8 @@ def main():
|
|
|
385
387
|
kwargs = vars(args)
|
|
386
388
|
action = kwargs.pop('action')
|
|
387
389
|
config_file = kwargs.pop('config_file')
|
|
388
|
-
|
|
389
|
-
|
|
390
|
+
if config_file:
|
|
391
|
+
apply_config_file(config_file)
|
|
390
392
|
|
|
391
393
|
if action == 'dump-manifest-sha':
|
|
392
394
|
arguments = DumpManifestShaArguments(**drop_none_kwargs(kwargs))
|
|
@@ -1,6 +1,17 @@
|
|
|
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
|
"""
|
|
5
5
|
Manifest file
|
|
6
6
|
"""
|
|
7
|
+
|
|
8
|
+
from esp_bool_parser import register_addition_attribute
|
|
9
|
+
|
|
10
|
+
from .manifest import FolderRule
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def folder_rule_attr(target, **kwargs):
|
|
14
|
+
return 1 if target in FolderRule.DEFAULT_BUILD_TARGETS else 0
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
register_addition_attribute('INCLUDE_DEFAULT', folder_rule_attr)
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
# SPDX-FileCopyrightText: 2022-
|
|
1
|
+
# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
|
|
2
2
|
# SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
import logging
|
|
4
4
|
import os
|
|
5
|
-
import pickle
|
|
6
5
|
import typing as t
|
|
7
6
|
from hashlib import sha512
|
|
8
7
|
|
|
8
|
+
from esp_bool_parser import BoolStmt, parse_bool_expr
|
|
9
9
|
from pyparsing import (
|
|
10
10
|
ParseException,
|
|
11
11
|
)
|
|
@@ -23,10 +23,6 @@ from ..utils import (
|
|
|
23
23
|
from ..yaml import (
|
|
24
24
|
parse,
|
|
25
25
|
)
|
|
26
|
-
from .if_parser import (
|
|
27
|
-
BOOL_EXPR,
|
|
28
|
-
BoolStmt,
|
|
29
|
-
)
|
|
30
26
|
|
|
31
27
|
LOGGER = logging.getLogger(__name__)
|
|
32
28
|
|
|
@@ -34,7 +30,8 @@ LOGGER = logging.getLogger(__name__)
|
|
|
34
30
|
class IfClause:
|
|
35
31
|
def __init__(self, stmt: str, temporary: bool = False, reason: t.Optional[str] = None) -> None:
|
|
36
32
|
try:
|
|
37
|
-
self.stmt: BoolStmt =
|
|
33
|
+
self.stmt: BoolStmt = parse_bool_expr(stmt)
|
|
34
|
+
self._stmt: str = stmt
|
|
38
35
|
except (ParseException, InvalidIfClause) as ex:
|
|
39
36
|
raise InvalidIfClause(f'Invalid if clause: {stmt}. {ex}')
|
|
40
37
|
|
|
@@ -51,6 +48,9 @@ class IfClause:
|
|
|
51
48
|
f' reason: lack of ci runners'
|
|
52
49
|
)
|
|
53
50
|
|
|
51
|
+
def __repr__(self):
|
|
52
|
+
return f'IfClause(stmt={self._stmt!r}, temporary={self.temporary!r}, reason={self.reason!r})'
|
|
53
|
+
|
|
54
54
|
def get_value(self, target: str, config_name: str) -> t.Any:
|
|
55
55
|
return self.stmt.get_value(target, config_name)
|
|
56
56
|
|
|
@@ -69,6 +69,14 @@ class SwitchClause:
|
|
|
69
69
|
return content
|
|
70
70
|
return self.default_clause
|
|
71
71
|
|
|
72
|
+
def __repr__(self) -> str:
|
|
73
|
+
return (
|
|
74
|
+
f'SwitchClause('
|
|
75
|
+
f'if_clauses={self.if_clauses!r}, '
|
|
76
|
+
f'contents={self.contents!r}, '
|
|
77
|
+
f'default_clause={self.default_clause!r})'
|
|
78
|
+
)
|
|
79
|
+
|
|
72
80
|
|
|
73
81
|
class FolderRule:
|
|
74
82
|
DEFAULT_BUILD_TARGETS = SUPPORTED_TARGETS
|
|
@@ -153,7 +161,7 @@ class FolderRule:
|
|
|
153
161
|
self.depends_components,
|
|
154
162
|
self.depends_filepatterns,
|
|
155
163
|
]:
|
|
156
|
-
sha.update(
|
|
164
|
+
sha.update(repr(obj).encode())
|
|
157
165
|
|
|
158
166
|
return sha.hexdigest()
|
|
159
167
|
|
|
@@ -1,141 +1,6 @@
|
|
|
1
|
-
# SPDX-FileCopyrightText:
|
|
1
|
+
# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
|
2
2
|
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
-
import logging
|
|
4
|
-
import os.path
|
|
5
|
-
import typing as t
|
|
6
|
-
from pathlib import (
|
|
7
|
-
Path,
|
|
8
|
-
)
|
|
9
3
|
|
|
10
|
-
|
|
11
|
-
CaselessLiteral,
|
|
12
|
-
Char,
|
|
13
|
-
Combine,
|
|
14
|
-
Group,
|
|
15
|
-
Literal,
|
|
16
|
-
MatchFirst,
|
|
17
|
-
OneOrMore,
|
|
18
|
-
Optional,
|
|
19
|
-
ParseException,
|
|
20
|
-
ParseResults,
|
|
21
|
-
QuotedString,
|
|
22
|
-
Word,
|
|
23
|
-
alphas,
|
|
24
|
-
hexnums,
|
|
25
|
-
nums,
|
|
26
|
-
)
|
|
4
|
+
import esp_bool_parser
|
|
27
5
|
|
|
28
|
-
|
|
29
|
-
ALL_TARGETS,
|
|
30
|
-
IDF_PATH,
|
|
31
|
-
)
|
|
32
|
-
|
|
33
|
-
LOGGER = logging.getLogger(__name__)
|
|
34
|
-
|
|
35
|
-
# Group for parsing literal suffix of a numbers, e.g. 100UL
|
|
36
|
-
_literal_symbol = Group(CaselessLiteral('L') | CaselessLiteral('U'))
|
|
37
|
-
_literal_suffix = OneOrMore(_literal_symbol)
|
|
38
|
-
|
|
39
|
-
# Define name
|
|
40
|
-
_name = Word(alphas, alphas + nums + '_')
|
|
41
|
-
|
|
42
|
-
# Define value, either a hex, int or a string
|
|
43
|
-
_hex_value = Combine(Literal('0x') + Word(hexnums) + Optional(_literal_suffix).suppress())('hex_value')
|
|
44
|
-
_str_value = QuotedString('"')('str_value')
|
|
45
|
-
_int_value = Combine(Optional('-') + Word(nums))('int_value') + ~Char('.') + Optional(_literal_suffix)('literal_suffix')
|
|
46
|
-
|
|
47
|
-
# Remove optional parenthesis around values
|
|
48
|
-
_value = Optional('(').suppress() + MatchFirst([_hex_value, _str_value, _int_value])('value') + Optional(')').suppress()
|
|
49
|
-
|
|
50
|
-
_define_expr = '#define' + Optional(_name)('name') + Optional(_value)
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
def get_defines(header_path: str) -> t.List[str]:
|
|
54
|
-
defines = []
|
|
55
|
-
LOGGER.debug('Reading macros from %s...', header_path)
|
|
56
|
-
with open(header_path) as f:
|
|
57
|
-
output = f.read()
|
|
58
|
-
|
|
59
|
-
for line in output.split('\n'):
|
|
60
|
-
line = line.strip()
|
|
61
|
-
if len(line):
|
|
62
|
-
defines.append(line)
|
|
63
|
-
|
|
64
|
-
return defines
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
def parse_define(define_line: str) -> ParseResults:
|
|
68
|
-
res = _define_expr.parseString(define_line)
|
|
69
|
-
|
|
70
|
-
return res
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
class SocHeader(dict):
|
|
74
|
-
CAPS_HEADER_FILEPATTERN = '*_caps.h'
|
|
75
|
-
|
|
76
|
-
def __init__(self, target: str) -> None:
|
|
77
|
-
if target != 'linux':
|
|
78
|
-
soc_header_dict = self._parse_soc_header(target)
|
|
79
|
-
else:
|
|
80
|
-
soc_header_dict = {}
|
|
81
|
-
|
|
82
|
-
super().__init__(**soc_header_dict)
|
|
83
|
-
|
|
84
|
-
@staticmethod
|
|
85
|
-
def _get_dirs_from_candidates(candidates: t.List[str]) -> t.List[str]:
|
|
86
|
-
dirs = []
|
|
87
|
-
for d in candidates:
|
|
88
|
-
if not os.path.isdir(d):
|
|
89
|
-
LOGGER.debug('folder "%s" not found. Skipping...', os.path.abspath(d))
|
|
90
|
-
else:
|
|
91
|
-
dirs.append(d)
|
|
92
|
-
|
|
93
|
-
return dirs
|
|
94
|
-
|
|
95
|
-
@classmethod
|
|
96
|
-
def _parse_soc_header(cls, target: str) -> t.Dict[str, t.Any]:
|
|
97
|
-
soc_headers_dirs = cls._get_dirs_from_candidates(
|
|
98
|
-
[
|
|
99
|
-
# master c5 mp
|
|
100
|
-
os.path.abspath(os.path.join(IDF_PATH, 'components', 'soc', target, 'mp', 'include', 'soc')),
|
|
101
|
-
# other branches
|
|
102
|
-
os.path.abspath(os.path.join(IDF_PATH, 'components', 'soc', target, 'include', 'soc')),
|
|
103
|
-
# release/v4.2
|
|
104
|
-
os.path.abspath(os.path.join(IDF_PATH, 'components', 'soc', 'soc', target, 'include', 'soc')),
|
|
105
|
-
]
|
|
106
|
-
)
|
|
107
|
-
esp_rom_headers_dirs = cls._get_dirs_from_candidates(
|
|
108
|
-
[
|
|
109
|
-
# master c5 mp
|
|
110
|
-
os.path.abspath(os.path.join(IDF_PATH, 'components', 'esp_rom', target, 'mp', target)),
|
|
111
|
-
# others
|
|
112
|
-
os.path.abspath(os.path.join(IDF_PATH, 'components', 'esp_rom', target)),
|
|
113
|
-
]
|
|
114
|
-
)
|
|
115
|
-
|
|
116
|
-
header_files: t.List[str] = []
|
|
117
|
-
for d in [*soc_headers_dirs, *esp_rom_headers_dirs]:
|
|
118
|
-
LOGGER.debug('Checking dir %s', d)
|
|
119
|
-
header_files += [str(p.resolve()) for p in Path(d).glob(cls.CAPS_HEADER_FILEPATTERN)]
|
|
120
|
-
|
|
121
|
-
output_dict = {}
|
|
122
|
-
for f in header_files:
|
|
123
|
-
LOGGER.debug('Checking header file %s', f)
|
|
124
|
-
for line in get_defines(f):
|
|
125
|
-
try:
|
|
126
|
-
res = parse_define(line)
|
|
127
|
-
except ParseException:
|
|
128
|
-
LOGGER.debug('Failed to parse: %s', line)
|
|
129
|
-
continue
|
|
130
|
-
|
|
131
|
-
if 'str_value' in res:
|
|
132
|
-
output_dict[res.name] = res.str_value
|
|
133
|
-
elif 'int_value' in res:
|
|
134
|
-
output_dict[res.name] = int(res.int_value)
|
|
135
|
-
elif 'hex_value' in res:
|
|
136
|
-
output_dict[res.name] = int(res.hex_value, 16)
|
|
137
|
-
|
|
138
|
-
return output_dict
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
SOC_HEADERS: t.Dict[str, SocHeader] = {target: SocHeader(target) for target in ALL_TARGETS}
|
|
6
|
+
SOC_HEADERS = esp_bool_parser.SOC_HEADERS
|
|
@@ -93,7 +93,9 @@ class TomlConfigSettingsSource(InitSettingsSource, ConfigFileSourceMixin):
|
|
|
93
93
|
:param depth: Number of directories up the tree to check of a pyproject.toml.
|
|
94
94
|
"""
|
|
95
95
|
if provided and Path(provided).is_file():
|
|
96
|
-
|
|
96
|
+
fp = provided.resolve()
|
|
97
|
+
print(f'Loading config file: {fp}')
|
|
98
|
+
return fp
|
|
97
99
|
|
|
98
100
|
rv = Path.cwd()
|
|
99
101
|
count = -1
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: idf-build-apps
|
|
3
|
-
Version: 2.6.
|
|
3
|
+
Version: 2.6.1
|
|
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
|
|
@@ -21,6 +21,7 @@ Requires-Dist: pydantic~=2.0
|
|
|
21
21
|
Requires-Dist: pydantic_settings
|
|
22
22
|
Requires-Dist: argcomplete>=3
|
|
23
23
|
Requires-Dist: typing-extensions; python_version < '3.11'
|
|
24
|
+
Requires-Dist: esp-bool-parser>=0.1.2,<1
|
|
24
25
|
Requires-Dist: sphinx ; extra == "doc"
|
|
25
26
|
Requires-Dist: sphinx-rtd-theme ; extra == "doc"
|
|
26
27
|
Requires-Dist: sphinx_copybutton ; extra == "doc"
|
|
@@ -1,28 +1,27 @@
|
|
|
1
|
-
idf_build_apps/__init__.py,sha256=
|
|
1
|
+
idf_build_apps/__init__.py,sha256=vUpvuUfhUex6RVt7a3vpSTczJJkHz8qSc2HqbwFW_80,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=zB08ctBXFz1UkPv4r7kE6E6sBezCFrrzt99HKRDiRTA,34821
|
|
5
5
|
idf_build_apps/autocompletions.py,sha256=g-bx0pzXoFKI0VQqftkHyGVWN6MLjuFOdozeuAf45yo,2138
|
|
6
|
-
idf_build_apps/constants.py,sha256=
|
|
6
|
+
idf_build_apps/constants.py,sha256=HU0rtKqhvLj9nMsy6XvyQMjMEBliNi9xaS2D8CQEPsE,2421
|
|
7
7
|
idf_build_apps/finder.py,sha256=hY6uSMB2s65MqMKIDBSHABOfa93mOLT7x5hlMxC43EQ,5794
|
|
8
8
|
idf_build_apps/log.py,sha256=pyvT7N4MWzGjIXph5mThQCGBiSt53RNPW0WrFfLr0Kw,2650
|
|
9
|
-
idf_build_apps/main.py,sha256=
|
|
9
|
+
idf_build_apps/main.py,sha256=SZauvC_DNEsl1Twc5xQxHSSPt8sgYsNOZjN4UjHk0gQ,16569
|
|
10
10
|
idf_build_apps/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
11
|
idf_build_apps/session_args.py,sha256=2WDTy40IFAc0KQ57HaeBcYj_k10eUXRKkDOWLrFCaHY,2985
|
|
12
12
|
idf_build_apps/utils.py,sha256=s4D8P7QA17XcaCUQ_EoiNOW_VpU3cPQgiZVV9KQ8I30,10171
|
|
13
13
|
idf_build_apps/junit/__init__.py,sha256=IxvdaS6eSXp7kZxRuXqyZyGxuA_A1nOW1jF1HMi8Gns,231
|
|
14
14
|
idf_build_apps/junit/report.py,sha256=T7dVU3Sz5tqjfbcFW7wjsb65PDH6C2HFf73ePJqBhMs,6555
|
|
15
15
|
idf_build_apps/junit/utils.py,sha256=NXZxQD4tdbSVKjKMNx1kO2H3IoEiysXkDoDjLEf1RO8,1303
|
|
16
|
-
idf_build_apps/manifest/__init__.py,sha256=
|
|
17
|
-
idf_build_apps/manifest/
|
|
18
|
-
idf_build_apps/manifest/
|
|
19
|
-
idf_build_apps/manifest/soc_header.py,sha256=8vlsAjNsTxxb85RFJxVJTe11ealNQ8n5abUdNuC9ULo,4369
|
|
16
|
+
idf_build_apps/manifest/__init__.py,sha256=LYGR9doEKGPEdsJPuHnmJmV-qw2kuAipV0bodkhY_JE,399
|
|
17
|
+
idf_build_apps/manifest/manifest.py,sha256=5BIzNzGAk0w5qOCTMGsmvKcN4DQLwUi6JVGt2G4JKQs,14793
|
|
18
|
+
idf_build_apps/manifest/soc_header.py,sha256=_F6H5-HP6ateAqKUGlRGH-SUtQ8NJ1RI0hBeCFvsDYA,172
|
|
20
19
|
idf_build_apps/vendors/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
21
|
-
idf_build_apps/vendors/pydantic_sources.py,sha256=
|
|
20
|
+
idf_build_apps/vendors/pydantic_sources.py,sha256=cO316vq4wAw51O1-KsYz8jrhiI_lkCghiPCYyH0Ghik,4487
|
|
22
21
|
idf_build_apps/yaml/__init__.py,sha256=W-3z5no07RQ6eYKGyOAPA8Z2CLiMPob8DD91I4URjrA,162
|
|
23
22
|
idf_build_apps/yaml/parser.py,sha256=b3LvogO6do-eJPRsYzT-8xk8AT2MnXpLCzQutJqyC7M,2128
|
|
24
|
-
idf_build_apps-2.6.
|
|
25
|
-
idf_build_apps-2.6.
|
|
26
|
-
idf_build_apps-2.6.
|
|
27
|
-
idf_build_apps-2.6.
|
|
28
|
-
idf_build_apps-2.6.
|
|
23
|
+
idf_build_apps-2.6.1.dist-info/entry_points.txt,sha256=3pVUirUEsb6jsDRikkQWNUt4hqLK2ci1HvW_Vf8b6uE,59
|
|
24
|
+
idf_build_apps-2.6.1.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
|
|
25
|
+
idf_build_apps-2.6.1.dist-info/WHEEL,sha256=CpUCUxeHQbRN5UGRQHYRJorO5Af-Qy_fHMctcQ8DSGI,82
|
|
26
|
+
idf_build_apps-2.6.1.dist-info/METADATA,sha256=z7cnY1oC-PXymCxVYo7_Ao5LvPnFyzblDYVE_sUavbI,4693
|
|
27
|
+
idf_build_apps-2.6.1.dist-info/RECORD,,
|
|
@@ -1,240 +0,0 @@
|
|
|
1
|
-
# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
|
2
|
-
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
-
import operator
|
|
4
|
-
import os
|
|
5
|
-
from ast import (
|
|
6
|
-
literal_eval,
|
|
7
|
-
)
|
|
8
|
-
from typing import (
|
|
9
|
-
Any,
|
|
10
|
-
)
|
|
11
|
-
|
|
12
|
-
from packaging.version import (
|
|
13
|
-
Version,
|
|
14
|
-
)
|
|
15
|
-
from pyparsing import (
|
|
16
|
-
Keyword,
|
|
17
|
-
Literal,
|
|
18
|
-
MatchFirst,
|
|
19
|
-
ParseResults,
|
|
20
|
-
QuotedString,
|
|
21
|
-
Suppress,
|
|
22
|
-
Word,
|
|
23
|
-
alphas,
|
|
24
|
-
delimitedList,
|
|
25
|
-
hexnums,
|
|
26
|
-
infixNotation,
|
|
27
|
-
nums,
|
|
28
|
-
opAssoc,
|
|
29
|
-
)
|
|
30
|
-
|
|
31
|
-
from ..constants import (
|
|
32
|
-
IDF_VERSION,
|
|
33
|
-
IDF_VERSION_MAJOR,
|
|
34
|
-
IDF_VERSION_MINOR,
|
|
35
|
-
IDF_VERSION_PATCH,
|
|
36
|
-
)
|
|
37
|
-
from ..utils import (
|
|
38
|
-
InvalidIfClause,
|
|
39
|
-
InvalidInput,
|
|
40
|
-
to_version,
|
|
41
|
-
)
|
|
42
|
-
from .soc_header import (
|
|
43
|
-
SOC_HEADERS,
|
|
44
|
-
)
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
class Stmt:
|
|
48
|
-
"""
|
|
49
|
-
Statement
|
|
50
|
-
"""
|
|
51
|
-
|
|
52
|
-
def get_value(self, target: str, config_name: str) -> Any:
|
|
53
|
-
"""
|
|
54
|
-
Lazy calculated. All subclasses of `Stmt` should implement this function.
|
|
55
|
-
|
|
56
|
-
:param target: ESP-IDF target
|
|
57
|
-
:type target: str
|
|
58
|
-
:param config_name: config name
|
|
59
|
-
:type target: str
|
|
60
|
-
:return: the value of the statement
|
|
61
|
-
"""
|
|
62
|
-
raise NotImplementedError('Please implement this function in sub classes')
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
class ChipAttr(Stmt):
|
|
66
|
-
"""
|
|
67
|
-
Attributes defined in SOC Header Files and other keywords as followed:
|
|
68
|
-
|
|
69
|
-
- IDF_TARGET: target
|
|
70
|
-
- INCLUDE_DEFAULT: take the default build targets into account or not
|
|
71
|
-
- IDF_VERSION_MAJOR: major version of ESP-IDF
|
|
72
|
-
- IDF_VERSION_MINOR: minor version of ESP-IDF
|
|
73
|
-
- IDF_VERSION_PATCH: patch version of ESP-IDF
|
|
74
|
-
- CONFIG_NAME: config name defined in the config rules
|
|
75
|
-
"""
|
|
76
|
-
|
|
77
|
-
def __init__(self, t: ParseResults):
|
|
78
|
-
self.attr: str = t[0]
|
|
79
|
-
|
|
80
|
-
def get_value(self, target: str, config_name: str) -> Any:
|
|
81
|
-
from .manifest import FolderRule # lazy-load
|
|
82
|
-
|
|
83
|
-
if self.attr == 'IDF_TARGET':
|
|
84
|
-
return target
|
|
85
|
-
|
|
86
|
-
if self.attr == 'INCLUDE_DEFAULT':
|
|
87
|
-
return 1 if target in FolderRule.DEFAULT_BUILD_TARGETS else 0
|
|
88
|
-
|
|
89
|
-
if self.attr == 'IDF_VERSION':
|
|
90
|
-
return IDF_VERSION
|
|
91
|
-
|
|
92
|
-
if self.attr == 'IDF_VERSION_MAJOR':
|
|
93
|
-
return IDF_VERSION_MAJOR
|
|
94
|
-
|
|
95
|
-
if self.attr == 'IDF_VERSION_MINOR':
|
|
96
|
-
return IDF_VERSION_MINOR
|
|
97
|
-
|
|
98
|
-
if self.attr == 'IDF_VERSION_PATCH':
|
|
99
|
-
return IDF_VERSION_PATCH
|
|
100
|
-
|
|
101
|
-
if self.attr == 'CONFIG_NAME':
|
|
102
|
-
return config_name
|
|
103
|
-
|
|
104
|
-
if self.attr in SOC_HEADERS[target]:
|
|
105
|
-
return SOC_HEADERS[target][self.attr]
|
|
106
|
-
|
|
107
|
-
# for non-keyword cap words, check if it is defined in the environment variables
|
|
108
|
-
if self.attr in os.environ:
|
|
109
|
-
return os.environ[self.attr]
|
|
110
|
-
|
|
111
|
-
return 0 # default return 0 as false
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
class Integer(Stmt):
|
|
115
|
-
def __init__(self, t: ParseResults):
|
|
116
|
-
self.expr: str = t[0]
|
|
117
|
-
|
|
118
|
-
def get_value(self, target: str, config_name: str) -> Any: # noqa: ARG002
|
|
119
|
-
return literal_eval(self.expr)
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
class String(Stmt):
|
|
123
|
-
def __init__(self, t: ParseResults):
|
|
124
|
-
self.expr: str = t[0]
|
|
125
|
-
|
|
126
|
-
def get_value(self, target: str, config_name: str) -> Any: # noqa: ARG002
|
|
127
|
-
return literal_eval(f'"{self.expr}"') # double quotes is swallowed by QuotedString
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
class List_(Stmt):
|
|
131
|
-
def __init__(self, t: ParseResults):
|
|
132
|
-
self.expr = t
|
|
133
|
-
|
|
134
|
-
def get_value(self, target: str, config_name: str) -> Any:
|
|
135
|
-
return [item.get_value(target, config_name) for item in self.expr]
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
class BoolStmt(Stmt):
|
|
139
|
-
_OP_DICT = {
|
|
140
|
-
'==': operator.eq,
|
|
141
|
-
'!=': operator.ne,
|
|
142
|
-
'>': operator.gt,
|
|
143
|
-
'>=': operator.ge,
|
|
144
|
-
'<': operator.lt,
|
|
145
|
-
'<=': operator.le,
|
|
146
|
-
'not in': lambda x, y: x not in y,
|
|
147
|
-
'in': lambda x, y: x in y,
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
def __init__(self, t: ParseResults):
|
|
151
|
-
self.left: Stmt = t[0]
|
|
152
|
-
self.comparison: str = t[1]
|
|
153
|
-
self.right: Stmt = t[2]
|
|
154
|
-
|
|
155
|
-
def get_value(self, target: str, config_name: str) -> Any:
|
|
156
|
-
_l = self.left.get_value(target, config_name)
|
|
157
|
-
_r = self.right.get_value(target, config_name)
|
|
158
|
-
|
|
159
|
-
if self.comparison not in ['in', 'not in']:
|
|
160
|
-
# will use version comparison if any of the operands is a Version
|
|
161
|
-
if any(isinstance(x, Version) for x in [_l, _r]):
|
|
162
|
-
_l = to_version(_l)
|
|
163
|
-
_r = to_version(_r)
|
|
164
|
-
else:
|
|
165
|
-
# use str for "in" and "not in" operator
|
|
166
|
-
if isinstance(_l, Version):
|
|
167
|
-
_l = str(_l)
|
|
168
|
-
if isinstance(_r, Version):
|
|
169
|
-
_r = str(_r)
|
|
170
|
-
|
|
171
|
-
if self.comparison in self._OP_DICT:
|
|
172
|
-
return self._OP_DICT[self.comparison](_l, _r)
|
|
173
|
-
|
|
174
|
-
raise InvalidInput(f'Unsupported comparison operator: "{self.comparison}"')
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
class BoolExpr(Stmt):
|
|
178
|
-
pass
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
def _and(_l, _r):
|
|
182
|
-
return _l and _r
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
def _or(_l, _r):
|
|
186
|
-
return _l or _r
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
class BoolOrAnd(BoolExpr):
|
|
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
|
-
)
|
|
196
|
-
self.left: BoolStmt = t[0][0]
|
|
197
|
-
self.right: BoolStmt = t[0][2]
|
|
198
|
-
|
|
199
|
-
if t[0][1] == 'and':
|
|
200
|
-
self.operation = _and
|
|
201
|
-
if t[0][1] == 'or':
|
|
202
|
-
self.operation = _or
|
|
203
|
-
|
|
204
|
-
def get_value(self, target: str, config_name: str) -> Any:
|
|
205
|
-
return self.operation(self.left.get_value(target, config_name), self.right.get_value(target, config_name))
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
CAP_WORD = Word(alphas.upper(), nums + alphas.upper() + '_').setParseAction(ChipAttr)
|
|
209
|
-
|
|
210
|
-
DECIMAL_NUMBER = Word(nums)
|
|
211
|
-
HEX_NUMBER = Literal('0x') + Word(hexnums)
|
|
212
|
-
INTEGER = (HEX_NUMBER | DECIMAL_NUMBER).setParseAction(Integer)
|
|
213
|
-
|
|
214
|
-
STRING = QuotedString('"').setParseAction(String)
|
|
215
|
-
|
|
216
|
-
LIST = Suppress('[') + delimitedList(INTEGER | STRING).setParseAction(List_) + Suppress(']')
|
|
217
|
-
|
|
218
|
-
BOOL_OPERAND = CAP_WORD | INTEGER | STRING | LIST
|
|
219
|
-
|
|
220
|
-
EQ = Keyword('==').setParseAction(lambda t: t[0])
|
|
221
|
-
NE = Keyword('!=').setParseAction(lambda t: t[0])
|
|
222
|
-
LE = Keyword('<=').setParseAction(lambda t: t[0])
|
|
223
|
-
LT = Keyword('<').setParseAction(lambda t: t[0])
|
|
224
|
-
GE = Keyword('>=').setParseAction(lambda t: t[0])
|
|
225
|
-
GT = Keyword('>').setParseAction(lambda t: t[0])
|
|
226
|
-
NOT_IN = Keyword('not in').setParseAction(lambda t: t[0])
|
|
227
|
-
IN = Keyword('in').setParseAction(lambda t: t[0])
|
|
228
|
-
|
|
229
|
-
BOOL_STMT = BOOL_OPERAND + (EQ | NE | LE | LT | GE | GT | NOT_IN | IN) + BOOL_OPERAND
|
|
230
|
-
BOOL_STMT.setParseAction(BoolStmt)
|
|
231
|
-
|
|
232
|
-
AND = Keyword('and')
|
|
233
|
-
OR = Keyword('or')
|
|
234
|
-
|
|
235
|
-
BOOL_EXPR = infixNotation(
|
|
236
|
-
BOOL_STMT,
|
|
237
|
-
[
|
|
238
|
-
(MatchFirst((AND, OR)), 2, opAssoc.LEFT, BoolOrAnd),
|
|
239
|
-
],
|
|
240
|
-
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|