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
ommlds/minichain/_typedvalues.py
CHANGED
|
@@ -23,14 +23,21 @@ def _tv_field_coercer(
|
|
|
23
23
|
) -> ta.Callable[[ta.Sequence], tv.TypedValues]:
|
|
24
24
|
if isinstance(tvc, tuple):
|
|
25
25
|
check.arg(all(issubclass(e, tv.TypedValue) for e in tvc))
|
|
26
|
+
|
|
26
27
|
else:
|
|
27
28
|
check.issubclass(tvc, tv.TypedValue)
|
|
28
29
|
|
|
29
30
|
def inner(seq):
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
if isinstance(seq, tv.TypedValues):
|
|
32
|
+
for e in seq:
|
|
33
|
+
check.isinstance(e, tvc)
|
|
34
|
+
return seq
|
|
35
|
+
|
|
36
|
+
else:
|
|
37
|
+
return tv.TypedValues(*[
|
|
38
|
+
check.isinstance(e, tvc)
|
|
39
|
+
for e in check.isinstance(seq, ta.Sequence)
|
|
40
|
+
])
|
|
34
41
|
|
|
35
42
|
return inner
|
|
36
43
|
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import typing as ta
|
|
2
|
+
|
|
3
|
+
from ..content.content import Content
|
|
4
|
+
from ..content.transform.strings import transform_content_strings
|
|
5
|
+
from .messages import AiMessage
|
|
6
|
+
from .messages import Message
|
|
7
|
+
from .messages import SystemMessage
|
|
8
|
+
from .messages import ToolUseMessage
|
|
9
|
+
from .messages import ToolUseResultMessage
|
|
10
|
+
from .messages import UserMessage
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
MessageT = ta.TypeVar('MessageT', bound=Message)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
##
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def transform_message_content(fn: ta.Callable[[Content], Content], m: MessageT) -> MessageT:
|
|
20
|
+
if isinstance(m, UserMessage):
|
|
21
|
+
return m.replace(c=fn(m.c))
|
|
22
|
+
|
|
23
|
+
elif isinstance(m, AiMessage):
|
|
24
|
+
return m.replace(c=fn(m.c))
|
|
25
|
+
|
|
26
|
+
elif isinstance(m, SystemMessage):
|
|
27
|
+
return m.replace(c=fn(m.c))
|
|
28
|
+
|
|
29
|
+
elif isinstance(m, ToolUseMessage):
|
|
30
|
+
# TODO: m.tu.args?
|
|
31
|
+
return m
|
|
32
|
+
|
|
33
|
+
elif isinstance(m, ToolUseResultMessage):
|
|
34
|
+
# TODO: m.tur.c?
|
|
35
|
+
return m
|
|
36
|
+
|
|
37
|
+
else:
|
|
38
|
+
raise TypeError(m)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def transform_message_content_strings(fn: ta.Callable[[str], str], m: MessageT) -> MessageT:
|
|
42
|
+
return transform_message_content(lambda c: transform_content_strings(fn, c), m)
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
"""
|
|
2
|
+
TODO:
|
|
3
|
+
- channel? reasoning / thinking?
|
|
4
|
+
"""
|
|
1
5
|
import operator
|
|
2
6
|
import typing as ta
|
|
3
7
|
|
|
@@ -5,13 +9,12 @@ from omlish import check
|
|
|
5
9
|
from omlish import dataclasses as dc
|
|
6
10
|
from omlish import lang
|
|
7
11
|
from omlish import marshal as msh
|
|
8
|
-
from omlish import typedvalues as tv
|
|
9
12
|
|
|
10
|
-
from ..
|
|
11
|
-
from ..
|
|
12
|
-
from ..metadata import MetadataContainer
|
|
13
|
+
from ..content.content import Content
|
|
14
|
+
from ..metadata import MetadataContainerDataclass
|
|
13
15
|
from ..tools.types import ToolUse
|
|
14
16
|
from ..tools.types import ToolUseResult
|
|
17
|
+
from .metadata import MessageMetadata
|
|
15
18
|
from .metadata import MessageMetadatas
|
|
16
19
|
|
|
17
20
|
|
|
@@ -23,7 +26,7 @@ msh.register_global_module_import('._marshal', __package__)
|
|
|
23
26
|
|
|
24
27
|
@dc.dataclass(frozen=True)
|
|
25
28
|
class Message( # noqa
|
|
26
|
-
|
|
29
|
+
MetadataContainerDataclass[MessageMetadatas],
|
|
27
30
|
lang.Abstract,
|
|
28
31
|
lang.Sealed,
|
|
29
32
|
):
|
|
@@ -31,18 +34,14 @@ class Message( # noqa
|
|
|
31
34
|
default=(),
|
|
32
35
|
kw_only=True,
|
|
33
36
|
repr=False,
|
|
34
|
-
metadata=_tv_field_metadata(
|
|
35
|
-
MessageMetadatas,
|
|
36
|
-
marshal_name='metadata',
|
|
37
|
-
),
|
|
38
37
|
)
|
|
39
38
|
|
|
40
|
-
|
|
41
|
-
def metadata(self) -> tv.TypedValues[MessageMetadatas]:
|
|
42
|
-
return check.isinstance(self._metadata, tv.TypedValues)
|
|
39
|
+
MetadataContainerDataclass._configure_metadata_field(_metadata, MessageMetadatas) # noqa
|
|
43
40
|
|
|
44
|
-
def
|
|
45
|
-
|
|
41
|
+
def replace(self, **kwargs: ta.Any) -> ta.Self:
|
|
42
|
+
if (n := dc.replace_is_not(self, **kwargs)) is self:
|
|
43
|
+
return self
|
|
44
|
+
return n.update_metadata(MessageOriginal(self), discard=[MessageOriginal], override=True)
|
|
46
45
|
|
|
47
46
|
|
|
48
47
|
Chat: ta.TypeAlias = ta.Sequence[Message]
|
|
@@ -51,6 +50,14 @@ Chat: ta.TypeAlias = ta.Sequence[Message]
|
|
|
51
50
|
##
|
|
52
51
|
|
|
53
52
|
|
|
53
|
+
@dc.dataclass(frozen=True)
|
|
54
|
+
class MessageOriginal(MessageMetadata, lang.Final):
|
|
55
|
+
c: Message
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
##
|
|
59
|
+
|
|
60
|
+
|
|
54
61
|
@dc.dataclass(frozen=True)
|
|
55
62
|
class AnyUserMessage(Message, lang.Abstract):
|
|
56
63
|
pass
|
|
@@ -4,7 +4,7 @@ from omlish import dataclasses as dc
|
|
|
4
4
|
from omlish import lang
|
|
5
5
|
from omlish import marshal as msh
|
|
6
6
|
|
|
7
|
-
from ...content.
|
|
7
|
+
from ...content.content import Content
|
|
8
8
|
from ...stream.services import StreamOptions
|
|
9
9
|
from ...types import Option
|
|
10
10
|
from ...types import Output
|
|
@@ -10,9 +10,9 @@ from omlish import dataclasses as dc
|
|
|
10
10
|
from omlish import lang
|
|
11
11
|
from omlish.text import templating as tpl
|
|
12
12
|
|
|
13
|
-
from ..content.transform.strings import transform_content_strings
|
|
14
13
|
from ..envs import Env
|
|
15
14
|
from ..envs import EnvKey
|
|
15
|
+
from .content import transform_message_content_strings
|
|
16
16
|
from .messages import Chat
|
|
17
17
|
from .messages import Message
|
|
18
18
|
|
|
@@ -81,7 +81,7 @@ class ChatTemplater:
|
|
|
81
81
|
t = self.d[s]
|
|
82
82
|
return t.render(tpl.Templater.Context(env))
|
|
83
83
|
|
|
84
|
-
return [
|
|
84
|
+
return [transform_message_content_strings(render_content_str, self.m)]
|
|
85
85
|
|
|
86
86
|
@dc.dataclass(frozen=True)
|
|
87
87
|
class _PlaceholderStep(_Step):
|
|
@@ -110,7 +110,7 @@ class ChatTemplater:
|
|
|
110
110
|
content_strs.add(s)
|
|
111
111
|
return s
|
|
112
112
|
|
|
113
|
-
|
|
113
|
+
transform_message_content_strings(visit_content_str, p.v)
|
|
114
114
|
|
|
115
115
|
d: dict[str, tpl.Templater] = {
|
|
116
116
|
s: self._template_factory(s)
|
|
@@ -26,7 +26,7 @@ class UuidAddingMessageTransform(MessageTransform):
|
|
|
26
26
|
|
|
27
27
|
def transform_message(self, m: Message) -> Chat:
|
|
28
28
|
if Uuid not in m.metadata:
|
|
29
|
-
m = m.
|
|
29
|
+
m = m.update_metadata(Uuid(self.uuid_factory()))
|
|
30
30
|
return [m]
|
|
31
31
|
|
|
32
32
|
|
|
@@ -36,7 +36,7 @@ class CreatedAtAddingMessageTransform(MessageTransform):
|
|
|
36
36
|
|
|
37
37
|
def transform_message(self, m: Message) -> Chat:
|
|
38
38
|
if CreatedAt not in m.metadata:
|
|
39
|
-
m = m.
|
|
39
|
+
m = m.update_metadata(CreatedAt(self.clock()))
|
|
40
40
|
return [m]
|
|
41
41
|
|
|
42
42
|
|
|
@@ -54,6 +54,6 @@ class OriginAddingMessageTransform(MessageTransform):
|
|
|
54
54
|
|
|
55
55
|
def transform_message(self, m: Message) -> Chat:
|
|
56
56
|
return [
|
|
57
|
-
o.
|
|
57
|
+
o.update_metadata(TransformedMessageOrigin(m)) if TransformedMessageOrigin not in o.metadata else m
|
|
58
58
|
for o in self.child.transform_message(m)
|
|
59
59
|
]
|
|
@@ -8,17 +8,26 @@ _msh.register_global_module_import('._marshal', __package__)
|
|
|
8
8
|
##
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
#
|
|
11
|
+
# These are all of the Content subtypes - it must all be imported before the conditional import.
|
|
12
12
|
|
|
13
13
|
from . import ( # noqa
|
|
14
14
|
code as _code,
|
|
15
|
+
composite as _composite,
|
|
16
|
+
content as _content,
|
|
15
17
|
dynamic as _dynamic,
|
|
18
|
+
emphasis as _emphasis,
|
|
16
19
|
images as _images,
|
|
17
20
|
json as _json,
|
|
21
|
+
link as _link,
|
|
22
|
+
markdown as _markdown,
|
|
23
|
+
namespaces as _namespaces,
|
|
24
|
+
placeholders as _placeholders,
|
|
18
25
|
quote as _quote,
|
|
19
26
|
raw as _raw,
|
|
27
|
+
recursive as _recursive,
|
|
20
28
|
section as _section,
|
|
21
29
|
sequence as _sequence,
|
|
30
|
+
standard as _standard,
|
|
22
31
|
tag as _tag,
|
|
23
32
|
templates as _templates,
|
|
24
33
|
text as _text,
|
|
@@ -7,24 +7,28 @@ from omlish import lang
|
|
|
7
7
|
from omlish import marshal as msh
|
|
8
8
|
from omlish import reflect as rfl
|
|
9
9
|
|
|
10
|
-
from .code import
|
|
11
|
-
from .
|
|
12
|
-
from .
|
|
13
|
-
from .
|
|
14
|
-
from .
|
|
10
|
+
from .code import BlockCodeContent
|
|
11
|
+
from .code import InlineCodeContent
|
|
12
|
+
from .content import BaseContent
|
|
13
|
+
from .content import Content
|
|
14
|
+
from .emphasis import BoldContent
|
|
15
|
+
from .emphasis import BoldItalicContent
|
|
16
|
+
from .emphasis import ItalicContent
|
|
17
|
+
from .images import ImageContent
|
|
18
|
+
from .json import JsonContent
|
|
19
|
+
from .link import LinkContent
|
|
20
|
+
from .markdown import MarkdownContent
|
|
21
|
+
from .quote import QuoteContent
|
|
15
22
|
from .raw import NON_STR_SINGLE_RAW_CONTENT_TYPES
|
|
16
23
|
from .raw import NonStrSingleRawContent
|
|
17
|
-
from .raw import RawContent
|
|
18
|
-
from .raw import SingleRawContent
|
|
19
|
-
from .section import SectionContent
|
|
20
|
-
from .sequence import BlockContent
|
|
21
|
-
from .sequence import InlineContent
|
|
22
|
-
from .sequence import ItemListContent
|
|
23
|
-
from .tag import TagContent
|
|
24
|
-
from .text import TextContent
|
|
25
|
-
from .types import CONTENT_TYPES # noqa
|
|
26
|
-
from .types import BaseContent
|
|
27
|
-
from .types import Content
|
|
24
|
+
from .raw import RawContent
|
|
25
|
+
from .raw import SingleRawContent
|
|
26
|
+
from .section import SectionContent
|
|
27
|
+
from .sequence import BlockContent
|
|
28
|
+
from .sequence import InlineContent
|
|
29
|
+
from .sequence import ItemListContent
|
|
30
|
+
from .tag import TagContent
|
|
31
|
+
from .text import TextContent
|
|
28
32
|
|
|
29
33
|
|
|
30
34
|
##
|
|
@@ -234,12 +238,21 @@ def _install_standard_marshaling() -> None:
|
|
|
234
238
|
BaseContent,
|
|
235
239
|
[
|
|
236
240
|
|
|
237
|
-
msh.Impl(
|
|
241
|
+
msh.Impl(InlineCodeContent, 'inline_code'),
|
|
242
|
+
msh.Impl(BlockCodeContent, 'block_code'),
|
|
243
|
+
|
|
244
|
+
msh.Impl(BoldContent, 'bold'),
|
|
245
|
+
msh.Impl(ItalicContent, 'italic'),
|
|
246
|
+
msh.Impl(BoldItalicContent, 'bold_italic'),
|
|
238
247
|
|
|
239
248
|
msh.Impl(ImageContent, 'image'),
|
|
240
249
|
|
|
241
250
|
msh.Impl(JsonContent, 'json'),
|
|
242
251
|
|
|
252
|
+
msh.Impl(LinkContent, 'link'),
|
|
253
|
+
|
|
254
|
+
msh.Impl(MarkdownContent, 'markdown'),
|
|
255
|
+
|
|
243
256
|
msh.Impl(QuoteContent, 'quote'),
|
|
244
257
|
|
|
245
258
|
msh.Impl(SectionContent, 'section'),
|
ommlds/minichain/content/code.py
CHANGED
|
@@ -2,16 +2,25 @@ 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 CodeContent(StandardContent,
|
|
11
|
+
class CodeContent(StandardContent, lang.Abstract):
|
|
13
12
|
s: str
|
|
14
13
|
|
|
15
14
|
_: dc.KW_ONLY
|
|
16
15
|
|
|
17
16
|
lang: str | None = None
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@dc.dataclass(frozen=True)
|
|
20
|
+
class InlineCodeContent(CodeContent, lang.Final):
|
|
21
|
+
pass
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@dc.dataclass(frozen=True)
|
|
25
|
+
class BlockCodeContent(CodeContent, lang.Final):
|
|
26
|
+
pass
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import abc
|
|
2
|
+
import typing as ta
|
|
3
|
+
|
|
4
|
+
from omlish import dataclasses as dc
|
|
5
|
+
from omlish import lang
|
|
6
|
+
|
|
7
|
+
from .content import Content
|
|
8
|
+
from .standard import StandardContent
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
##
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dc.dataclass(frozen=True)
|
|
15
|
+
class CompositeContent(StandardContent, lang.Abstract):
|
|
16
|
+
@abc.abstractmethod
|
|
17
|
+
def child_content(self) -> ta.Sequence[Content]:
|
|
18
|
+
raise NotImplementedError
|
|
19
|
+
|
|
20
|
+
@abc.abstractmethod
|
|
21
|
+
def _replace_child_content(self, new_child_content: ta.Sequence[Content]) -> ta.Self:
|
|
22
|
+
raise NotImplementedError
|
|
23
|
+
|
|
24
|
+
def replace_child_content(self, new_child_content: ta.Sequence[Content]) -> ta.Self:
|
|
25
|
+
if lang.seqs_identical(new_child_content, self.child_content()):
|
|
26
|
+
return self
|
|
27
|
+
|
|
28
|
+
return self._replace_child_content(new_child_content)
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from omlish import dataclasses as dc
|
|
2
|
+
from omlish import lang
|
|
3
|
+
|
|
4
|
+
from .standard import StandardContent
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
##
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dc.dataclass(frozen=True)
|
|
11
|
+
class EmphasisContent(StandardContent, lang.Abstract):
|
|
12
|
+
s: str
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@dc.dataclass(frozen=True)
|
|
16
|
+
class BoldContent(EmphasisContent, lang.Final):
|
|
17
|
+
pass
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@dc.dataclass(frozen=True)
|
|
21
|
+
class ItalicContent(EmphasisContent, lang.Final):
|
|
22
|
+
pass
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@dc.dataclass(frozen=True)
|
|
26
|
+
class BoldItalicContent(EmphasisContent, lang.Final):
|
|
27
|
+
pass
|
|
@@ -9,7 +9,6 @@ from omlish import dataclasses as dc
|
|
|
9
9
|
from omlish import lang
|
|
10
10
|
|
|
11
11
|
from .standard import StandardContent
|
|
12
|
-
from .types import LeafContent
|
|
13
12
|
|
|
14
13
|
|
|
15
14
|
if ta.TYPE_CHECKING:
|
|
@@ -22,5 +21,5 @@ else:
|
|
|
22
21
|
|
|
23
22
|
|
|
24
23
|
@dc.dataclass(frozen=True)
|
|
25
|
-
class ImageContent(StandardContent,
|
|
24
|
+
class ImageContent(StandardContent, lang.Final):
|
|
26
25
|
i: 'pimg.Image' = dc.field()
|
ommlds/minichain/content/json.py
CHANGED
|
@@ -3,12 +3,11 @@ from omlish import lang
|
|
|
3
3
|
|
|
4
4
|
from ..json import JsonValue
|
|
5
5
|
from .standard import StandardContent
|
|
6
|
-
from .types import LeafContent
|
|
7
6
|
|
|
8
7
|
|
|
9
8
|
##
|
|
10
9
|
|
|
11
10
|
|
|
12
11
|
@dc.dataclass(frozen=True)
|
|
13
|
-
class JsonContent(StandardContent,
|
|
12
|
+
class JsonContent(StandardContent, lang.Final):
|
|
14
13
|
v: JsonValue
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import typing as ta
|
|
2
2
|
|
|
3
|
+
from omlish import dataclasses as dc
|
|
3
4
|
from omlish import lang
|
|
4
5
|
|
|
5
6
|
from ..metadata import CommonMetadata
|
|
6
7
|
from ..metadata import Metadata
|
|
8
|
+
from .content import Content
|
|
7
9
|
|
|
8
10
|
|
|
9
11
|
##
|
|
@@ -14,3 +16,11 @@ class ContentMetadata(Metadata, lang.Abstract):
|
|
|
14
16
|
|
|
15
17
|
|
|
16
18
|
ContentMetadatas: ta.TypeAlias = ContentMetadata | CommonMetadata
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
##
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@dc.dataclass(frozen=True)
|
|
25
|
+
class ContentOriginal(ContentMetadata, lang.Final):
|
|
26
|
+
c: Content
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
from omlish import dataclasses as dc
|
|
2
2
|
from omlish import lang
|
|
3
3
|
|
|
4
|
-
from .
|
|
5
|
-
from .types import LeafContent
|
|
4
|
+
from .recursive import RecursiveContent
|
|
6
5
|
|
|
7
6
|
|
|
8
7
|
##
|
|
@@ -13,5 +12,5 @@ class ContentNamespace(lang.Namespace, lang.Abstract):
|
|
|
13
12
|
|
|
14
13
|
|
|
15
14
|
@dc.dataclass(frozen=True)
|
|
16
|
-
class NamespaceContent(
|
|
15
|
+
class NamespaceContent(RecursiveContent, lang.Final):
|
|
17
16
|
ns: type[ContentNamespace]
|
|
@@ -3,8 +3,7 @@ import typing as ta
|
|
|
3
3
|
from omlish import dataclasses as dc
|
|
4
4
|
from omlish import lang
|
|
5
5
|
|
|
6
|
-
from .
|
|
7
|
-
from .types import LeafContent
|
|
6
|
+
from .recursive import RecursiveContent
|
|
8
7
|
|
|
9
8
|
|
|
10
9
|
##
|
|
@@ -18,5 +17,5 @@ PlaceholderContentKey: ta.TypeAlias = str | type[ContentPlaceholder]
|
|
|
18
17
|
|
|
19
18
|
|
|
20
19
|
@dc.dataclass(frozen=True)
|
|
21
|
-
class PlaceholderContent(
|
|
20
|
+
class PlaceholderContent(RecursiveContent, lang.Final):
|
|
22
21
|
k: PlaceholderContentKey
|
|
@@ -2,16 +2,25 @@
|
|
|
2
2
|
TODO:
|
|
3
3
|
- attribution
|
|
4
4
|
"""
|
|
5
|
+
import typing as ta
|
|
6
|
+
|
|
7
|
+
from omlish import check
|
|
5
8
|
from omlish import dataclasses as dc
|
|
6
9
|
from omlish import lang
|
|
7
10
|
|
|
8
|
-
from .
|
|
9
|
-
from .
|
|
11
|
+
from .composite import CompositeContent
|
|
12
|
+
from .content import Content
|
|
10
13
|
|
|
11
14
|
|
|
12
15
|
##
|
|
13
16
|
|
|
14
17
|
|
|
15
18
|
@dc.dataclass(frozen=True)
|
|
16
|
-
class QuoteContent(
|
|
19
|
+
class QuoteContent(CompositeContent, lang.Final):
|
|
17
20
|
body: Content
|
|
21
|
+
|
|
22
|
+
def child_content(self) -> ta.Sequence[Content]:
|
|
23
|
+
return [self.body]
|
|
24
|
+
|
|
25
|
+
def _replace_child_content(self, new_child_content: ta.Sequence[Content]) -> ta.Self:
|
|
26
|
+
return self.replace(body=check.single(new_child_content))
|
|
@@ -1,14 +1,26 @@
|
|
|
1
|
+
import typing as ta
|
|
2
|
+
|
|
3
|
+
from omlish import check
|
|
1
4
|
from omlish import dataclasses as dc
|
|
2
5
|
from omlish import lang
|
|
3
6
|
|
|
4
|
-
from .
|
|
5
|
-
from .
|
|
7
|
+
from .composite import CompositeContent
|
|
8
|
+
from .content import Content
|
|
6
9
|
|
|
7
10
|
|
|
8
11
|
##
|
|
9
12
|
|
|
10
13
|
|
|
11
14
|
@dc.dataclass(frozen=True)
|
|
12
|
-
class SectionContent(
|
|
13
|
-
header: str
|
|
15
|
+
class SectionContent(CompositeContent, lang.Final):
|
|
14
16
|
body: Content
|
|
17
|
+
|
|
18
|
+
_: dc.KW_ONLY
|
|
19
|
+
|
|
20
|
+
header: str | None
|
|
21
|
+
|
|
22
|
+
def child_content(self) -> ta.Sequence[Content]:
|
|
23
|
+
return [self.body]
|
|
24
|
+
|
|
25
|
+
def _replace_child_content(self, new_child_content: ta.Sequence[Content]) -> ta.Self:
|
|
26
|
+
return self.replace(body=check.single(new_child_content))
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"""
|
|
2
2
|
TODO:
|
|
3
|
+
- ... does inline have *any* separator? generic whitespace when content is stripped?
|
|
3
4
|
- track BlockContent nesting depth?
|
|
4
5
|
- section names? dedicated 'section' content with header and body?
|
|
5
6
|
"""
|
|
@@ -8,17 +9,23 @@ import typing as ta
|
|
|
8
9
|
from omlish import dataclasses as dc
|
|
9
10
|
from omlish import lang
|
|
10
11
|
|
|
11
|
-
from .
|
|
12
|
-
from .
|
|
12
|
+
from .composite import CompositeContent
|
|
13
|
+
from .content import Content
|
|
13
14
|
|
|
14
15
|
|
|
15
16
|
##
|
|
16
17
|
|
|
17
18
|
|
|
18
19
|
@dc.dataclass(frozen=True)
|
|
19
|
-
class SequenceContent(
|
|
20
|
+
class SequenceContent(CompositeContent, lang.Abstract):
|
|
20
21
|
l: ta.Sequence[Content]
|
|
21
22
|
|
|
23
|
+
def child_content(self) -> ta.Sequence[Content]:
|
|
24
|
+
return self.l
|
|
25
|
+
|
|
26
|
+
def _replace_child_content(self, new_child_content: ta.Sequence[Content]) -> ta.Self:
|
|
27
|
+
return self.replace(l=new_child_content)
|
|
28
|
+
|
|
22
29
|
|
|
23
30
|
@dc.dataclass(frozen=True)
|
|
24
31
|
class InlineContent(SequenceContent, lang.Final):
|
|
@@ -32,4 +39,6 @@ class BlockContent(SequenceContent, lang.Final):
|
|
|
32
39
|
|
|
33
40
|
@dc.dataclass(frozen=True)
|
|
34
41
|
class ItemListContent(SequenceContent, lang.Final):
|
|
35
|
-
|
|
42
|
+
_: dc.KW_ONLY
|
|
43
|
+
|
|
44
|
+
style: ta.Literal['-', '#'] = '-'
|