idf-build-apps 2.1.1__py3-none-any.whl → 2.2.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.
@@ -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.1.1'
11
+ __version__ = '2.2.1'
12
12
 
13
13
  from .session_args import (
14
14
  SessionArgs,
@@ -36,8 +36,8 @@ __all__ = [
36
36
  'AppDeserializer',
37
37
  'CMakeApp',
38
38
  'MakeApp',
39
- 'find_apps',
40
39
  'build_apps',
40
+ 'find_apps',
41
41
  'json_to_app',
42
42
  'setup_logging',
43
43
  ]
idf_build_apps/app.py CHANGED
@@ -88,7 +88,7 @@ class App(BaseModel):
88
88
  IDF_VERSION_PLACEHOLDER: t.ClassVar[str] = '@v' # replace it with the IDF version
89
89
  INDEX_PLACEHOLDER: t.ClassVar[str] = '@i' # replace it with the build index (while build_apps)
90
90
 
91
- SDKCONFIG_LINE_REGEX: t.ClassVar[t.Pattern] = re.compile(r"^([^=]+)=\"?([^\"\n]*)\"?\n*$")
91
+ SDKCONFIG_LINE_REGEX: t.ClassVar[t.Pattern] = re.compile(r'^([^=]+)=\"?([^\"\n]*)\"?\n*$')
92
92
 
93
93
  # could be assigned later, used for filtering out apps by supported_targets
94
94
  MANIFEST: t.ClassVar[t.Optional[Manifest]] = None
@@ -151,12 +151,10 @@ class App(BaseModel):
151
151
  size_json_filename: t.Optional[str] = None,
152
152
  **kwargs: t.Any,
153
153
  ) -> None:
154
- kwargs.update(
155
- {
156
- 'app_dir': app_dir,
157
- 'target': target,
158
- }
159
- )
154
+ kwargs.update({
155
+ 'app_dir': app_dir,
156
+ 'target': target,
157
+ })
160
158
  super().__init__(**kwargs)
161
159
 
162
160
  # These internal variables store the paths with environment variables and placeholders;
@@ -169,14 +167,12 @@ class App(BaseModel):
169
167
  self._is_build_log_path_temp = not bool(build_log_filename)
170
168
 
171
169
  # pass all parameters to initialize hook method
172
- kwargs.update(
173
- {
174
- 'work_dir': self._work_dir,
175
- 'build_dir': self._build_dir,
176
- 'build_log_filename': build_log_filename,
177
- 'size_json_filename': size_json_filename,
178
- }
179
- )
170
+ kwargs.update({
171
+ 'work_dir': self._work_dir,
172
+ 'build_dir': self._build_dir,
173
+ 'build_log_filename': build_log_filename,
174
+ 'size_json_filename': size_json_filename,
175
+ })
180
176
  self._kwargs = kwargs
181
177
  self._initialize_hook(**kwargs)
182
178
 
@@ -240,12 +236,10 @@ class App(BaseModel):
240
236
  return [DEFAULT_SDKCONFIG]
241
237
 
242
238
  @t.overload
243
- def _expand(self, path: None) -> None:
244
- ...
239
+ def _expand(self, path: None) -> None: ...
245
240
 
246
241
  @t.overload
247
- def _expand(self, path: str) -> str:
248
- ...
242
+ def _expand(self, path: str) -> str: ...
249
243
 
250
244
  def _expand(self, path):
