roborean-documents-dxf 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,17 @@
1
+ # Changelog
2
+
3
+ ## [Unreleased]
4
+
5
+ ### Added
6
+
7
+ - `roborean.dxf` driver with drawing ops and drawing-json preview.
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 CR/LF in template DXF text so ezdxf preserves R2010+ versions
17
+ on Windows checkouts.
@@ -0,0 +1,11 @@
1
+ Metadata-Version: 2.4
2
+ Name: roborean-documents-dxf
3
+ Version: 0.1.2
4
+ Summary: DXF 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: ezdxf>=1.3
10
+ Requires-Dist: roborean-documents-base>=0.1.1
11
+ Requires-Dist: roborean-spec>=0.1.1
@@ -0,0 +1,26 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "roborean-documents-dxf"
7
+ version = "0.1.2"
8
+ description = "DXF 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
+ "ezdxf>=1.3",
15
+ ]
16
+
17
+ [project.entry-points."roborean.document_drivers"]
18
+ "roborean.dxf" = "roborean_documents_dxf.driver:create_driver"
19
+
20
+
21
+ [project.urls]
22
+ Homepage = "https://github.com/TNick/roborean"
23
+ Repository = "https://github.com/TNick/roborean"
24
+
25
+ [tool.hatch.build.targets.wheel]
26
+ packages = ["src/roborean_documents_dxf"]
@@ -0,0 +1,151 @@
1
+ """DXF document driver using ezdxf."""
2
+
3
+ import io
4
+ from dataclasses import dataclass, field
5
+ from datetime import UTC, datetime
6
+ from typing import Any, Mapping
7
+
8
+ import ezdxf
9
+ from roborean_documents_base.capabilities import assert_op_allowed
10
+ from roborean_spec import (
11
+ DocumentDriverManifest,
12
+ DocumentOperation,
13
+ DocumentPreview,
14
+ TemplateManifest,
15
+ )
16
+
17
+
18
+ @dataclass
19
+ class DxfSession:
20
+ """ezdxf drawing session."""
21
+
22
+ document_id: str
23
+ driver_id: str
24
+ doc: Any
25
+ msp: Any
26
+ ops_applied: list[dict[str, Any]] = field(default_factory=list)
27
+ entities: list[dict[str, Any]] = field(default_factory=list)
28
+
29
+
30
+ class DxfDocumentDriver:
31
+ """DXF drawing driver."""
32
+
33
+ driver_id = "roborean.dxf"
34
+ manifest = DocumentDriverManifest(
35
+ driverId="roborean.dxf",
36
+ version="0.3.0",
37
+ irFamily="drawing",
38
+ capabilities=[
39
+ "set_metadata",
40
+ "drawing.ensure_layer",
41
+ "drawing.insert_polyline",
42
+ "drawing.insert_text",
43
+ "finalize",
44
+ ],
45
+ supportsPreview=True,
46
+ supportsBrowserExecution=False,
47
+ supportsDiff=True,
48
+ requiresBackend=True,
49
+ templateMediaTypes=["image/vnd.dxf", "application/dxf"],
50
+ )
51
+
52
+ def __init__(self) -> None:
53
+ """Initialize empty template state."""
54
+ self._template: bytes | None = None
55
+ self._manifest: TemplateManifest | None = None
56
+
57
+ def load_template(self, template_ref, *, store, manifest) -> None:
58
+ """Load optional base DXF bytes."""
59
+ self._template = store.load_bytes(template_ref)
60
+ self._manifest = manifest
61
+
62
+ def begin_session(
63
+ self, workspace, metadata: Mapping[str, Any]
64
+ ) -> DxfSession:
65
+ """Open a DXF document from template or create a new one."""
66
+ if self._template:
67
+ # ezdxf text parsing mis-detects $ACADVER when CR/LF is present.
68
+ text = self._template.decode("utf-8").replace("\r\n", "\n")
69
+ doc = ezdxf.read(io.StringIO(text))
70
+ else:
71
+ doc = ezdxf.new("R2010")
72
+ return DxfSession(
73
+ document_id=str(metadata.get("documentId", "")),
74
+ driver_id=self.driver_id,
75
+ doc=doc,
76
+ msp=doc.modelspace(),
77
+ )
78
+
79
+ def apply_operation(
80
+ self, session: DxfSession, op: DocumentOperation
81
+ ) -> None:
82
+ """Apply drawing operations."""
83
+ assert_op_allowed(self.manifest, op)
84
+ data = op.model_dump(mode="python", by_alias=True)
85
+ session.ops_applied.append(op.model_dump(mode="json", by_alias=True))
86
+ if op.op == "drawing.ensure_layer":
87
+ name = str(data["name"])
88
+ if name not in session.doc.layers:
89
+ session.doc.layers.add(name)
90
+ session.entities.append({"type": "layer", "name": name})
91
+ elif op.op == "drawing.insert_polyline":
92
+ points = [tuple(point) for point in data["points"]]
93
+ session.msp.add_lwpolyline(
94
+ points, dxfattribs={"layer": str(data["layer"])}
95
+ )
96
+ session.entities.append(
97
+ {
98
+ "type": "polyline",
99
+ "layer": data["layer"],
100
+ "points": data["points"],
101
+ }
102
+ )
103
+ elif op.op == "drawing.insert_text":
104
+ at = tuple(data["at"])
105
+ height = float(data.get("height") or 2.5)
106
+ session.msp.add_text(
107
+ str(data["text"]),
108
+ dxfattribs={
109
+ "layer": str(data["layer"]),
110
+ "height": height,
111
+ "insert": at,
112
+ },
113
+ )
114
+ session.entities.append(
115
+ {
116
+ "type": "text",
117
+ "layer": data["layer"],
118
+ "at": data["at"],
119
+ "text": data["text"],
120
+ "height": height,
121
+ }
122
+ )
123
+
124
+ def finalize(self, session: DxfSession) -> None:
125
+ """No-op finalize."""
126
+ return
127
+
128
+ def serialize(self, session: DxfSession) -> bytes:
129
+ """Return DXF text bytes."""
130
+ buffer = io.StringIO()
131
+ session.doc.write(buffer)
132
+ return buffer.getvalue().encode("utf-8")
133
+
134
+ def preview(self, session: DxfSession) -> DocumentPreview:
135
+ """Return drawing-json preview for canvas consumers."""
136
+ return DocumentPreview(
137
+ documentId=session.document_id,
138
+ mode="drawing-json",
139
+ body={"entities": session.entities},
140
+ warnings=[],
141
+ generatedAt=datetime.now(UTC).isoformat(),
142
+ renderer={
143
+ "package": "roborean-documents-dxf",
144
+ "version": "0.3.0",
145
+ },
146
+ )
147
+
148
+
149
+ def create_driver() -> DxfDocumentDriver:
150
+ """Entry-point factory."""
151
+ return DxfDocumentDriver()