idf-build-apps 2.6.0__py3-none-any.whl → 2.6.2__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.
@@ -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.6.0'
11
+ __version__ = '2.6.2'
12
12
 
13
13
  from .session_args import (
14
14
  SessionArgs,
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
- return (
136
- init_settings,
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 config_file:
882
- BaseArguments.model_config['toml_file'] = str(config_file)
883
- # modify all subclasses
886
+ if reset:
887
+ BaseArguments.CONFIG_FILE_PATH = None
884
888
  for cls in _subclasses(BaseArguments):
885
- cls.model_config['toml_file'] = str(config_file)
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...')
@@ -1,70 +1,25 @@
1
- # SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
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
- from .utils import (
13
- to_version,
14
- )
7
+ import esp_bool_parser
15
8
 
16
- LOGGER = logging.getLogger(__name__)
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
- _idf_py_actions = os.path.join(IDF_PATH, 'tools', 'idf_py_actions')
30
- sys.path.append(_idf_py_actions)
31
- try:
32
- _idf_py_constant_py = importlib.import_module('constants')
33
- except ModuleNotFoundError:
34
- LOGGER.warning(
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-2024 Espressif Systems (Shanghai) CO LTD
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
- apply_config_file(config_file)
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
- apply_config_file(config_file)
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
- apply_config_file(config_file)
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-2023 Espressif Systems (Shanghai) CO LTD
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-2024 Espressif Systems (Shanghai) CO LTD
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 = BOOL_EXPR.parseString(stmt)[0]
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(pickle.dumps(obj, protocol=4)) # protocol 4 by default is set in Python 3.8
164
+ sha.update(repr(obj).encode())
157
165
 
158
166
  return sha.hexdigest()
159
167
 
@@ -1,141 +1,6 @@
1
- # SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
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
- from pyparsing import (
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
- from ..constants import (
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
@@ -17,6 +17,7 @@ Modifications:
17
17
  - recursively find TOML file.
18
18
  """
19
19
 
20
+ import logging
20
21
  import os
21
22
  import sys
22
23
  from abc import ABC, abstractmethod
@@ -30,6 +31,7 @@ from idf_build_apps.constants import IDF_BUILD_APPS_TOML_FN
30
31
 
31
32
  PathType = Union[Path, str, List[Union[Path, str]], Tuple[Union[Path, str], ...]]
32
33
  DEFAULT_PATH = Path('')
34
+ LOGGER = logging.getLogger(__name__)
33
35
 
34
36
 
35
37
  class ConfigFileSourceMixin(ABC):
@@ -93,17 +95,19 @@ class TomlConfigSettingsSource(InitSettingsSource, ConfigFileSourceMixin):
93
95
  :param depth: Number of directories up the tree to check of a pyproject.toml.
94
96
  """
95
97
  if provided and Path(provided).is_file():
96
- return provided.resolve()
98
+ fp = provided.resolve()
99
+ LOGGER.debug(f'Loading config file: {fp}')
100
+ return fp
97
101
 
98
102
  rv = Path.cwd()
99
103
  count = -1
100
104
  while count < depth:
101
- if str(rv) == rv.root:
105
+ if len(rv.parts) == 1:
102
106
  break
103
107
 
104
108
  fp = rv / filename
105
109
  if fp.is_file():
106
- print(f'Loading config file: {fp}')
110
+ LOGGER.debug(f'Loading config file: {fp}')
107
111
  return fp
108
112
 
109
113
  rv = rv.parent
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: idf-build-apps
3
- Version: 2.6.0
3
+ Version: 2.6.2
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=VMMqqRp30Golk7dqGCARNL8mR9oZaz86HOXoySoXvIY,650
1
+ idf_build_apps/__init__.py,sha256=m6Rv6NFbCuro2DEeChOgSIDFGQahhbsPVd6IEqQJY74,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=7-rphv1hhbjJRfE_agBUyQbJaiUhsjsBo6C3eDmug2k,34101
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=07ve2FtWuLBuc_6LFzbs1XncB1VNi9HJUqGjQQauRNM,3952
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=Z_hetbOavgCJZQPaP01_jx57fR1w0DefiFz0J2cCwp0,16498
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=Q2-cb3ngNjnl6_zWhUfzZZB10f_-Rv2JYNck3Lk7UkQ,133
17
- idf_build_apps/manifest/if_parser.py,sha256=AAEyYPgcBWL2ToCmcvhx3fl8ebYdC5-LMvvDkYtWn8o,6546
18
- idf_build_apps/manifest/manifest.py,sha256=6F6Nt93eaoBOHlGHZtv2hHT8Zw0HmJf0d_MESlgye6M,14478
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=2e-zA_aHe7NVXMoPKU_0Z9Lg9lw80TFWQ-2PZf10FMs,4419
20
+ idf_build_apps/vendors/pydantic_sources.py,sha256=cxSIPRc3eI5peVMhDxwf58YaGhuG4SCwPRVX2znFEek,4553
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.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,,
23
+ idf_build_apps-2.6.2.dist-info/entry_points.txt,sha256=3pVUirUEsb6jsDRikkQWNUt4hqLK2ci1HvW_Vf8b6uE,59
24
+ idf_build_apps-2.6.2.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
25
+ idf_build_apps-2.6.2.dist-info/WHEEL,sha256=CpUCUxeHQbRN5UGRQHYRJorO5Af-Qy_fHMctcQ8DSGI,82
26
+ idf_build_apps-2.6.2.dist-info/METADATA,sha256=mKkCtbqE575AjE9JLBbTUeRQ9Cs1gcep0FHeHl0tN8s,4693
27
+ idf_build_apps-2.6.2.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
- )