eazydraw 1.0.0__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.
- eazydraw-1.0.0/LICENSE +21 -0
- eazydraw-1.0.0/PKG-INFO +180 -0
- eazydraw-1.0.0/README.md +129 -0
- eazydraw-1.0.0/eazydraw/__init__.py +62 -0
- eazydraw-1.0.0/eazydraw/client.py +795 -0
- eazydraw-1.0.0/eazydraw/mcp.py +624 -0
- eazydraw-1.0.0/eazydraw/models.py +153 -0
- eazydraw-1.0.0/eazydraw/semantic.py +341 -0
- eazydraw-1.0.0/eazydraw.egg-info/PKG-INFO +180 -0
- eazydraw-1.0.0/eazydraw.egg-info/SOURCES.txt +14 -0
- eazydraw-1.0.0/eazydraw.egg-info/dependency_links.txt +1 -0
- eazydraw-1.0.0/eazydraw.egg-info/entry_points.txt +2 -0
- eazydraw-1.0.0/eazydraw.egg-info/requires.txt +9 -0
- eazydraw-1.0.0/eazydraw.egg-info/top_level.txt +1 -0
- eazydraw-1.0.0/pyproject.toml +60 -0
- eazydraw-1.0.0/setup.cfg +4 -0
eazydraw-1.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Dekorra Optics, LLC
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
eazydraw-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: eazydraw
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Python client and MCP server for the EazyDraw Automation API
|
|
5
|
+
Author-email: Dave Mattson <davemattson@eazydraw.com>
|
|
6
|
+
Maintainer-email: "Dekorra Optics, LLC" <davemattson@eazydraw.com>
|
|
7
|
+
License: MIT License
|
|
8
|
+
|
|
9
|
+
Copyright (c) 2026 Dekorra Optics, LLC
|
|
10
|
+
|
|
11
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
12
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
13
|
+
in the Software without restriction, including without limitation the rights
|
|
14
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
15
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
16
|
+
furnished to do so, subject to the following conditions:
|
|
17
|
+
|
|
18
|
+
The above copyright notice and this permission notice shall be included in all
|
|
19
|
+
copies or substantial portions of the Software.
|
|
20
|
+
|
|
21
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
22
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
23
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
24
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
25
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
26
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
27
|
+
SOFTWARE.
|
|
28
|
+
|
|
29
|
+
Project-URL: Homepage, https://www.eazydraw.com
|
|
30
|
+
Project-URL: Documentation, https://www.eazydraw.com/ezdHelpPages/apiReference.htm
|
|
31
|
+
Keywords: eazydraw,automation,api,rest,mcp,model context protocol,claude,drawing,vector,graphics
|
|
32
|
+
Classifier: Development Status :: 4 - Beta
|
|
33
|
+
Classifier: Intended Audience :: Developers
|
|
34
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
35
|
+
Classifier: Operating System :: MacOS
|
|
36
|
+
Classifier: Programming Language :: Python :: 3
|
|
37
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
38
|
+
Classifier: Topic :: Multimedia :: Graphics
|
|
39
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
40
|
+
Requires-Python: >=3.10
|
|
41
|
+
Description-Content-Type: text/markdown
|
|
42
|
+
License-File: LICENSE
|
|
43
|
+
Requires-Dist: requests>=2.31
|
|
44
|
+
Requires-Dist: pydantic>=2.6
|
|
45
|
+
Provides-Extra: mcp
|
|
46
|
+
Requires-Dist: mcp>=1.2; extra == "mcp"
|
|
47
|
+
Provides-Extra: dev
|
|
48
|
+
Requires-Dist: pyyaml>=6.0; extra == "dev"
|
|
49
|
+
Requires-Dist: openapi-spec-validator>=0.7; extra == "dev"
|
|
50
|
+
Dynamic: license-file
|
|
51
|
+
|
|
52
|
+
# EazyDraw Automation API — Python client
|
|
53
|
+
|
|
54
|
+
Python wrapper around the HTTP API documented in `../../API.md` and
|
|
55
|
+
`../../spec/openapi.yaml`. A developer tool, not (yet) a shipped SDK.
|
|
56
|
+
|
|
57
|
+
Packaged as the `eazydraw` module:
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
eazydraw/
|
|
61
|
+
__init__.py public exports (EazyDraw, EazyDrawError, models)
|
|
62
|
+
client.py the EazyDraw HTTP client (returns raw dicts)
|
|
63
|
+
models.py pydantic v2 models mirroring spec/openapi.yaml
|
|
64
|
+
eazydraw_api.py backward-compat shim (re-exports from eazydraw)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Setup
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
pip install -r requirements.txt # requests + pydantic (+ dev: pyyaml, openapi-spec-validator)
|
|
71
|
+
# or, to install the package itself (editable): pip install -e .
|
|
72
|
+
cp config.example.py config.py
|
|
73
|
+
# edit config.py and paste your bearer token from API Settings -> Reveal
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Python 3.10+. `config.py` is gitignored so your real token stays on your
|
|
77
|
+
machine; `config.example.py` is the committed placeholder.
|
|
78
|
+
|
|
79
|
+
## Quickstart
|
|
80
|
+
|
|
81
|
+
```python
|
|
82
|
+
from eazydraw import EazyDraw # (the old `from eazydraw_api import EazyDraw` still works)
|
|
83
|
+
|
|
84
|
+
# Paste your bearer token from API Settings -> Reveal
|
|
85
|
+
ed = EazyDraw(token="7b3f...")
|
|
86
|
+
|
|
87
|
+
ed.status()
|
|
88
|
+
# {'status': 'OK', 'version': '12.3.6', 'build': '51059'}
|
|
89
|
+
|
|
90
|
+
# Open a drawing, capture its uuid
|
|
91
|
+
d = ed.open_drawing("~/Documents/sketch.ezdjson")
|
|
92
|
+
print(d["uuid"], "newly opened" if ed.last_response.status_code == 201 else "already open")
|
|
93
|
+
|
|
94
|
+
# Walk down to graphics on the active layer
|
|
95
|
+
layers = ed.layers(d["uuid"])
|
|
96
|
+
gs = ed.layer_graphics(d["uuid"], layers[0]["uuid"])
|
|
97
|
+
print(len(gs), "graphics on layer 0")
|
|
98
|
+
|
|
99
|
+
# Place a library element into the drawing
|
|
100
|
+
libs = ed.libraries()
|
|
101
|
+
math_lib = next(l for l in libs if l["DisplayName"] == "Math")
|
|
102
|
+
els = ed.library_elements(math_lib["uuid"])
|
|
103
|
+
graphic_el = next(e for e in els if e["elementType"] == "graphic")
|
|
104
|
+
placed = ed.use_library_element(
|
|
105
|
+
d["uuid"], layers[0]["uuid"], math_lib["uuid"], graphic_el["uuid"]
|
|
106
|
+
)
|
|
107
|
+
print("Placed", placed["class"], "as", placed["graphicUUID"])
|
|
108
|
+
|
|
109
|
+
# Export the drawing as a PNG to disk
|
|
110
|
+
ed.export_drawing(d["uuid"], "png", save_to="/tmp/sketch.png")
|
|
111
|
+
|
|
112
|
+
# Close it
|
|
113
|
+
ed.close_drawing(d["uuid"])
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Typed models (optional)
|
|
117
|
+
|
|
118
|
+
The client returns raw dicts. For validation / IDE support, parse them with the
|
|
119
|
+
pydantic models in `eazydraw.models` (these mirror `spec/openapi.yaml`):
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
from eazydraw import EazyDraw, Graphic, Text
|
|
123
|
+
|
|
124
|
+
ed = EazyDraw(token="7b3f...")
|
|
125
|
+
g = Graphic.model_validate(ed.graphic(D, L, G))
|
|
126
|
+
print(g.graphic_uuid, g.hidden_bounds.width, g.is_group) # snake_case fields
|
|
127
|
+
|
|
128
|
+
# round-trips back to wire form (camelCase / PascalCase keys)
|
|
129
|
+
g.model_dump(by_alias=True)
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Field names are snake_case with the wire keys as aliases; unknown server keys
|
|
133
|
+
are preserved (`extra="allow"`), so a newer server field won't break parsing.
|
|
134
|
+
|
|
135
|
+
## Error handling
|
|
136
|
+
|
|
137
|
+
Non-2xx responses raise `EazyDrawError(status_code, message, body)`:
|
|
138
|
+
|
|
139
|
+
```python
|
|
140
|
+
from eazydraw import EazyDraw, EazyDrawError
|
|
141
|
+
|
|
142
|
+
ed = EazyDraw(token="wrong-token")
|
|
143
|
+
try:
|
|
144
|
+
ed.status()
|
|
145
|
+
except EazyDrawError as exc:
|
|
146
|
+
print(exc.status_code, exc.message) # 401 "Missing or invalid bearer token"
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## Status codes
|
|
150
|
+
|
|
151
|
+
Every method calls `self.last_response = resp`, so when the server's status
|
|
152
|
+
code carries semantic meaning (201 vs 200 on POST, etc.), inspect it
|
|
153
|
+
afterward:
|
|
154
|
+
|
|
155
|
+
```python
|
|
156
|
+
d = ed.open_drawing(path)
|
|
157
|
+
already_open = (ed.last_response.status_code == 200)
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## Conventions
|
|
161
|
+
|
|
162
|
+
- Methods take UUIDs as positional strings, in path order: `ed.layer(D, L)`,
|
|
163
|
+
`ed.layer_graphics(D, L)`, etc.
|
|
164
|
+
- Recursive group-traversal methods take a variadic list of UUIDs in chain
|
|
165
|
+
order: `ed.group_graphics(D, L, G1, G2, G3)` reads as "drilling down".
|
|
166
|
+
- `export_*` methods take `fmt` as a keyword argument (so the call site stays
|
|
167
|
+
readable when there's a long UUID chain) and accept an optional `save_to`
|
|
168
|
+
path; if given, bytes are written to that path and the path is returned.
|
|
169
|
+
Otherwise raw bytes are returned.
|
|
170
|
+
- Collection endpoints unwrap the envelope: `ed.drawings()` returns the list
|
|
171
|
+
directly, not `{"drawings": [...]}`.
|
|
172
|
+
- `client.py` is single-class; as we add API endpoints we add a method — no
|
|
173
|
+
inheritance, no abstractions. `models.py` is plain pydantic data classes.
|
|
174
|
+
|
|
175
|
+
## Not shipped
|
|
176
|
+
|
|
177
|
+
This lives in the repo for convenience but is not part of the EazyDraw app
|
|
178
|
+
bundle. A versioned, published Python SDK is a future product decision; the
|
|
179
|
+
`eazydraw` package here is the working basis for it (and for the semantic
|
|
180
|
+
resolver + MCP server layers to come).
|
eazydraw-1.0.0/README.md
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# EazyDraw Automation API — Python client
|
|
2
|
+
|
|
3
|
+
Python wrapper around the HTTP API documented in `../../API.md` and
|
|
4
|
+
`../../spec/openapi.yaml`. A developer tool, not (yet) a shipped SDK.
|
|
5
|
+
|
|
6
|
+
Packaged as the `eazydraw` module:
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
eazydraw/
|
|
10
|
+
__init__.py public exports (EazyDraw, EazyDrawError, models)
|
|
11
|
+
client.py the EazyDraw HTTP client (returns raw dicts)
|
|
12
|
+
models.py pydantic v2 models mirroring spec/openapi.yaml
|
|
13
|
+
eazydraw_api.py backward-compat shim (re-exports from eazydraw)
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Setup
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
pip install -r requirements.txt # requests + pydantic (+ dev: pyyaml, openapi-spec-validator)
|
|
20
|
+
# or, to install the package itself (editable): pip install -e .
|
|
21
|
+
cp config.example.py config.py
|
|
22
|
+
# edit config.py and paste your bearer token from API Settings -> Reveal
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Python 3.10+. `config.py` is gitignored so your real token stays on your
|
|
26
|
+
machine; `config.example.py` is the committed placeholder.
|
|
27
|
+
|
|
28
|
+
## Quickstart
|
|
29
|
+
|
|
30
|
+
```python
|
|
31
|
+
from eazydraw import EazyDraw # (the old `from eazydraw_api import EazyDraw` still works)
|
|
32
|
+
|
|
33
|
+
# Paste your bearer token from API Settings -> Reveal
|
|
34
|
+
ed = EazyDraw(token="7b3f...")
|
|
35
|
+
|
|
36
|
+
ed.status()
|
|
37
|
+
# {'status': 'OK', 'version': '12.3.6', 'build': '51059'}
|
|
38
|
+
|
|
39
|
+
# Open a drawing, capture its uuid
|
|
40
|
+
d = ed.open_drawing("~/Documents/sketch.ezdjson")
|
|
41
|
+
print(d["uuid"], "newly opened" if ed.last_response.status_code == 201 else "already open")
|
|
42
|
+
|
|
43
|
+
# Walk down to graphics on the active layer
|
|
44
|
+
layers = ed.layers(d["uuid"])
|
|
45
|
+
gs = ed.layer_graphics(d["uuid"], layers[0]["uuid"])
|
|
46
|
+
print(len(gs), "graphics on layer 0")
|
|
47
|
+
|
|
48
|
+
# Place a library element into the drawing
|
|
49
|
+
libs = ed.libraries()
|
|
50
|
+
math_lib = next(l for l in libs if l["DisplayName"] == "Math")
|
|
51
|
+
els = ed.library_elements(math_lib["uuid"])
|
|
52
|
+
graphic_el = next(e for e in els if e["elementType"] == "graphic")
|
|
53
|
+
placed = ed.use_library_element(
|
|
54
|
+
d["uuid"], layers[0]["uuid"], math_lib["uuid"], graphic_el["uuid"]
|
|
55
|
+
)
|
|
56
|
+
print("Placed", placed["class"], "as", placed["graphicUUID"])
|
|
57
|
+
|
|
58
|
+
# Export the drawing as a PNG to disk
|
|
59
|
+
ed.export_drawing(d["uuid"], "png", save_to="/tmp/sketch.png")
|
|
60
|
+
|
|
61
|
+
# Close it
|
|
62
|
+
ed.close_drawing(d["uuid"])
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Typed models (optional)
|
|
66
|
+
|
|
67
|
+
The client returns raw dicts. For validation / IDE support, parse them with the
|
|
68
|
+
pydantic models in `eazydraw.models` (these mirror `spec/openapi.yaml`):
|
|
69
|
+
|
|
70
|
+
```python
|
|
71
|
+
from eazydraw import EazyDraw, Graphic, Text
|
|
72
|
+
|
|
73
|
+
ed = EazyDraw(token="7b3f...")
|
|
74
|
+
g = Graphic.model_validate(ed.graphic(D, L, G))
|
|
75
|
+
print(g.graphic_uuid, g.hidden_bounds.width, g.is_group) # snake_case fields
|
|
76
|
+
|
|
77
|
+
# round-trips back to wire form (camelCase / PascalCase keys)
|
|
78
|
+
g.model_dump(by_alias=True)
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Field names are snake_case with the wire keys as aliases; unknown server keys
|
|
82
|
+
are preserved (`extra="allow"`), so a newer server field won't break parsing.
|
|
83
|
+
|
|
84
|
+
## Error handling
|
|
85
|
+
|
|
86
|
+
Non-2xx responses raise `EazyDrawError(status_code, message, body)`:
|
|
87
|
+
|
|
88
|
+
```python
|
|
89
|
+
from eazydraw import EazyDraw, EazyDrawError
|
|
90
|
+
|
|
91
|
+
ed = EazyDraw(token="wrong-token")
|
|
92
|
+
try:
|
|
93
|
+
ed.status()
|
|
94
|
+
except EazyDrawError as exc:
|
|
95
|
+
print(exc.status_code, exc.message) # 401 "Missing or invalid bearer token"
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Status codes
|
|
99
|
+
|
|
100
|
+
Every method calls `self.last_response = resp`, so when the server's status
|
|
101
|
+
code carries semantic meaning (201 vs 200 on POST, etc.), inspect it
|
|
102
|
+
afterward:
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
d = ed.open_drawing(path)
|
|
106
|
+
already_open = (ed.last_response.status_code == 200)
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Conventions
|
|
110
|
+
|
|
111
|
+
- Methods take UUIDs as positional strings, in path order: `ed.layer(D, L)`,
|
|
112
|
+
`ed.layer_graphics(D, L)`, etc.
|
|
113
|
+
- Recursive group-traversal methods take a variadic list of UUIDs in chain
|
|
114
|
+
order: `ed.group_graphics(D, L, G1, G2, G3)` reads as "drilling down".
|
|
115
|
+
- `export_*` methods take `fmt` as a keyword argument (so the call site stays
|
|
116
|
+
readable when there's a long UUID chain) and accept an optional `save_to`
|
|
117
|
+
path; if given, bytes are written to that path and the path is returned.
|
|
118
|
+
Otherwise raw bytes are returned.
|
|
119
|
+
- Collection endpoints unwrap the envelope: `ed.drawings()` returns the list
|
|
120
|
+
directly, not `{"drawings": [...]}`.
|
|
121
|
+
- `client.py` is single-class; as we add API endpoints we add a method — no
|
|
122
|
+
inheritance, no abstractions. `models.py` is plain pydantic data classes.
|
|
123
|
+
|
|
124
|
+
## Not shipped
|
|
125
|
+
|
|
126
|
+
This lives in the repo for convenience but is not part of the EazyDraw app
|
|
127
|
+
bundle. A versioned, published Python SDK is a future product decision; the
|
|
128
|
+
`eazydraw` package here is the working basis for it (and for the semantic
|
|
129
|
+
resolver + MCP server layers to come).
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"""
|
|
2
|
+
eazydraw — Python client + models for the EazyDraw Automation API.
|
|
3
|
+
|
|
4
|
+
from eazydraw import EazyDraw, Graphic
|
|
5
|
+
ed = EazyDraw(token="...")
|
|
6
|
+
g = Graphic.model_validate(ed.graphic(d, l, g_uuid))
|
|
7
|
+
|
|
8
|
+
The HTTP layer (``EazyDraw``, ``EazyDrawError``) lives in ``eazydraw.client``;
|
|
9
|
+
the typed JSON shapes in ``eazydraw.models``. The client returns raw dicts —
|
|
10
|
+
the models are an optional typed layer over them (see models.py).
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from .client import EazyDraw, EazyDrawError, DEFAULT_HOST, DEFAULT_PORT
|
|
14
|
+
from .models import (
|
|
15
|
+
Status,
|
|
16
|
+
Rect,
|
|
17
|
+
Size,
|
|
18
|
+
Locks,
|
|
19
|
+
Drawing,
|
|
20
|
+
Library,
|
|
21
|
+
Layer,
|
|
22
|
+
Graphic,
|
|
23
|
+
Element,
|
|
24
|
+
TextLayout,
|
|
25
|
+
TextBase,
|
|
26
|
+
Text,
|
|
27
|
+
Annotation,
|
|
28
|
+
)
|
|
29
|
+
from .semantic import (
|
|
30
|
+
Semantic,
|
|
31
|
+
Located,
|
|
32
|
+
SemanticError,
|
|
33
|
+
NoMatch,
|
|
34
|
+
AmbiguousMatch,
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
__version__ = "1.0.0"
|
|
38
|
+
|
|
39
|
+
__all__ = [
|
|
40
|
+
"EazyDraw",
|
|
41
|
+
"EazyDrawError",
|
|
42
|
+
"DEFAULT_HOST",
|
|
43
|
+
"DEFAULT_PORT",
|
|
44
|
+
"Status",
|
|
45
|
+
"Rect",
|
|
46
|
+
"Size",
|
|
47
|
+
"Locks",
|
|
48
|
+
"Drawing",
|
|
49
|
+
"Library",
|
|
50
|
+
"Layer",
|
|
51
|
+
"Graphic",
|
|
52
|
+
"Element",
|
|
53
|
+
"TextLayout",
|
|
54
|
+
"TextBase",
|
|
55
|
+
"Text",
|
|
56
|
+
"Annotation",
|
|
57
|
+
"Semantic",
|
|
58
|
+
"Located",
|
|
59
|
+
"SemanticError",
|
|
60
|
+
"NoMatch",
|
|
61
|
+
"AmbiguousMatch",
|
|
62
|
+
]
|