specitems 1.5.2__tar.gz → 1.6.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.
- {specitems-1.5.2 → specitems-1.6.0}/PKG-INFO +1 -1
- {specitems-1.5.2 → specitems-1.6.0}/pyproject.toml +1 -1
- {specitems-1.5.2 → specitems-1.6.0}/src/specitems/itemmapper.py +35 -18
- {specitems-1.5.2 → specitems-1.6.0}/README.md +0 -0
- {specitems-1.5.2 → specitems-1.6.0}/src/specitems/__init__.py +0 -0
- {specitems-1.5.2 → specitems-1.6.0}/src/specitems/cite.py +0 -0
- {specitems-1.5.2 → specitems-1.6.0}/src/specitems/clihash.py +0 -0
- {specitems-1.5.2 → specitems-1.6.0}/src/specitems/clipickle.py +0 -0
- {specitems-1.5.2 → specitems-1.6.0}/src/specitems/clispecdoc.py +0 -0
- {specitems-1.5.2 → specitems-1.6.0}/src/specitems/cliutil.py +0 -0
- {specitems-1.5.2 → specitems-1.6.0}/src/specitems/cliyamlquery.py +0 -0
- {specitems-1.5.2 → specitems-1.6.0}/src/specitems/content.py +0 -0
- {specitems-1.5.2 → specitems-1.6.0}/src/specitems/contentcommonmark.py +0 -0
- {specitems-1.5.2 → specitems-1.6.0}/src/specitems/contentmarkdown.py +0 -0
- {specitems-1.5.2 → specitems-1.6.0}/src/specitems/contentsphinx.py +0 -0
- {specitems-1.5.2 → specitems-1.6.0}/src/specitems/contenttext.py +0 -0
- {specitems-1.5.2 → specitems-1.6.0}/src/specitems/getvaluesubprocess.py +0 -0
- {specitems-1.5.2 → specitems-1.6.0}/src/specitems/glossary.py +0 -0
- {specitems-1.5.2 → specitems-1.6.0}/src/specitems/hashutil.py +0 -0
- {specitems-1.5.2 → specitems-1.6.0}/src/specitems/items.py +0 -0
- {specitems-1.5.2 → specitems-1.6.0}/src/specitems/py.typed +0 -0
- {specitems-1.5.2 → specitems-1.6.0}/src/specitems/spec.pickle +0 -0
- {specitems-1.5.2 → specitems-1.6.0}/src/specitems/specdoc.py +0 -0
- {specitems-1.5.2 → specitems-1.6.0}/src/specitems/specverify.py +0 -0
- {specitems-1.5.2 → specitems-1.6.0}/src/specitems/subprocessaction.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: specitems
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.6.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
|
|
@@ -30,7 +30,6 @@ import copy
|
|
|
30
30
|
import dataclasses
|
|
31
31
|
import os
|
|
32
32
|
import re
|
|
33
|
-
import string
|
|
34
33
|
from typing import Any, Callable, Iterator, Optional
|
|
35
34
|
|
|
36
35
|
from .items import Item, ItemType
|
|
@@ -38,29 +37,44 @@ from .items import Item, ItemType
|
|
|
38
37
|
ItemGetValue = Callable[["ItemGetValueContext"], Any]
|
|
39
38
|
ItemGetValueMap = dict[str, tuple[ItemGetValue, Any]]
|
|
40
39
|
|
|
40
|
+
_VAR_NAME = "(?:[a-zA-Z0-9._/-]+|\\*):[\\[\\]a-zA-Z0-9._/-]+(?::[^${}]*)?"
|
|
41
|
+
_VAR_SINGLE = re.compile(f"^[$@]\\{{{_VAR_NAME}\\}}$")
|
|
42
|
+
_VAR_TOKENS = re.compile(r"(?:\$\$(?=\{|\$\{))|(?:@@(?=\{|@\{))|"
|
|
43
|
+
f"[$@]\\{{{_VAR_NAME}\\}}|(?:[$@]\\{{)")
|
|
41
44
|
|
|
42
|
-
class _ItemTemplate(string.Template):
|
|
43
|
-
""" String template for item mapper identifiers. """
|
|
44
|
-
idpattern = "(?:[a-zA-Z0-9._/-]+|\\*):[\\[\\]a-zA-Z0-9._/-]+(?::[^${}]*)?"
|
|
45
45
|
|
|
46
|
+
class _ItemMapperError(Exception):
|
|
46
47
|
|
|
47
|
-
|
|
48
|
+
def __init__(self, start: int, end: int) -> None:
|
|
49
|
+
super().__init__()
|
|
50
|
+
self.start = start
|
|
51
|
+
self.end = end
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class _ItemMapperContext:
|
|
48
55
|
"""
|
|
49
56
|
Provides a context to map identifiers to items and attribute values.
|
|
50
57
|
"""
|
|
51
58
|
|
|
59
|
+
# pylint: disable=too-few-public-methods
|
|
52
60
|
def __init__(self, mapper: "ItemMapper", item: Optional[Item],
|
|
53
61
|
prefix: str) -> None:
|
|
54
|
-
super().__init__()
|
|
55
62
|
self._mapper = mapper
|
|
56
63
|
self._item = item
|
|
57
64
|
self._prefix = prefix
|
|
58
65
|
|
|
59
|
-
def
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
66
|
+
def replace(self, mobj: re.Match) -> str:
|
|
67
|
+
""" Replace the match. """
|
|
68
|
+
token = mobj.group(0)
|
|
69
|
+
if len(token) > 2:
|
|
70
|
+
try:
|
|
71
|
+
return str(
|
|
72
|
+
self._mapper.map(token[2:-1], self._item, self._prefix)[2])
|
|
73
|
+
except Exception as err:
|
|
74
|
+
raise _ItemMapperError(mobj.start(), mobj.end()) from err
|
|
75
|
+
if token[1] == "{":
|
|
76
|
+
raise _ItemMapperError(mobj.start(), mobj.end())
|
|
77
|
+
return token[0]
|
|
64
78
|
|
|
65
79
|
|
|
66
80
|
class _GetValueDictionary(dict):
|
|
@@ -464,13 +478,16 @@ class ItemMapper(abc.ABC):
|
|
|
464
478
|
"""
|
|
465
479
|
if not text:
|
|
466
480
|
return ""
|
|
481
|
+
context = _ItemMapperContext(self, item, prefix)
|
|
467
482
|
try:
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
483
|
+
return _VAR_TOKENS.sub(context.replace, text)
|
|
484
|
+
except _ItemMapperError as err:
|
|
485
|
+
start = max(text.count("\n", 0, err.start) - 3, 0)
|
|
486
|
+
end = text.count("\n", 0, err.end) + 4
|
|
471
487
|
spec = self.item.spec if item is None else item.spec
|
|
472
|
-
enumerated = "\n".join(
|
|
473
|
-
|
|
488
|
+
enumerated = "\n".join(
|
|
489
|
+
f"{i + start + 1}: {line}"
|
|
490
|
+
for i, line in enumerate(text.splitlines()[start:end]))
|
|
474
491
|
msg = (f"substitution for {spec} using prefix '{prefix}' "
|
|
475
492
|
f"failed for text:\n{enumerated}")
|
|
476
493
|
raise ValueError(msg) from err
|
|
@@ -490,7 +507,7 @@ class ItemMapper(abc.ABC):
|
|
|
490
507
|
for index, element in enumerate(data):
|
|
491
508
|
prefix_2 = f"{prefix}[{index}]"
|
|
492
509
|
if isinstance(element, str):
|
|
493
|
-
match =
|
|
510
|
+
match = _VAR_SINGLE.search(element)
|
|
494
511
|
if match:
|
|
495
512
|
new_element = self.map(element[2:-1], item,
|
|
496
513
|
prefix_2)[2]
|
|
@@ -537,7 +554,7 @@ class ItemMapper(abc.ABC):
|
|
|
537
554
|
element = self.substitute_data(element["value"], item,
|
|
538
555
|
prefix_2)
|
|
539
556
|
elif isinstance(element, str):
|
|
540
|
-
if
|
|
557
|
+
if _VAR_SINGLE.search(element):
|
|
541
558
|
element = self.map(element[2:-1], item, prefix_2)[2]
|
|
542
559
|
else:
|
|
543
560
|
element = self.substitute(element, item, prefix_2)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|