roborean-documents-text 0.1.2__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.
@@ -0,0 +1,27 @@
1
+ venv/
2
+ venv-qt5/
3
+ venv-qt6/
4
+ .venv/
5
+ __pycache__/
6
+ *.py[cod]
7
+ .pytest_cache/
8
+ .mypy_cache/
9
+ .coverage
10
+ htmlcov/
11
+ dist/
12
+ build/
13
+ *.egg-info/
14
+ *.tsbuildinfo
15
+ node_modules/
16
+ .pnpm-store/
17
+ .DS_Store
18
+ .idea/
19
+ .vscode/*.local
20
+ playground/
21
+ .e2e-ai/
22
+ **/test-results/
23
+ **/playwright-report/
24
+ research/
25
+ .roborean/
26
+ .roborean-sql-artifacts/
27
+ *.db
@@ -0,0 +1,16 @@
1
+ # Changelog
2
+
3
+ ## [Unreleased]
4
+
5
+ ### Added
6
+
7
+ - `roborean.text` driver with `{{slot}}` replacement and plain text ops.
8
+
9
+ ### Changed
10
+
11
+ ### Fixed
12
+
13
+
14
+ - Lower inter-package dependency pins to `>=0.1.1` to match lockstep
15
+ release versions.
16
+ - Normalize template newlines to LF so rendered text is portable on Windows.
@@ -0,0 +1,10 @@
1
+ Metadata-Version: 2.4
2
+ Name: roborean-documents-text
3
+ Version: 0.1.2
4
+ Summary: Plain-text document driver for Roborean
5
+ Project-URL: Homepage, https://github.com/TNick/roborean
6
+ Project-URL: Repository, https://github.com/TNick/roborean
7
+ License-Expression: MIT
8
+ Requires-Python: >=3.11
9
+ Requires-Dist: roborean-documents-base>=0.1.1
10
+ Requires-Dist: roborean-spec>=0.1.1
@@ -0,0 +1,25 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "roborean-documents-text"
7
+ version = "0.1.2"
8
+ description = "Plain-text document driver for Roborean"
9
+ requires-python = ">=3.11"
10
+ license = "MIT"
11
+ dependencies = [
12
+ "roborean-documents-base>=0.1.1",
13
+ "roborean-spec>=0.1.1",
14
+ ]
15
+
16
+ [project.entry-points."roborean.document_drivers"]
17
+ "roborean.text" = "roborean_documents_text.driver:create_driver"
18
+
19
+
20
+ [project.urls]
21
+ Homepage = "https://github.com/TNick/roborean"
22
+ Repository = "https://github.com/TNick/roborean"
23
+
24
+ [tool.hatch.build.targets.wheel]
25
+ packages = ["src/roborean_documents_text"]
@@ -0,0 +1,122 @@
1
+ """Plain-text document driver."""
2
+
3
+ from dataclasses import dataclass, field
4
+ from datetime import UTC, datetime
5
+ from typing import Any, Mapping
6
+
7
+ from pydantic import TypeAdapter
8
+ from roborean_documents_base.capabilities import assert_op_allowed
9
+ from roborean_documents_base.resolve_values import public_literal_value
10
+ from roborean_spec import (
11
+ DocumentDriverManifest,
12
+ DocumentOperation,
13
+ DocumentPreview,
14
+ TemplateManifest,
15
+ WorkspaceValue,
16
+ )
17
+
18
+
19
+ @dataclass
20
+ class TextSession:
21
+ """In-memory text generation session."""
22
+
23
+ document_id: str
24
+ driver_id: str
25
+ body: str
26
+ ops_applied: list[dict[str, Any]] = field(default_factory=list)
27
+ finalized: bool = False
28
+
29
+
30
+ class TextDocumentDriver:
31
+ """UTF-8 text driver using Mustache-like ``{{slot}}`` replacement."""
32
+
33
+ driver_id = "roborean.text"
34
+ manifest = DocumentDriverManifest(
35
+ driverId="roborean.text",
36
+ version="0.3.0",
37
+ irFamily="plain",
38
+ capabilities=[
39
+ "set_metadata",
40
+ "replace_named_value",
41
+ "plain.append_text",
42
+ "plain.replace_all",
43
+ "finalize",
44
+ ],
45
+ supportsPreview=True,
46
+ supportsBrowserExecution=True,
47
+ supportsDiff=True,
48
+ requiresBackend=False,
49
+ templateMediaTypes=["text/plain"],
50
+ )
51
+
52
+ def __init__(self) -> None:
53
+ """Initialize empty template state."""
54
+ self._template = ""
55
+ self._manifest: TemplateManifest | None = None
56
+
57
+ def load_template(self, template_ref, *, store, manifest) -> None:
58
+ """Load UTF-8 template bytes."""
59
+ # Normalize newlines so Windows-checked-out templates stay portable.
60
+ text = store.load_bytes(template_ref).decode("utf-8")
61
+ self._template = text.replace("\r\n", "\n")
62
+ self._manifest = manifest
63
+
64
+ def begin_session(
65
+ self, workspace, metadata: Mapping[str, Any]
66
+ ) -> TextSession:
67
+ """Start a session from the loaded template."""
68
+ return TextSession(
69
+ document_id=str(metadata.get("documentId", "")),
70
+ driver_id=self.driver_id,
71
+ body=self._template,
72
+ )
73
+
74
+ def apply_operation(
75
+ self, session: TextSession, op: DocumentOperation
76
+ ) -> None:
77
+ """Apply one plain-text operation."""
78
+ assert_op_allowed(self.manifest, op)
79
+ data = op.model_dump(mode="python", by_alias=True)
80
+ session.ops_applied.append(op.model_dump(mode="json", by_alias=True))
81
+ if op.op == "replace_named_value":
82
+ value = TypeAdapter(WorkspaceValue).validate_python(data["value"])
83
+ session.body = session.body.replace(
84
+ "{{" + str(data["name"]) + "}}",
85
+ str(public_literal_value(value)),
86
+ )
87
+ elif op.op == "plain.append_text":
88
+ session.body += str(data["text"])
89
+ elif op.op == "plain.replace_all":
90
+ session.body = session.body.replace(
91
+ str(data["find"]), str(data["replace"])
92
+ )
93
+
94
+ def finalize(self, session: TextSession) -> None:
95
+ """Mark the session finalized."""
96
+ session.finalized = True
97
+
98
+ def serialize(self, session: TextSession) -> bytes:
99
+ """Return UTF-8 bytes with a trailing newline."""
100
+ body = session.body
101
+ if not body.endswith("\n"):
102
+ body += "\n"
103
+ return body.encode("utf-8")
104
+
105
+ def preview(self, session: TextSession) -> DocumentPreview:
106
+ """Return a text preview identical to serialization."""
107
+ return DocumentPreview(
108
+ documentId=session.document_id,
109
+ mode="text",
110
+ body=self.serialize(session).decode("utf-8"),
111
+ warnings=[],
112
+ generatedAt=datetime.now(UTC).isoformat(),
113
+ renderer={
114
+ "package": "roborean-documents-text",
115
+ "version": "0.3.0",
116
+ },
117
+ )
118
+
119
+
120
+ def create_driver() -> TextDocumentDriver:
121
+ """Entry-point factory."""
122
+ return TextDocumentDriver()