specitems 1.2.2__tar.gz → 1.4.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. {specitems-1.2.2 → specitems-1.4.0}/PKG-INFO +1 -1
  2. {specitems-1.2.2 → specitems-1.4.0}/pyproject.toml +1 -1
  3. {specitems-1.2.2 → specitems-1.4.0}/src/specitems/itemmapper.py +70 -30
  4. {specitems-1.2.2 → specitems-1.4.0}/src/specitems/items.py +13 -13
  5. {specitems-1.2.2 → specitems-1.4.0}/README.md +0 -0
  6. {specitems-1.2.2 → specitems-1.4.0}/src/specitems/__init__.py +0 -0
  7. {specitems-1.2.2 → specitems-1.4.0}/src/specitems/cite.py +0 -0
  8. {specitems-1.2.2 → specitems-1.4.0}/src/specitems/clihash.py +0 -0
  9. {specitems-1.2.2 → specitems-1.4.0}/src/specitems/clipickle.py +0 -0
  10. {specitems-1.2.2 → specitems-1.4.0}/src/specitems/clispecdoc.py +0 -0
  11. {specitems-1.2.2 → specitems-1.4.0}/src/specitems/cliutil.py +0 -0
  12. {specitems-1.2.2 → specitems-1.4.0}/src/specitems/cliyamlquery.py +0 -0
  13. {specitems-1.2.2 → specitems-1.4.0}/src/specitems/content.py +0 -0
  14. {specitems-1.2.2 → specitems-1.4.0}/src/specitems/contentmarkdown.py +0 -0
  15. {specitems-1.2.2 → specitems-1.4.0}/src/specitems/contentsphinx.py +0 -0
  16. {specitems-1.2.2 → specitems-1.4.0}/src/specitems/contenttext.py +0 -0
  17. {specitems-1.2.2 → specitems-1.4.0}/src/specitems/getvaluesubprocess.py +0 -0
  18. {specitems-1.2.2 → specitems-1.4.0}/src/specitems/glossary.py +0 -0
  19. {specitems-1.2.2 → specitems-1.4.0}/src/specitems/hashutil.py +0 -0
  20. {specitems-1.2.2 → specitems-1.4.0}/src/specitems/py.typed +0 -0
  21. {specitems-1.2.2 → specitems-1.4.0}/src/specitems/spec.pickle +0 -0
  22. {specitems-1.2.2 → specitems-1.4.0}/src/specitems/specdoc.py +0 -0
  23. {specitems-1.2.2 → specitems-1.4.0}/src/specitems/specverify.py +0 -0
  24. {specitems-1.2.2 → specitems-1.4.0}/src/specitems/subprocessaction.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: specitems
3
- Version: 1.2.2
3
+ Version: 1.4.0
4
4
  Summary: Provides interfaces to work with specification items.
5
5
  Keywords: certification,documentation,markdown,qualification,requirements-management,traceability
6
6
  Author: The specitems Authors
@@ -4,7 +4,7 @@
4
4
 
5
5
  [project]
6
6
  name = "specitems"
7
- version = "1.2.2"
7
+ version = "1.4.0"
8
8
  description = "Provides interfaces to work with specification items."