251
245
  """
@@ -437,14 +431,18 @@ class App(BaseModel):
437
431
  @property
438
432
  def depends_components(self) -> t.List[str]:
439
433
  if self.MANIFEST:
440
- return self.MANIFEST.depends_components(self.app_dir)
434
+ return self.MANIFEST.depends_components(
435
+ self.app_dir, self.sdkconfig_files_defined_idf_target, self.config_name
436
+ )
441
437
 
442
438
  return []
443
439
 
444
440
  @property
445
441
  def depends_filepatterns(self) -> t.List[str]:
446
442
  if self.MANIFEST:
447
- return self.MANIFEST.depends_filepatterns(self.app_dir)
443
+ return self.MANIFEST.depends_filepatterns(
444
+ self.app_dir, self.sdkconfig_files_defined_idf_target, self.config_name
445
+ )
448
446
 
449
447
  return []
450
448
 
@@ -618,10 +616,10 @@ class App(BaseModel):
618
616
  def _build(
619
617
  self,
620
618
  *,
621
- manifest_rootpath: t.Optional[str] = None,
622
- modified_components: t.Optional[t.List[str]] = None,
623
- modified_files: t.Optional[t.List[str]] = None,
624
- check_app_dependencies: bool = False,
619
+ manifest_rootpath: t.Optional[str] = None, # noqa: ARG002
620
+ modified_components: t.Optional[t.List[str]] = None, # noqa: ARG002
621
+ modified_files: t.Optional[t.List[str]] = None, # noqa: ARG002
622
+ check_app_dependencies: bool = False, # noqa: ARG002
625
623
  ) -> None:
626
624
  self._build_stage = BuildStage.BUILD
627
625
 
@@ -654,14 +652,12 @@ class App(BaseModel):
654
652
  else:
655
653
  with open(self.size_json_path, 'w') as fw:
656
654
  subprocess_run(
657
- (
658
- [
659
- sys.executable,
660
- str(IDF_SIZE_PY),
661
- '--json',
662
- map_file,
663
- ]
664
- ),
655
+ ([
656
+ sys.executable,
657
+ str(IDF_SIZE_PY),
658
+ '--json',
659
+ map_file,
660
+ ]),
665
661
  log_terminal=False,
666
662
  log_fs=fw,
667
663
  check=True,
@@ -789,7 +785,7 @@ class MakeApp(App):
789
785
  if self.sdkconfig_files_defined_idf_target:
790
786
  return [self.sdkconfig_files_defined_idf_target]
791
787
 
792
- return ['esp8266'] + FolderRule.DEFAULT_BUILD_TARGETS
788
+ return ['esp8266', *FolderRule.DEFAULT_BUILD_TARGETS]
793
789
 
794
790
  def _build(
795
791
  self,
@@ -910,7 +906,7 @@ class CMakeApp(App):
910
906
 
911
907
  if modified_components is not None and check_app_dependencies and self.build_status == BuildStatus.UNKNOWN:
912
908
  subprocess_run(
913
- common_args + ['reconfigure'],
909
+ [*common_args, 'reconfigure'],
914
910
  log_terminal=self._is_build_log_path_temp,
915
911
  log_fs=self.build_log_path,
916
912
  check=True,
@@ -1,4 +1,4 @@
1
- # SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
1
+ # SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
2
2
  # SPDX-License-Identifier: Apache-2.0
3
3
 
4
4
  from .report import (
@@ -7,4 +7,4 @@ from .report import (
7
7
  TestSuite,
8
8
  )
9
9
 
10
- __all__ = ['TestReport', 'TestCase', 'TestSuite']
10
+ __all__ = ['TestCase', 'TestReport', 'TestSuite']
@@ -1,4 +1,4 @@
1
- # SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
1
+ # SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
2
2
  # SPDX-License-Identifier: Apache-2.0
3
3
 
4
4
  """
@@ -39,7 +39,9 @@ import typing as t
39
39
  from datetime import (
40
40
  datetime,
41
41
  )
42
- from xml.etree import ElementTree as ET
42
+ from xml.etree import (
43
+ ElementTree,
44
+ )
43
45
  from xml.sax.saxutils import (
44
46
  escape,
45
47
  )
@@ -118,8 +120,8 @@ class TestCase:
118
120
  def is_error(self) -> bool:
119
121
  return self.error_reason is not None
120
122
 
