ommlds 0.0.0.dev496__py3-none-any.whl → 0.0.0.dev498__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.
- ommlds/.omlish-manifests.json +1 -1
- ommlds/cli/main.py +2 -2
- ommlds/cli/secrets.py +1 -1
- ommlds/minichain/__init__.py +45 -9
- ommlds/minichain/_dataclasses.py +1229 -1071
- ommlds/minichain/_typedvalues.py +11 -4
- ommlds/minichain/chat/content.py +42 -0
- ommlds/minichain/chat/messages.py +21 -14
- ommlds/minichain/chat/stream/types.py +1 -1
- ommlds/minichain/chat/templating.py +3 -3
- ommlds/minichain/chat/transforms/metadata.py +3 -3
- ommlds/minichain/content/__init__.py +10 -1
- ommlds/minichain/content/_marshal.py +30 -17
- ommlds/minichain/content/code.py +11 -2
- ommlds/minichain/content/composite.py +28 -0
- ommlds/minichain/content/{types.py → content.py} +0 -4
- ommlds/minichain/content/emphasis.py +27 -0
- ommlds/minichain/content/images.py +1 -2
- ommlds/minichain/content/json.py +1 -2
- ommlds/minichain/content/link.py +13 -0
- ommlds/minichain/content/markdown.py +12 -0
- ommlds/minichain/content/metadata.py +10 -0
- ommlds/minichain/content/namespaces.py +2 -3
- ommlds/minichain/content/placeholders.py +2 -3
- ommlds/minichain/content/quote.py +12 -3
- ommlds/minichain/content/recursive.py +12 -0
- ommlds/minichain/content/section.py +16 -4
- ommlds/minichain/content/sequence.py +13 -4
- ommlds/minichain/content/standard.py +10 -15
- ommlds/minichain/content/tag.py +12 -3
- ommlds/minichain/content/templates.py +1 -2
- ommlds/minichain/content/text.py +1 -2
- ommlds/minichain/content/transform/json.py +55 -0
- ommlds/minichain/content/transform/markdown.py +8 -0
- ommlds/minichain/content/transform/materialize.py +19 -78
- ommlds/minichain/content/transform/metadata.py +16 -0
- ommlds/minichain/content/transform/prepare.py +1 -5
- ommlds/minichain/content/transform/recursive.py +97 -0
- ommlds/minichain/content/transform/standard.py +43 -0
- ommlds/minichain/content/transform/stringify.py +1 -1
- ommlds/minichain/content/transform/strings.py +16 -7
- ommlds/minichain/content/transform/templates.py +25 -0
- ommlds/minichain/content/visitors.py +231 -0
- ommlds/minichain/metadata.py +58 -1
- ommlds/minichain/tools/execution/catalog.py +1 -1
- ommlds/minichain/tools/execution/errorhandling.py +3 -2
- ommlds/minichain/tools/execution/errors.py +1 -1
- ommlds/minichain/tools/execution/executors.py +1 -1
- ommlds/minichain/tools/fns.py +1 -1
- ommlds/minichain/tools/reflect.py +1 -1
- ommlds/minichain/tools/types.py +1 -1
- ommlds/minichain/vectors/embeddings.py +1 -1
- ommlds/tools/git.py +74 -63
- {ommlds-0.0.0.dev496.dist-info → ommlds-0.0.0.dev498.dist-info}/METADATA +4 -4
- {ommlds-0.0.0.dev496.dist-info → ommlds-0.0.0.dev498.dist-info}/RECORD +59 -49
- ommlds/minichain/content/transform/base.py +0 -63
- ommlds/minichain/content/transform/interleave.py +0 -68
- ommlds/minichain/content/transform/squeeze.py +0 -59
- {ommlds-0.0.0.dev496.dist-info → ommlds-0.0.0.dev498.dist-info}/WHEEL +0 -0
- {ommlds-0.0.0.dev496.dist-info → ommlds-0.0.0.dev498.dist-info}/entry_points.txt +0 -0
- {ommlds-0.0.0.dev496.dist-info → ommlds-0.0.0.dev498.dist-info}/licenses/LICENSE +0 -0
- {ommlds-0.0.0.dev496.dist-info → ommlds-0.0.0.dev498.dist-info}/top_level.txt +0 -0
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
import typing as ta
|
|
2
2
|
|
|
3
|
-
from omlish import check
|
|
4
3
|
from omlish import dataclasses as dc
|
|
5
4
|
from omlish import lang
|
|
6
|
-
from omlish import typedvalues as tv
|
|
7
5
|
|
|
8
|
-
from ..
|
|
9
|
-
from
|
|
6
|
+
from ..metadata import MetadataContainerDataclass
|
|
7
|
+
from .content import BaseContent
|
|
10
8
|
from .metadata import ContentMetadatas
|
|
11
|
-
from .
|
|
9
|
+
from .metadata import ContentOriginal
|
|
12
10
|
|
|
13
11
|
|
|
14
12
|
##
|
|
@@ -16,22 +14,19 @@ from .types import BaseContent
|
|
|
16
14
|
|
|
17
15
|
@dc.dataclass(frozen=True)
|
|
18
16
|
class StandardContent( # noqa
|
|
19
|
-
|
|
17
|
+
MetadataContainerDataclass[ContentMetadatas],
|
|
20
18
|
BaseContent,
|
|
21
19
|
lang.Abstract,
|
|
22
20
|
):
|
|
23
21
|
_metadata: ta.Sequence[ContentMetadatas] = dc.field(
|
|
24
22
|
default=(),
|
|
25
23
|
kw_only=True,
|
|
26
|
-
|
|
27
|
-
ContentMetadatas,
|
|
28
|
-
marshal_name='metadata',
|
|
29
|
-
),
|
|
24
|
+
repr=False,
|
|
30
25
|
)
|
|
31
26
|
|
|
32
|
-
|
|
33
|
-
def metadata(self) -> tv.TypedValues[ContentMetadatas]:
|
|
34
|
-
return check.isinstance(self._metadata, tv.TypedValues)
|
|
27
|
+
MetadataContainerDataclass._configure_metadata_field(_metadata, ContentMetadatas) # noqa
|
|
35
28
|
|
|
36
|
-
def
|
|
37
|
-
|
|
29
|
+
def replace(self, **kwargs: ta.Any) -> ta.Self:
|
|
30
|
+
if (n := dc.replace_is_not(self, **kwargs)) is self:
|
|
31
|
+
return self
|
|
32
|
+
return n.update_metadata(ContentOriginal(self), discard=[ContentOriginal], override=True)
|
ommlds/minichain/content/tag.py
CHANGED
|
@@ -3,17 +3,26 @@ TODO:
|
|
|
3
3
|
- track BlockContent nesting depth?
|
|
4
4
|
- section names? dedicated 'section' content with header and body?
|
|
5
5
|
"""
|
|
6
|
+
import typing as ta
|
|
7
|
+
|
|
8
|
+
from omlish import check
|
|
6
9
|
from omlish import dataclasses as dc
|
|
7
10
|
from omlish import lang
|
|
8
11
|
|
|
9
|
-
from .
|
|
10
|
-
from .
|
|
12
|
+
from .composite import CompositeContent
|
|
13
|
+
from .content import Content
|
|
11
14
|
|
|
12
15
|
|
|
13
16
|
##
|
|
14
17
|
|
|
15
18
|
|
|
16
19
|
@dc.dataclass(frozen=True)
|
|
17
|
-
class TagContent(
|
|
20
|
+
class TagContent(CompositeContent, lang.Final):
|
|
18
21
|
tag: str
|
|
19
22
|
body: Content
|
|
23
|
+
|
|
24
|
+
def child_content(self) -> ta.Sequence[Content]:
|
|
25
|
+
return [self.body]
|
|
26
|
+
|
|
27
|
+
def _replace_child_content(self, new_child_content: ta.Sequence[Content]) -> ta.Self:
|
|
28
|
+
return self.replace(body=check.single(new_child_content))
|
|
@@ -3,12 +3,11 @@ from omlish import lang
|
|
|
3
3
|
from omlish.text import templating as tpl
|
|
4
4
|
|
|
5
5
|
from .dynamic import DynamicContent
|
|
6
|
-
from .types import LeafContent
|
|
7
6
|
|
|
8
7
|
|
|
9
8
|
##
|
|
10
9
|
|
|
11
10
|
|
|
12
11
|
@dc.dataclass(frozen=True)
|
|
13
|
-
class TemplateContent(DynamicContent,
|
|
12
|
+
class TemplateContent(DynamicContent, lang.Final):
|
|
14
13
|
t: tpl.Templater
|
ommlds/minichain/content/text.py
CHANGED
|
@@ -2,12 +2,11 @@ from omlish import dataclasses as dc
|
|
|
2
2
|
from omlish import lang
|
|
3
3
|
|
|
4
4
|
from .standard import StandardContent
|
|
5
|
-
from .types import LeafContent
|
|
6
5
|
|
|
7
6
|
|
|
8
7
|
##
|
|
9
8
|
|
|
10
9
|
|
|
11
10
|
@dc.dataclass(frozen=True)
|
|
12
|
-
class TextContent(StandardContent,
|
|
11
|
+
class TextContent(StandardContent, lang.Final):
|
|
13
12
|
s: str
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import typing as ta
|
|
2
|
+
|
|
3
|
+
from omlish.formats import json
|
|
4
|
+
|
|
5
|
+
from ..code import BlockCodeContent
|
|
6
|
+
from ..code import InlineCodeContent
|
|
7
|
+
from ..json import JsonContent
|
|
8
|
+
from ..metadata import ContentOriginal
|
|
9
|
+
from ..standard import StandardContent
|
|
10
|
+
from ..text import TextContent
|
|
11
|
+
from ..visitors import ContentTransform
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
##
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class JsonContentRenderer(ContentTransform[None]):
|
|
18
|
+
def __init__(
|
|
19
|
+
self,
|
|
20
|
+
*,
|
|
21
|
+
backend: json.Backend | None = None,
|
|
22
|
+
mode: ta.Literal['pretty', 'compact', 'normal'] = 'pretty',
|
|
23
|
+
code: ta.Literal['inline', 'block', None] = None,
|
|
24
|
+
) -> None:
|
|
25
|
+
super().__init__()
|
|
26
|
+
|
|
27
|
+
if backend is None:
|
|
28
|
+
backend = json.default_backend()
|
|
29
|
+
self._backend = backend
|
|
30
|
+
self._mode = mode
|
|
31
|
+
self._code = code
|
|
32
|
+
|
|
33
|
+
def visit_json_content(self, c: JsonContent, ctx: None) -> StandardContent:
|
|
34
|
+
match self._mode:
|
|
35
|
+
case 'pretty':
|
|
36
|
+
s = self._backend.dumps_pretty(c.v)
|
|
37
|
+
case 'compact':
|
|
38
|
+
s = self._backend.dumps_compact(c.v)
|
|
39
|
+
case 'normal':
|
|
40
|
+
s = self._backend.dumps(c.v)
|
|
41
|
+
case _:
|
|
42
|
+
raise ValueError(self._mode)
|
|
43
|
+
|
|
44
|
+
nc: StandardContent
|
|
45
|
+
match self._code:
|
|
46
|
+
case 'inline':
|
|
47
|
+
nc = InlineCodeContent(s, lang='json')
|
|
48
|
+
case 'block':
|
|
49
|
+
nc = BlockCodeContent(s, lang='json')
|
|
50
|
+
case None:
|
|
51
|
+
nc = TextContent(s)
|
|
52
|
+
case _:
|
|
53
|
+
raise ValueError(self._code)
|
|
54
|
+
|
|
55
|
+
return nc.update_metadata(ContentOriginal(c))
|
|
@@ -1,110 +1,51 @@
|
|
|
1
|
-
import
|
|
1
|
+
import abc
|
|
2
2
|
|
|
3
|
-
from omlish import
|
|
4
|
-
from omlish import dataclasses as dc
|
|
3
|
+
from omlish import lang
|
|
5
4
|
from omlish.text import templating as tpl
|
|
6
5
|
|
|
7
|
-
from ..
|
|
8
|
-
from
|
|
9
|
-
from
|
|
10
|
-
from
|
|
11
|
-
from ..types import Content
|
|
12
|
-
from .base import ContentTransform
|
|
6
|
+
from ..content import Content
|
|
7
|
+
from .recursive import PlaceholderContents
|
|
8
|
+
from .recursive import RecursiveContentMaterializer
|
|
9
|
+
from .templates import TemplateContentMaterializer
|
|
13
10
|
|
|
14
11
|
|
|
15
12
|
##
|
|
16
13
|
|
|
17
14
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
@dc.dataclass()
|
|
24
|
-
class PlaceholderContentMissingError(Exception):
|
|
25
|
-
key: PlaceholderContentKey
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
def _make_placeholder_content_fn(cps: PlaceholderContents | None = None) -> PlaceholderContentFn:
|
|
29
|
-
if cps is None:
|
|
30
|
-
def none_fn(cpk: PlaceholderContentKey) -> Content:
|
|
31
|
-
raise PlaceholderContentMissingError(cpk)
|
|
32
|
-
|
|
33
|
-
return none_fn
|
|
34
|
-
|
|
35
|
-
elif isinstance(cps, ta.Mapping):
|
|
36
|
-
def mapping_fn(cpk: PlaceholderContentKey) -> Content:
|
|
37
|
-
try:
|
|
38
|
-
return cps[cpk]
|
|
39
|
-
except KeyError:
|
|
40
|
-
raise PlaceholderContentMissingError(cpk) from None
|
|
41
|
-
|
|
42
|
-
return mapping_fn
|
|
43
|
-
|
|
44
|
-
elif callable(cps):
|
|
45
|
-
return cps
|
|
46
|
-
|
|
47
|
-
else:
|
|
48
|
-
raise TypeError(cps)
|
|
15
|
+
class ContentMaterializer(lang.Abstract):
|
|
16
|
+
@abc.abstractmethod
|
|
17
|
+
def apply(self, c: Content) -> Content:
|
|
18
|
+
raise NotImplementedError
|
|
49
19
|
|
|
50
20
|
|
|
51
21
|
##
|
|
52
22
|
|
|
53
23
|
|
|
54
|
-
class
|
|
55
|
-
pass
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
class ContentMaterializer(ContentTransform):
|
|
59
|
-
DEFAULT_MAX_DEPTH: int = 8
|
|
60
|
-
|
|
24
|
+
class DefaultContentMaterializer(ContentMaterializer):
|
|
61
25
|
def __init__(
|
|
62
26
|
self,
|
|
63
27
|
*,
|
|
64
28
|
placeholder_contents: PlaceholderContents | None = None,
|
|
65
29
|
templater_context: tpl.Templater.Context | None = None,
|
|
66
|
-
max_depth: int = DEFAULT_MAX_DEPTH,
|
|
67
30
|
) -> None:
|
|
68
31
|
super().__init__()
|
|
69
32
|
|
|
33
|
+
self._placeholder_contents = placeholder_contents
|
|
70
34
|
self._templater_context = templater_context
|
|
71
|
-
self._placeholder_content_fn = _make_placeholder_content_fn(placeholder_contents)
|
|
72
|
-
self._max_depth = max_depth
|
|
73
|
-
|
|
74
|
-
self._cur_depth = 0
|
|
75
|
-
|
|
76
|
-
def recurse(self, o: Content) -> Content:
|
|
77
|
-
if self._cur_depth >= self._max_depth:
|
|
78
|
-
raise ContentDepthExceededError
|
|
79
|
-
|
|
80
|
-
self._cur_depth += 1
|
|
81
|
-
try:
|
|
82
|
-
return self.apply(o)
|
|
83
|
-
finally:
|
|
84
|
-
self._cur_depth -= 1
|
|
85
|
-
|
|
86
|
-
@ContentTransform.apply.register
|
|
87
|
-
def apply_namespace_content(self, c: NamespaceContent) -> Content:
|
|
88
|
-
check.issubclass(c.ns, ContentNamespace)
|
|
89
|
-
out: list[Content] = []
|
|
90
|
-
for n, e in c.ns:
|
|
91
|
-
if n.startswith('_'):
|
|
92
|
-
continue
|
|
93
|
-
out.append(self.recurse(e))
|
|
94
|
-
return out
|
|
95
35
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
36
|
+
def apply(self, c: Content) -> Content:
|
|
37
|
+
c = RecursiveContentMaterializer(self._placeholder_contents).visit(c, None)
|
|
38
|
+
c = TemplateContentMaterializer(self._templater_context).visit(c, None)
|
|
39
|
+
return c
|
|
99
40
|
|
|
100
41
|
|
|
101
42
|
def materialize_content(
|
|
102
|
-
|
|
43
|
+
c: Content,
|
|
103
44
|
*,
|
|
104
45
|
placeholder_contents: PlaceholderContents | None = None,
|
|
105
46
|
templater_context: tpl.Templater.Context | None = None,
|
|
106
47
|
) -> Content:
|
|
107
|
-
return
|
|
48
|
+
return DefaultContentMaterializer(
|
|
108
49
|
placeholder_contents=placeholder_contents,
|
|
109
50
|
templater_context=templater_context,
|
|
110
|
-
).apply(
|
|
51
|
+
).apply(c)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from ..content import Content
|
|
2
|
+
from ..metadata import ContentOriginal
|
|
3
|
+
from ..standard import StandardContent
|
|
4
|
+
from ..visitors import ContentTransform
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
##
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class OriginalMetadataStrippingContentTransform(ContentTransform[None]):
|
|
11
|
+
def visit_standard_content(self, c: StandardContent, ctx: None) -> StandardContent:
|
|
12
|
+
return c.discard_metadata(ContentOriginal)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def strip_content_original_metadata(c: Content) -> Content:
|
|
16
|
+
return OriginalMetadataStrippingContentTransform().visit(c, None)
|
|
@@ -8,10 +8,8 @@ import typing as ta
|
|
|
8
8
|
from omlish import dataclasses as dc
|
|
9
9
|
from omlish import lang
|
|
10
10
|
|
|
11
|
-
from ..
|
|
12
|
-
from .interleave import interleave_content
|
|
11
|
+
from ..content import Content
|
|
13
12
|
from .materialize import materialize_content
|
|
14
|
-
from .squeeze import squeeze_content
|
|
15
13
|
from .stringify import stringify_content
|
|
16
14
|
|
|
17
15
|
|
|
@@ -45,8 +43,6 @@ class DefaultContentPreparer(ContentPreparer):
|
|
|
45
43
|
|
|
46
44
|
def prepare(self, c: Content) -> Content:
|
|
47
45
|
c = materialize_content(c)
|
|
48
|
-
c = squeeze_content(c, strip_strings=self.strip_strings)
|
|
49
|
-
c = interleave_content(c, block_separator=self.block_separator)
|
|
50
46
|
return c
|
|
51
47
|
|
|
52
48
|
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import typing as ta
|
|
2
|
+
|
|
3
|
+
from omlish import check
|
|
4
|
+
from omlish import dataclasses as dc
|
|
5
|
+
|
|
6
|
+
from ..content import Content
|
|
7
|
+
from ..namespaces import ContentNamespace
|
|
8
|
+
from ..namespaces import NamespaceContent
|
|
9
|
+
from ..placeholders import PlaceholderContent
|
|
10
|
+
from ..placeholders import PlaceholderContentKey
|
|
11
|
+
from ..recursive import RecursiveContent
|
|
12
|
+
from ..visitors import ContentTransform
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
##
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
PlaceholderContentMap: ta.TypeAlias = ta.Mapping[PlaceholderContentKey, Content]
|
|
19
|
+
PlaceholderContentFn: ta.TypeAlias = ta.Callable[[PlaceholderContentKey], Content]
|
|
20
|
+
PlaceholderContents: ta.TypeAlias = PlaceholderContentMap | PlaceholderContentFn
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@dc.dataclass()
|
|
24
|
+
class PlaceholderContentMissingError(Exception):
|
|
25
|
+
key: PlaceholderContentKey
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _make_placeholder_content_fn(cps: PlaceholderContents | None = None) -> PlaceholderContentFn:
|
|
29
|
+
if cps is None:
|
|
30
|
+
def none_fn(cpk: PlaceholderContentKey) -> Content:
|
|
31
|
+
raise PlaceholderContentMissingError(cpk)
|
|
32
|
+
|
|
33
|
+
return none_fn
|
|
34
|
+
|
|
35
|
+
elif isinstance(cps, ta.Mapping):
|
|
36
|
+
def mapping_fn(cpk: PlaceholderContentKey) -> Content:
|
|
37
|
+
try:
|
|
38
|
+
return cps[cpk]
|
|
39
|
+
except KeyError:
|
|
40
|
+
raise PlaceholderContentMissingError(cpk) from None
|
|
41
|
+
|
|
42
|
+
return mapping_fn
|
|
43
|
+
|
|
44
|
+
elif callable(cps):
|
|
45
|
+
return cps
|
|
46
|
+
|
|
47
|
+
else:
|
|
48
|
+
raise TypeError(cps)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
##
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class RecursiveContentDepthExceededError(Exception):
|
|
55
|
+
pass
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class RecursiveContentMaterializer(ContentTransform[None]):
|
|
59
|
+
DEFAULT_MAX_DEPTH: int = 8
|
|
60
|
+
|
|
61
|
+
def __init__(
|
|
62
|
+
self,
|
|
63
|
+
placeholder_contents: PlaceholderContents | None = None,
|
|
64
|
+
*,
|
|
65
|
+
max_depth: int = DEFAULT_MAX_DEPTH,
|
|
66
|
+
) -> None:
|
|
67
|
+
super().__init__()
|
|
68
|
+
|
|
69
|
+
self._placeholder_content_fn = _make_placeholder_content_fn(placeholder_contents)
|
|
70
|
+
self._max_depth = max_depth
|
|
71
|
+
|
|
72
|
+
self._cur_depth = 0
|
|
73
|
+
|
|
74
|
+
def recurse(self, o: Content, ctx: None) -> Content:
|
|
75
|
+
if self._cur_depth >= self._max_depth:
|
|
76
|
+
raise RecursiveContentDepthExceededError
|
|
77
|
+
|
|
78
|
+
self._cur_depth += 1
|
|
79
|
+
try:
|
|
80
|
+
return self.visit(o, ctx)
|
|
81
|
+
finally:
|
|
82
|
+
self._cur_depth -= 1
|
|
83
|
+
|
|
84
|
+
def visit_recursive_content(self, c: RecursiveContent, ctx: None) -> Content:
|
|
85
|
+
raise TypeError(c)
|
|
86
|
+
|
|
87
|
+
def visit_namespace_content(self, c: NamespaceContent, ctx: None) -> Content:
|
|
88
|
+
check.issubclass(c.ns, ContentNamespace)
|
|
89
|
+
out: list[Content] = []
|
|
90
|
+
for n, e in c.ns:
|
|
91
|
+
if n.startswith('_'):
|
|
92
|
+
continue
|
|
93
|
+
out.append(self.recurse(e, ctx))
|
|
94
|
+
return out
|
|
95
|
+
|
|
96
|
+
def visit_placeholder_content(self, c: PlaceholderContent, ctx: None) -> Content:
|
|
97
|
+
return self.recurse(self._placeholder_content_fn(c.k), ctx)
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import collections.abc
|
|
2
|
+
import typing as ta
|
|
3
|
+
|
|
4
|
+
from omlish import check
|
|
5
|
+
|
|
6
|
+
from ..content import Content
|
|
7
|
+
from ..metadata import ContentOriginal
|
|
8
|
+
from ..sequence import BlockContent
|
|
9
|
+
from ..sequence import InlineContent
|
|
10
|
+
from ..sequence import SequenceContent
|
|
11
|
+
from ..text import TextContent
|
|
12
|
+
from ..visitors import ContentTransform
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
##
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class LiftToStandardContentTransform(ContentTransform[None]):
|
|
19
|
+
def __init__(
|
|
20
|
+
self,
|
|
21
|
+
*,
|
|
22
|
+
sequence_mode: ta.Literal['block', 'inline'] = 'block',
|
|
23
|
+
) -> None:
|
|
24
|
+
super().__init__()
|
|
25
|
+
|
|
26
|
+
self._sequence_mode = sequence_mode
|
|
27
|
+
|
|
28
|
+
def visit_str(self, s: str, ctx: None) -> Content:
|
|
29
|
+
return TextContent(s).update_metadata(ContentOriginal(s))
|
|
30
|
+
|
|
31
|
+
def visit_sequence(self, c: ta.Sequence[Content], ctx: None) -> Content:
|
|
32
|
+
cc = check.isinstance(super().visit_sequence(c, ctx), collections.abc.Sequence)
|
|
33
|
+
|
|
34
|
+
nc: SequenceContent
|
|
35
|
+
match self._sequence_mode:
|
|
36
|
+
case 'block':
|
|
37
|
+
nc = BlockContent(cc)
|
|
38
|
+
case 'inline':
|
|
39
|
+
nc = InlineContent(cc)
|
|
40
|
+
case _:
|
|
41
|
+
raise ValueError(self._sequence_mode)
|
|
42
|
+
|
|
43
|
+
return nc.update_metadata(ContentOriginal(c))
|
|
@@ -2,7 +2,11 @@ import typing as ta
|
|
|
2
2
|
|
|
3
3
|
from omlish import dataclasses as dc
|
|
4
4
|
|
|
5
|
-
from
|
|
5
|
+
from ..content import Content
|
|
6
|
+
from ..emphasis import EmphasisContent
|
|
7
|
+
from ..metadata import ContentOriginal
|
|
8
|
+
from ..text import TextContent
|
|
9
|
+
from ..visitors import ContentTransform
|
|
6
10
|
|
|
7
11
|
|
|
8
12
|
T = ta.TypeVar('T')
|
|
@@ -12,13 +16,18 @@ T = ta.TypeVar('T')
|
|
|
12
16
|
|
|
13
17
|
|
|
14
18
|
@dc.dataclass(frozen=True)
|
|
15
|
-
class StringFnContentTransform(ContentTransform):
|
|
19
|
+
class StringFnContentTransform(ContentTransform[None]):
|
|
16
20
|
fn: ta.Callable[[str], str]
|
|
17
21
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
return self.fn(s)
|
|
22
|
+
def visit_str(self, c: str, ctx: None) -> TextContent:
|
|
23
|
+
return TextContent(self.fn(c)).update_metadata(ContentOriginal(c))
|
|
21
24
|
|
|
25
|
+
def visit_text_content(self, c: TextContent, ctx: None) -> TextContent:
|
|
26
|
+
return c.replace(s=self.fn(c.s))
|
|
22
27
|
|
|
23
|
-
def
|
|
24
|
-
|
|
28
|
+
def visit_emphasis_content(self, c: EmphasisContent, ctx: None) -> EmphasisContent:
|
|
29
|
+
return c.replace(s=self.fn(c.s))
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def transform_content_strings(fn: ta.Callable[[str], str], o: Content) -> Content:
|
|
33
|
+
return StringFnContentTransform(fn).visit(o, None)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from omlish import check
|
|
2
|
+
from omlish.text import templating as tpl
|
|
3
|
+
|
|
4
|
+
from ..content import Content
|
|
5
|
+
from ..metadata import ContentOriginal
|
|
6
|
+
from ..templates import TemplateContent
|
|
7
|
+
from ..text import TextContent
|
|
8
|
+
from ..visitors import ContentTransform
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
##
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class TemplateContentMaterializer(ContentTransform[None]):
|
|
15
|
+
def __init__(
|
|
16
|
+
self,
|
|
17
|
+
templater_context: tpl.Templater.Context | None = None,
|
|
18
|
+
) -> None:
|
|
19
|
+
super().__init__()
|
|
20
|
+
|
|
21
|
+
self._templater_context = templater_context
|
|
22
|
+
|
|
23
|
+
def visit_template_content(self, c: TemplateContent, ctx: None) -> Content:
|
|
24
|
+
s = c.t.render(check.not_none(self._templater_context))
|
|
25
|
+
return TextContent(s).update_metadata(ContentOriginal(c))
|