9
9
  authors = [
10
10
  {name = "The specitems Authors", email = "specthings@embedded-brains.de"}
@@ -203,13 +203,7 @@ class ItemGetValueContext:
203
203
 
204
204
  If the context arguments are not present, then return the value.
205
205
  """
206
- if self.args is None:
207
- return value
208
-
209
- def _substitute(text: str) -> str:
210
- return self.mapper.substitute(text, self.item, self.path)
211
-
212
- return self.mapper.transform(value, self.args, _substitute)
206
+ return self.mapper.transform(self, value)
213
207
 
214
208
  def substitute_and_transform(self, value: Any) -> Any:
215
209
  """
@@ -269,15 +263,10 @@ class ItemMapper(abc.ABC):
269
263
  value = ctx.value[ctx.key]
270
264
  if ctx.index >= 0:
271
265
  value = value[ctx.index]
272
- if not ctx.remaining_path:
273
- value = self.substitute_data(value, ctx.item, ctx.path)
274
- if ctx.args is not None:
275
-
276
- def _substitute(text: str) -> str:
277
- return self.substitute(text, ctx.item, ctx.path)
278
-
279
- value = self.transform(value, ctx.args, _substitute)
280
- return value
266
+ if ctx.remaining_path:
267
+ return value
268
+ return self.transform(ctx,
269
+ self.substitute_data(value, ctx.item, ctx.path))
281
270
 
282
271
  def _add_get_value_map_for_subtypes(
283
272
  self, spec_type: ItemType, type_path: str, path_key: str,
@@ -340,28 +329,42 @@ class ItemMapper(abc.ABC):
340
329
  """
341
330
  Associate the name with the value transformer.
342
331
 
332
+ The get value context is passed as the first argument to the
333
+ transformer.
334
+
343
335
  The transformer is used to transform a mapped value. The mapped value
344
- is passed as the first argument to the transformer.
336
+ is passed as the second argument to the transformer.
345
337
  """
346
338
  self._transformers[name] = transformer
347
339
 
348
- def transform(self, value: Any, name_and_args: str,
349
- substitute: Callable[[str], str]) -> Any:
340
+ def transform(self, ctx: ItemGetValueContext, value: Any) -> Any:
350
341
  """
351
- Transform the value using the transformer specified by the name and
352
- optional arguments.
342
+ Transform the value using the transformer specified by the get value
343
+ context arguments.
344
+
345
+ The get value context is passed as the first argument to the
346
+ transformer.
353
347
 
354
- The value is passed as the first argument to the transformer.
348
+ The value is passed as the second argument to the transformer.
349
+
350
+ If the get value context arguments are not present, then return the
351
+ value.
355
352
 
356
- The name and arguments string parameter specifies the name of the
357
- transformer and optional additional positional and keyword arguments.
358
- The transformer name is the start of the string up to the first space
359
- character or the end of the string. Arguments following the space
360
- character are unpacked and passed to the transformer.
353
+ The get value context arguments specify the name of the transformer and
354
+ optional additional positional and keyword arguments. The transformer
355
+ name is the start of the string up to the first space character or the
356
+ end of the string. Arguments following the space character are
357
+ unpacked and passed to the transformer.
361
358
  """
362
- name, _, args_string = name_and_args.partition(" ")
363
- args, kwargs = unpack_args(args_string, substitute)
364
- return self._transformers[name](value, *args, **kwargs)
359
+ if ctx.args is None:
360
+ return value
361
+
362
+ def _substitute(value_2: str) -> str:
363
+ return self.substitute(value_2, ctx.item, ctx.path)
364
+
365
+ name, _, args_string = ctx.args.partition(" ")
366
+ args, kwargs = unpack_args(args_string, _substitute)
367
+ return self._transformers[name](ctx, value, *args, **kwargs)
365
368
 
366
369
  @contextlib.contextmanager
367
370
  def scope(self, item: Item) -> Iterator[None]:
@@ -510,6 +513,43 @@ class ItemMapper(abc.ABC):
510
513
  return new_dict
511
514
  return data
512
515
 
516
+ def substitute_flexible_list(self,
517
+ flexible_list: list,
518
+ is_enabled_method: Callable[[Any], bool],
519
+ item: Optional[Item] = None,
520
+ prefix: str = "") -> list[str]:
521
+ """
522
+ Create a new list containing the substituted elements of the flexible
523
+ list.
524
+
525
+ Where an element is a dictionary, when its enabled-by expression
526
+ evaluates to true, the data substitution of the element value is added
527
+ to the new list.
528
+ """
529
+ new_list: list[str] = []
530
+ for index, element in enumerate(flexible_list):
531
+ prefix_2 = f"{prefix}[{index}]"
532
+ if isinstance(element, dict):
533
+ if not is_enabled_method(
534
+ self.substitute_data(element["enabled-by"], item,
535
+ prefix_2)):
536
+ continue
537
+ element = self.substitute_data(element["value"], item,
538
+ prefix_2)
539
+ elif isinstance(element, str):
540
+ if _SINGLE_SUBSTITUTION.search(element):
541
+ element = self.map(element[2:-1], item, prefix_2)[2]
542
+ else:
543
+ element = self.substitute(element, item, prefix_2)
544
+ else:
545
+ element = self.substitute_data(element, item, prefix_2)
546
+ if isinstance(element, list):
547
+ new_list.extend(element)
548
+ else:
549
+ assert isinstance(element, str)
550
+ new_list.append(element)
551
+ return new_list
552
+
513
553
  def add_value_provider(self, provider: "ItemValueProvider") -> None:
514
554
  """ Add the value provider to the mapper. """
515
555
  self._value_providers.append(provider)
@@ -157,23 +157,23 @@ def is_enabled(enabled_set: EnabledSet, enabled_by: Any) -> bool:
157
157
  return enabled_by in enabled_set
158
158
 
159
159
 
160
- def _ops_is_enabled_op_and(enabled_set: EnabledSet, enabled_by: Any,
161
- ops: dict) -> bool:
160
+ def _ops_is_enabled_op_and(ops: dict, enabled_set: EnabledSet,
161
+ enabled_by: Any) -> bool:
162
162
  for next_enabled_by in enabled_by:
163
- if not is_enabled_with_ops(enabled_set, next_enabled_by, ops):
163
+ if not is_enabled_with_ops(ops, enabled_set, next_enabled_by):
164
164
  return False
165
165
  return True
166
166
 
167
167
 
168
- def _ops_is_enabled_op_not(enabled_set: EnabledSet, enabled_by: Any,
169
- ops: dict) -> bool:
170
- return not is_enabled_with_ops(enabled_set, enabled_by, ops)
168
+ def _ops_is_enabled_op_not(ops: dict, enabled_set: EnabledSet,
169
+ enabled_by: Any) -> bool:
170
+ return not is_enabled_with_ops(ops, enabled_set, enabled_by)
171
171
 
172
172
 
173
- def _ops_is_enabled_op_or(enabled_set: EnabledSet, enabled_by: Any,
174
- ops: dict) -> bool:
173
+ def _ops_is_enabled_op_or(ops: dict, enabled_set: EnabledSet,
174
+ enabled_by: Any) -> bool:
175
175
  for next_enabled_by in enabled_by:
176
- if is_enabled_with_ops(enabled_set, next_enabled_by, ops):
176
+ if is_enabled_with_ops(ops, enabled_set, next_enabled_by):
177
177
  return True
178
178
  return False
179
179
 
@@ -185,8 +185,8 @@ IS_ENABLED_OPS = {
185
185
  }
186
186
 
187
187
 
188
- def is_enabled_with_ops(enabled_set: EnabledSet, enabled_by: Any,
189
- ops: dict) -> bool:
188
+ def is_enabled_with_ops(ops: dict, enabled_set: EnabledSet,
189
+ enabled_by: Any) -> bool:
190
190
  """
191
191
  Evaluate the enabled-by expression using the enabled set with custom
192
192
  operations.
@@ -194,10 +194,10 @@ def is_enabled_with_ops(enabled_set: EnabledSet, enabled_by: Any,
194
194
  if isinstance(enabled_by, bool):
195
195
  return enabled_by
196
196
  if isinstance(enabled_by, list):
197
- return _ops_is_enabled_op_or(enabled_set, enabled_by, ops)
197
+ return _ops_is_enabled_op_or(ops, enabled_set, enabled_by)
198
198
  if isinstance(enabled_by, dict):
199
199
  key, value = next(iter(enabled_by.items()))
200
- return ops[key](enabled_set, value, ops)
200
+ return ops[key](ops, enabled_set, value)
201
201
  return enabled_by in enabled_set
202
202
 
203
203
 
File without changes