121
- def to_xml_elem(self) -> ET.Element:
122
- elem = ET.Element(
123
+ def to_xml_elem(self) -> ElementTree.Element:
124
+ elem = ElementTree.Element(
123
125
  'testcase',
124
126
  {
125
127
  'name': self.name,
@@ -128,11 +130,11 @@ class TestCase:
128
130
  },
129
131
  )
130
132
  if self.error_reason:
131
- ET.SubElement(elem, 'error', {'message': escape(self.error_reason)})
133
+ ElementTree.SubElement(elem, 'error', {'message': escape(self.error_reason)})
132
134
  elif self.failure_reason:
133
- ET.SubElement(elem, 'failure', {'message': escape(self.failure_reason)})
135
+ ElementTree.SubElement(elem, 'failure', {'message': escape(self.failure_reason)})
134
136
  elif self.skipped_reason:
135
- ET.SubElement(elem, 'skipped', {'message': escape(self.skipped_reason)})
137
+ ElementTree.SubElement(elem, 'skipped', {'message': escape(self.skipped_reason)})
136
138
 
137
139
  if self.properties:
138
140
  for k, v in self.properties.items():
@@ -171,8 +173,8 @@ class TestSuite:
171
173
 
172
174
  self.duration_sec += test_case.duration_sec
173
175
 
174
- def to_xml_elem(self) -> ET.Element:
175
- elem = ET.Element(
176
+ def to_xml_elem(self) -> ElementTree.Element:
177
+ elem = ElementTree.Element(
176
178
  'testsuite',
177
179
  {
178
180
  'name': self.name,
@@ -199,10 +201,10 @@ class TestReport:
199
201
  self.filepath = filepath
200
202
 
201
203
  def create_test_report(self) -> None:
202
- xml = ET.Element('testsuites')
204
+ xml = ElementTree.Element('testsuites')
203
205
 
204
206
  for test_suite in self.test_suites:
205
207
  xml.append(test_suite.to_xml_elem())
206
208
 
207
- ET.ElementTree(xml).write(self.filepath, encoding='utf-8')
209
+ ElementTree.ElementTree(xml).write(self.filepath, encoding='utf-8')
208
210
  LOGGER.info('Test report written to %s', self.filepath)
idf_build_apps/log.py CHANGED
@@ -1,4 +1,4 @@
1
- # SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
1
+ # SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
2
2
  # SPDX-License-Identifier: Apache-2.0
3
3
 
4
4
  import logging
@@ -51,7 +51,7 @@ class ColoredFormatter(logging.Formatter):
51
51
 
52
52
  if record.levelno in [logging.WARNING, logging.ERROR]:
53
53
  record.msg = '>>> ' + str(record.msg)
54
- elif record.levelno in [logging.CRITICAL]:
54
+ elif record.levelno == logging.CRITICAL:
55
55
  record.msg = '!!! ' + str(record.msg)
56
56
 
57
57
  formatter = logging.Formatter(log_fmt, datefmt=self.datefmt)
idf_build_apps/main.py CHANGED
@@ -351,14 +351,12 @@ def build_apps(
351
351
  if os.path.isfile(app.size_json_path):
352
352
  with open(build_apps_args.collect_size_info, 'a') as fw:
353
353
  fw.write(
354
- json.dumps(
355
- {
356
- 'app_name': app.name,
357
- 'config_name': app.config_name,
358
- 'target': app.target,
359
- 'path': app.size_json_path,
360
- }
361
- )
354
+ json.dumps({
355
+ 'app_name': app.name,
356
+ 'config_name': app.config_name,
357
+ 'target': app.target,
358
+ 'path': app.size_json_path,
359
+ })
362
360
  + '\n'
363
361
  )
364
362
  LOGGER.debug('Recorded size info file path in %s', build_apps_args.collect_size_info)
@@ -488,7 +486,7 @@ def get_parser() -> argparse.ArgumentParser:
488
486
  type=str,
489
487
  help='The --override-sdkconfig-items option is a comma-separated list '
490
488
  'that permits the overriding of specific configuration items defined '
491
- 'in the SDK\'s sdkconfig file and Kconfig using a command-line argument. '
489
+ "in the SDK's sdkconfig file and Kconfig using a command-line argument. "
492
490
  'The sdkconfig items specified here override the same sdkconfig '
493
491
  'item defined in the --override-sdkconfig-files, if exists.',
494
492
  )
@@ -669,7 +667,7 @@ def validate_args(parser: argparse.ArgumentParser, args: argparse.Namespace) ->
669
667
  if not args.target:
670
668
  raise InvalidCommand(
671
669
  'Must specify current build target with CLI option "-t <target>" or "--target <target>". '
672
- '(choices: [{}]'.format(','.join(ALL_TARGETS + ['all']))
670
+ '(choices: [{}]'.format(','.join([*ALL_TARGETS, 'all']))
673
671
  )
674
672
 
675
673
  default_build_targets = []
@@ -677,8 +675,8 @@ def validate_args(parser: argparse.ArgumentParser, args: argparse.Namespace) ->
677
675
  for target in args.default_build_targets:
678
676
  if target not in ALL_TARGETS:
679
677
  raise InvalidCommand(
680
- 'Unrecognizable target {} specified with "--default-build-targets". '
681
- 'Current ESP-IDF available targets: {}'.format(target, ALL_TARGETS)
678
+ f'Unrecognizable target {target} specified with "--default-build-targets". '
679
+ f'Current ESP-IDF available targets: {ALL_TARGETS}'
682
680
  )
683
681
 
684
682
  if target not in default_build_targets:
@@ -1,6 +1,7 @@
1
- # SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
1
+ # SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
2
2
  # SPDX-License-Identifier: Apache-2.0
3
3
 
4
+ import operator
4
5
  import os
5
6
  from ast import (
6
7
  literal_eval,
@@ -113,7 +114,7 @@ class Integer(Stmt):
113
114
  def __init__(self, t: ParseResults):
114
115
  self.expr: str = t[0]
115
116
 
116
- def get_value(self, target: str, config_name: str) -> Any:
117
+ def get_value(self, target: str, config_name: str) -> Any: # noqa: ARG002
117
118
  return literal_eval(self.expr)
118
119
 
119
120
 
@@ -121,7 +122,7 @@ class String(Stmt):
121
122
  def __init__(self, t: ParseResults):
122
123
  self.expr: str = t[0]
123
124
 
124
- def get_value(self, target: str, config_name: str) -> Any:
125
+ def get_value(self, target: str, config_name: str) -> Any: # noqa: ARG002
125
126
  return literal_eval(f'"{self.expr}"') # double quotes is swallowed by QuotedString
126
127
 
127
128
 
@@ -135,12 +136,12 @@ class List_(Stmt):
135
136
 
136
137
  class BoolStmt(Stmt):
137
138
  _OP_DICT = {
138
- '==': lambda x, y: x == y,
139
- '!=': lambda x, y: x != y,
140
- '>': lambda x, y: x > y,
141
- '>=': lambda x, y: x >= y,
142
- '<': lambda x, y: x < y,
143
- '<=': lambda x, y: x <= y,
139
+ '==': operator.eq,
140
+ '!=': operator.ne,
141
+ '>': operator.gt,
142
+ '>=': operator.ge,
143
+ '<': operator.lt,
144
+ '<=': operator.le,
144
145
  'not in': lambda x, y: x not in y,
145
146
  'in': lambda x, y: x in y,
146
147
  }
@@ -46,6 +46,21 @@ class IfClause:
46
46
  return self.stmt.get_value(target, config_name)
47
47
 
48
48
 
49
+ class SwitchClause:
50
+ def __init__(
51
+ self, if_clauses: t.List[IfClause], contents: t.List[t.List[str]], default_clause: t.List[str]
52
+ ) -> None:
53
+ self.if_clauses = if_clauses
54
+ self.contents = contents
55
+ self.default_clause = default_clause
56
+
57
+ def get_value(self, target: str, config_name: str) -> t.Any:
58
+ for if_clause, content in zip(self.if_clauses, self.contents):
59
+ if if_clause.get_value(target, config_name):
60
+ return content
61
+ return self.default_clause
62
+
63
+
49
64
  class FolderRule:
50
65
  DEFAULT_BUILD_TARGETS = SUPPORTED_TARGETS
51
66
 
@@ -55,8 +70,8 @@ class FolderRule:
55
70
  enable: t.Optional[t.List[t.Dict[str, t.Any]]] = None,
56
71
  disable: t.Optional[t.List[t.Dict[str, t.Any]]] = None,
57
72
  disable_test: t.Optional[t.List[t.Dict[str, t.Any]]] = None,
58
- depends_components: t.Optional[t.List[str]] = None,
59
- depends_filepatterns: t.Optional[t.List[str]] = None,
73
+ depends_components: t.Optional[t.List[t.Union[str, t.Dict[str, t.Any]]]] = None,
74
+ depends_filepatterns: t.Optional[t.List[t.Union[str, t.Dict[str, t.Any]]]] = None,
60
75
  ) -> None:
61
76
  self.folder = os.path.abspath(folder)
62
77
 
@@ -68,11 +83,48 @@ class FolderRule:
68
83
  _kwargs['reason'] = clause['reason']
69
84
  return IfClause(**_kwargs)
70
85
 
86
+ def _clause_to_switch_or_list(
87
+ statements: t.Optional[t.List[t.Union[str, t.Dict[str, t.Any]]]],
88
+ ) -> t.Union[SwitchClause, t.List[str]]:
89
+ if not statements:
90
+ return []
91
+
92
+ switch_statements = []
93
+ str_statements = []
94
+ for statement in statements:
95
+ if isinstance(statement, t.Dict):
96
+ switch_statements.append(statement)
97
+ else:
98
+ str_statements.append(statement)
99
+
100
+ if switch_statements and str_statements:
101
+ raise InvalidManifest('Current manifest format has to fit either the switch format or the list format.')
102
+
103
+ if str_statements:
104
+ return str_statements
105
+
106
+ return _clause_to_switch_clause(switch_statements)
107
+
108
+ def _clause_to_switch_clause(switch_statements: t.List[t.Dict[str, t.Any]]) -> SwitchClause:
109
+ if_clauses = []
110
+ contents = []
111
+ default_clauses = []
112
+ for statement in switch_statements:
113
+ if 'if' in statement:
114
+ if_clauses.append(IfClause(stmt=statement['if']))
115
+ contents.append(statement['content'])
116
+ elif 'default' in statement:
117
+ default_clauses.extend(statement['default'])
118
+ else:
119
+ raise InvalidManifest("Only the 'if' and 'default' keywords are supported in switch clause.")
120
+
121
+ return SwitchClause(if_clauses, contents, default_clauses)
122
+
71
123
  self.enable = [_clause_to_if_clause(clause) for clause in enable] if enable else []
72
124
  self.disable = [_clause_to_if_clause(clause) for clause in disable] if disable else []
73
125
  self.disable_test = [_clause_to_if_clause(clause) for clause in disable_test] if disable_test else []
74
- self.depends_components = depends_components or []
75
- self.depends_filepatterns = depends_filepatterns or []
126
+ self.depends_components = _clause_to_switch_or_list(depends_components)
127
+ self.depends_filepatterns = _clause_to_switch_or_list(depends_filepatterns)
76
128
 
77
129
  def __hash__(self) -> int:
78
130
  return hash(self.folder)
@@ -232,8 +284,18 @@ class Manifest:
232
284
  ) -> t.List[str]:
233
285
  return self._most_suitable_rule(folder).enable_test_targets(default_sdkconfig_target, config_name)
234
286
 
235
- def depends_components(self, folder: str) -> t.List[str]:
236
- return self._most_suitable_rule(folder).depends_components
287
+ def depends_components(
288
+ self, folder: str, default_sdkconfig_target: t.Optional[str] = None, config_name: t.Optional[str] = None
289
+ ) -> t.List[str]:
290
+ res = self._most_suitable_rule(folder).depends_components
291
+ if isinstance(res, list):
292
+ return res
293
+ return res.get_value(default_sdkconfig_target or '', config_name or '')
237
294
 
238
- def depends_filepatterns(self, folder: str) -> t.List[str]:
239
- return self._most_suitable_rule(folder).depends_filepatterns
295
+ def depends_filepatterns(
296
+ self, folder: str, default_sdkconfig_target: t.Optional[str] = None, config_name: t.Optional[str] = None
297
+ ) -> t.List[str]:
298
+ res = self._most_suitable_rule(folder).depends_filepatterns
299
+ if isinstance(res, list):
300
+ return res
301
+ return res.get_value(default_sdkconfig_target or '', config_name or '')
@@ -1,4 +1,4 @@
1
- # SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
1
+ # SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
2
2
  # SPDX-License-Identifier: Apache-2.0
3
3
  import logging
4
4
  import os.path
@@ -93,19 +93,15 @@ class SocHeader(dict):
93
93
 
94
94
  @classmethod
95
95
  def _parse_soc_header(cls, target: str) -> t.Dict[str, t.Any]:
96
- soc_headers_dir = cls._get_dir_from_candidates(
97
- [
98
- # other branches
99
- os.path.abspath(os.path.join(IDF_PATH, 'components', 'soc', target, 'include', 'soc')),
100
- # release/v4.2
101
- os.path.abspath(os.path.join(IDF_PATH, 'components', 'soc', 'soc', target, 'include', 'soc')),
102
- ]
103
- )
104
- esp_rom_headers_dir = cls._get_dir_from_candidates(
105
- [
106
- os.path.join(IDF_PATH, 'components', 'esp_rom', target),
107
- ]
108
- )
96
+ soc_headers_dir = cls._get_dir_from_candidates([
97
+ # other branches
98
+ os.path.abspath(os.path.join(IDF_PATH, 'components', 'soc', target, 'include', 'soc')),
99
+ # release/v4.2
100
+ os.path.abspath(os.path.join(IDF_PATH, 'components', 'soc', 'soc', target, 'include', 'soc')),
101
+ ])
102
+ esp_rom_headers_dir = cls._get_dir_from_candidates([
103
+ os.path.join(IDF_PATH, 'components', 'esp_rom', target),
104
+ ])
109
105
 
110
106
  header_files: t.List[str] = []
111
107
  if soc_headers_dir:
@@ -1,4 +1,4 @@
1
- # SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
1
+ # SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
2
2
  # SPDX-License-Identifier: Apache-2.0
3
3
 
4
4
  import logging
@@ -51,7 +51,7 @@ class SessionArgs:
51
51
 
52
52
  with open(f) as fr:
53
53
  for line in fr:
54
- m = re.compile(r"^([^=]+)=\"?([^\"\n]*)\"?\n*$").match(line)
54
+ m = re.compile(r'^([^=]+)=([^\n]*)\n*$').match(line)
55
55
  if not m:
56
56
  continue
57
57
  d[m.group(1)] = m.group(2)
@@ -60,7 +60,7 @@ class SessionArgs:
60
60
  def _get_override_sdkconfig_items(self, override_sdkconfig_items: t.Tuple[str]) -> t.Dict:
61
61
  d = {}
62
62
  for line in override_sdkconfig_items:
63
- m = re.compile(r"^([^=]+)=\"?([^\"\n]*)\"?\n*$").match(line)
63
+ m = re.compile(r'^([^=]+)=([^\n]*)\n*$').match(line)
64
64
  if m:
65
65
  d[m.group(1)] = m.group(2)
66
66
  return d
idf_build_apps/utils.py CHANGED
@@ -190,18 +190,15 @@ _T = t.TypeVar('_T')
190
190
 
191
191
 
192
192
  @t.overload
193
- def to_list(s: None) -> None:
194
- ...
193
+ def to_list(s: None) -> None: ...
195
194
 
196
195
 
197
196
  @t.overload
198
- def to_list(s: t.Iterable[_T]) -> t.List[_T]:
199
- ...
197
+ def to_list(s: t.Iterable[_T]) -> t.List[_T]: ...
200
198
 
201
199
 
202
200
  @t.overload
203
- def to_list(s: _T) -> t.List[_T]:
204
- ...
201
+ def to_list(s: _T) -> t.List[_T]: ...
205
202
 
206
203
 
207
204
  def to_list(s):
@@ -229,18 +226,15 @@ def to_list(s):
229
226
 
230
227
 
231
228
  @t.overload
232
- def to_set(s: None) -> None:
233
- ...
229
+ def to_set(s: None) -> None: ...
234
230
 
235
231
 
236
232
  @t.overload
237
- def to_set(s: t.Iterable[_T]) -> t.Set[_T]:
238
- ...
233
+ def to_set(s: t.Iterable[_T]) -> t.Set[_T]: ...
239
234
 
240
235
 
241
236
  @t.overload
242
- def to_set(s: _T) -> t.Set[_T]:
243
- ...
237
+ def to_set(s: _T) -> t.Set[_T]: ...
244
238
 
245
239
 
246
240
  def to_set(s):
@@ -366,4 +360,4 @@ class BaseModel(_BaseModel):
366
360
  else:
367
361
  hash_list.append(v)
368
362
 
369
- return hash((type(self),) + tuple(hash_list))
363
+ return hash((type(self), *tuple(hash_list)))
@@ -23,23 +23,39 @@ def parse_postfixes(manifest_dict: t.Dict):
23
23
 
24
24
  operation = key[-1]
25
25
 
26
- dict_obj = []
26
+ if_dict_obj = []
27
+ other_dict_obj = []
27
28
  str_obj = set()
28
29
  for obj in updated_folder[key[:-1]]:
29
30
  if isinstance(obj, t.Dict):
30
- dict_obj.append(obj)
31
+ if 'if' in obj:
32
+ if_dict_obj.append(obj)
33
+ else:
34
+ other_dict_obj.append(obj)
31
35
  else:
32
36
  str_obj.add(obj)
33
37
 
34
38
  for obj in folder_rule[key]:
35
39
  if isinstance(obj, t.Dict):
36
- dict_obj = [obj_j for obj_j in dict_obj if obj['if'] != obj_j['if']]
40
+ _l = obj['if']
41
+ if isinstance(_l, str):
42
+ _l = _l.replace(' ', '')
43
+
44
+ new_dict_obj = []
45
+ for obj_j in if_dict_obj:
46
+ _r = obj_j['if']
47
+ if isinstance(_r, str):
48
+ _r = _r.replace(' ', '')
49
+ if _l != _r:
50
+ new_dict_obj.append(obj_j)
51
+ if_dict_obj = new_dict_obj
52
+
37
53
  if operation == '+':
38
- dict_obj.append(obj)
54
+ if_dict_obj.append(obj)
39
55
  else:
40
56
  str_obj.add(obj) if operation == '+' else str_obj.remove(obj)
41
57
 
42
- updated_folder[key[:-1]] = dict_obj + sorted(str_obj)
58
+ updated_folder[key[:-1]] = if_dict_obj + other_dict_obj + sorted(str_obj)
43
59
 
44
60
  manifest_dict[folder] = updated_folder
45
61
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: idf-build-apps
3
- Version: 2.1.1
3
+ Version: 2.2.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
@@ -0,0 +1,25 @@
1
+ idf_build_apps/__init__.py,sha256=p6GpwxTEYyUc2XAP0E7MEG5zAbq9-de2YV-MR1_S-sc,650
2
+ idf_build_apps/__main__.py,sha256=8E-5xHm2MlRun0L88XJleNh5U50dpE0Q1nK5KqomA7I,182
3
+ idf_build_apps/app.py,sha256=LyaZ9bi_FEzK9Vkj6r0KP455XSoJ_gsuealE7PG2rEQ,35121
4
+ idf_build_apps/build_apps_args.py,sha256=r6VCJDdCzE873X8OTputYkCBZPgECaKoNlAejfcamJk,1644
5
+ idf_build_apps/config.py,sha256=I75uOQGarCWVKGi16ZYpo0qTVU25BUP4eh6-RWCtbvw,2924
6
+ idf_build_apps/constants.py,sha256=xqclwUpWE5dEByL4kxdg2HaHjbAfkJtxodFfLZuAk8A,2818
7
+ idf_build_apps/finder.py,sha256=qw5moNq7U5mHSsR0CCfGkKE9p4QsWYNcfkxzeQ73HgM,6252
8
+ idf_build_apps/log.py,sha256=JysogBHoompfW9E9w0U4wZH7tt8dBdfoh-stPXQz1hw,2573
9
+ idf_build_apps/main.py,sha256=jeQeNUiQoC1g5pS5vPpzfOpHCX7amdOqWpfp4BZjmac,32591
10
+ idf_build_apps/session_args.py,sha256=2WDTy40IFAc0KQ57HaeBcYj_k10eUXRKkDOWLrFCaHY,2985
11
+ idf_build_apps/utils.py,sha256=n9PNJEDDsA9hbbM0SNPdTFsO2_E8alNrX7CNYzaFHik,9644
12
+ idf_build_apps/junit/__init__.py,sha256=IxvdaS6eSXp7kZxRuXqyZyGxuA_A1nOW1jF1HMi8Gns,231
13
+ idf_build_apps/junit/report.py,sha256=vHE5RcBa7Bj4a1p2lXaTh0m9eJIO_uTGrOnJg8NEi4I,6430
14
+ idf_build_apps/junit/utils.py,sha256=gtibRs8WTE8IXTIAS73QR_k_jrJlOjCl2y-9KiP5_Nk,1304
15
+ idf_build_apps/manifest/__init__.py,sha256=Q2-cb3ngNjnl6_zWhUfzZZB10f_-Rv2JYNck3Lk7UkQ,133
16
+ idf_build_apps/manifest/if_parser.py,sha256=r0pivV9gmniPn3Ia6sTMbW5tFAKInhOXk-Lfd6GokqE,6381
17
+ idf_build_apps/manifest/manifest.py,sha256=P5ZaUd72A_HOVF6iuwap__Bw-w7WI72ugiTURm9PNNQ,10708
18
+ idf_build_apps/manifest/soc_header.py,sha256=ULLad1TI8mGfdJhB7LJ4T9A_8BugF1TmckgdO7jO7Fg,3956
19
+ idf_build_apps/yaml/__init__.py,sha256=W-3z5no07RQ6eYKGyOAPA8Z2CLiMPob8DD91I4URjrA,162
20
+ idf_build_apps/yaml/parser.py,sha256=Y2OyB4g1DCC7C7jrvpIyZV9lgeCB_XvuB75iGmqiTaM,2093
21
+ idf_build_apps-2.2.1.dist-info/entry_points.txt,sha256=3pVUirUEsb6jsDRikkQWNUt4hqLK2ci1HvW_Vf8b6uE,59
22
+ idf_build_apps-2.2.1.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
23
+ idf_build_apps-2.2.1.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81
24
+ idf_build_apps-2.2.1.dist-info/METADATA,sha256=wz146GLU-mtJhMQAZ8W9soUPAG1kTVpLavAVT2cyBf8,4450
25
+ idf_build_apps-2.2.1.dist-info/RECORD,,
@@ -1,25 +0,0 @@
1
- idf_build_apps/__init__.py,sha256=coRoaTf5HIYINwKK7XVWhJppR2EgU6graBHkYeF90v4,650
2
- idf_build_apps/__main__.py,sha256=8E-5xHm2MlRun0L88XJleNh5U50dpE0Q1nK5KqomA7I,182
3
- idf_build_apps/app.py,sha256=65K6Ou_fsgP0dsZu1EVbvV2_n7eM0OE8hf4q8tTHLPU,35037
4
- idf_build_apps/build_apps_args.py,sha256=r6VCJDdCzE873X8OTputYkCBZPgECaKoNlAejfcamJk,1644
5
- idf_build_apps/config.py,sha256=I75uOQGarCWVKGi16ZYpo0qTVU25BUP4eh6-RWCtbvw,2924
6
- idf_build_apps/constants.py,sha256=xqclwUpWE5dEByL4kxdg2HaHjbAfkJtxodFfLZuAk8A,2818
7
- idf_build_apps/finder.py,sha256=qw5moNq7U5mHSsR0CCfGkKE9p4QsWYNcfkxzeQ73HgM,6252
8
- idf_build_apps/log.py,sha256=4P4q8EqV68iQw0LCoNI6ibBBpAkNgetDxZ0Cgbhp0Bo,2570
9
- idf_build_apps/main.py,sha256=99UPxgqynfcoJwIUx5Ck1xxhG3i2T7vaDeWSo8ESrqE,32683
10
- idf_build_apps/session_args.py,sha256=LYgibgUGjHm0iAd6gBYcT9rpTCcdKfcblFMysAlv7UE,2996
11
- idf_build_apps/utils.py,sha256=-o0yyYHAhwVD2ihRupUJdKEu0sAIOaGg4DnIRy6iJNA,9669
12
- idf_build_apps/junit/__init__.py,sha256=GRyhJfZet00iWxe2PvUAG72CXhnhOZaV4B7Z7txKVAk,226
13
- idf_build_apps/junit/report.py,sha256=2sBLEL5EnGW6h0ku2W-BOyEFMgQcu0OO-WcFyXH_Aqg,6341
14
- idf_build_apps/junit/utils.py,sha256=gtibRs8WTE8IXTIAS73QR_k_jrJlOjCl2y-9KiP5_Nk,1304
15
- idf_build_apps/manifest/__init__.py,sha256=Q2-cb3ngNjnl6_zWhUfzZZB10f_-Rv2JYNck3Lk7UkQ,133
16
- idf_build_apps/manifest/if_parser.py,sha256=hS3khcDeFsoqfDLdRG931h91SU4bTALACxjcEiiDIBQ,6379
17
- idf_build_apps/manifest/manifest.py,sha256=JG-Fk2sK71Rl0ZEvluGFp2fJirb9vzDlFxUCLew2U18,8057
18
- idf_build_apps/manifest/soc_header.py,sha256=TVT7wxzcxdeIdX8WAtPYr8bFV7EqTWkVo4h18MWsD8Q,4028
19
- idf_build_apps/yaml/__init__.py,sha256=W-3z5no07RQ6eYKGyOAPA8Z2CLiMPob8DD91I4URjrA,162
20
- idf_build_apps/yaml/parser.py,sha256=pmT_6SKAY4PmHHGJwq-YcWkrX-JMXVNHsJOt7-TPbD0,1509
21
- idf_build_apps-2.1.1.dist-info/entry_points.txt,sha256=3pVUirUEsb6jsDRikkQWNUt4hqLK2ci1HvW_Vf8b6uE,59
22
- idf_build_apps-2.1.1.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
23
- idf_build_apps-2.1.1.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81
24
- idf_build_apps-2.1.1.dist-info/METADATA,sha256=Ud3Ob3HyzkGtuucbF0Zz5I_nzy9EpHxaolivWG3nER4,4450
25
- idf_build_apps-2.1.1.dist-info/RECORD,,