roborean-documents-dxf 0.1.2__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.
|
@@ -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()
|
|
@@ -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,5 @@
|
|
|
1
|
+
roborean_documents_dxf/driver.py,sha256=O3m4OyCNzb2vryqqLHil6Z9DTVuCNuyOSnJizscUQCg,4850
|
|
2
|
+
roborean_documents_dxf-0.1.2.dist-info/METADATA,sha256=nohLwiZlbguZUCTF_YrNSe8-Jqxi_vsWhH5UylbJYU4,380
|
|
3
|
+
roborean_documents_dxf-0.1.2.dist-info/WHEEL,sha256=lCkmxWfQsSc9CfIClYeavTdQeEX2toPqufh9gI35EQA,87
|
|
4
|
+
roborean_documents_dxf-0.1.2.dist-info/entry_points.txt,sha256=GlAW1JMe7jLiAkZ6eqMRYPsq4ubpE8XIg26kjD1-8PA,87
|
|
5
|
+
roborean_documents_dxf-0.1.2.dist-info/RECORD,,
|