plexus-python-pulse-common 1.1.75__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.
- plexus/pulse/common/__init__.py +6 -0
- plexus/pulse/common/carto/OSMFile.py +259 -0
- plexus/pulse/common/carto/OSMNode.py +25 -0
- plexus/pulse/common/carto/OSMTags.py +101 -0
- plexus/pulse/common/carto/OSMWay.py +24 -0
- plexus/pulse/common/carto/__init__.py +11 -0
- plexus/pulse/common/resources/__init__.py +0 -0
- plexus/pulse/common/resources/tags/__init__.py +35 -0
- plexus/pulse/common/resources/tags/unittest-1.0.0.tagset.yaml +98 -0
- plexus/pulse/common/resources/tags/universal-1.0.0.tagset.yaml +1390 -0
- plexus/pulse/common/utils/__init__.py +0 -0
- plexus/pulse/common/utils/apiutils.py +31 -0
- plexus/pulse/common/utils/bagutils.py +331 -0
- plexus/pulse/common/utils/config.py +63 -0
- plexus/pulse/common/utils/datautils.py +233 -0
- plexus/pulse/common/utils/dockerutils.py +181 -0
- plexus/pulse/common/utils/gisutils.py +406 -0
- plexus/pulse/common/utils/jsonutils.py +96 -0
- plexus/pulse/common/utils/ormutils.py +1638 -0
- plexus/pulse/common/utils/pathutils.py +234 -0
- plexus/pulse/common/utils/s3utils.py +939 -0
- plexus/pulse/common/utils/sqlutils.py +9 -0
- plexus/pulse/common/utils/strutils.py +401 -0
- plexus/pulse/common/utils/tagutils.py +1476 -0
- plexus/pulse/common/utils/testutils.py +172 -0
- plexus_python_pulse_common-1.1.75.dist-info/METADATA +42 -0
- plexus_python_pulse_common-1.1.75.dist-info/RECORD +29 -0
- plexus_python_pulse_common-1.1.75.dist-info/WHEEL +5 -0
- plexus_python_pulse_common-1.1.75.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
from typing import Any, Self
|
|
2
|
+
|
|
3
|
+
import lxml.etree
|
|
4
|
+
|
|
5
|
+
from plexus.pulse.common.carto.OSMNode import OSMNode
|
|
6
|
+
from plexus.pulse.common.carto.OSMTags import OSMTags
|
|
7
|
+
from plexus.pulse.common.carto.OSMWay import OSMWay
|
|
8
|
+
from plexus.pulse.common.utils.gisutils import Coord, Proj
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class OSMFile(object):
|
|
12
|
+
@classmethod
|
|
13
|
+
def load_file(cls, path: str, proj: Proj | None) -> Self:
|
|
14
|
+
"""
|
|
15
|
+
Loads OSM from file given the path
|
|
16
|
+
|
|
17
|
+
:param path: path of OSM file
|
|
18
|
+
:param proj: cartographic projection
|
|
19
|
+
|
|
20
|
+
:return: an OSM file instance
|
|
21
|
+
"""
|
|
22
|
+
root = lxml.etree.parse(path).getroot()
|
|
23
|
+
|
|
24
|
+
nodes = {}
|
|
25
|
+
ways = {}
|
|
26
|
+
for elem in root:
|
|
27
|
+
if elem.attrib.get("action") == "delete":
|
|
28
|
+
continue
|
|
29
|
+
|
|
30
|
+
if elem.tag == "node":
|
|
31
|
+
# Parse an OSM node
|
|
32
|
+
node_id = int(elem.attrib["id"])
|
|
33
|
+
tags = {}
|
|
34
|
+
for child in elem:
|
|
35
|
+
if child.tag == "tag":
|
|
36
|
+
k = child.attrib["k"]
|
|
37
|
+
v = child.attrib["v"]
|
|
38
|
+
tags[k] = v
|
|
39
|
+
|
|
40
|
+
tags = OSMTags.from_any_tags(tags)
|
|
41
|
+
coord = Coord.from_latlon(
|
|
42
|
+
float(elem.attrib["lat"]),
|
|
43
|
+
float(elem.attrib["lon"]),
|
|
44
|
+
tags.getfloat("z", 0.0),
|
|
45
|
+
proj,
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
nodes[node_id] = OSMNode(node_id, coord, tags)
|
|
49
|
+
|
|
50
|
+
elif elem.tag == "way":
|
|
51
|
+
# Parse an OSM way
|
|
52
|
+
way_id = int(elem.attrib["id"])
|
|
53
|
+
|
|
54
|
+
tags = {}
|
|
55
|
+
node_ids = []
|
|
56
|
+
for child in elem:
|
|
57
|
+
if child.tag == "tag":
|
|
58
|
+
k = child.attrib["k"]
|
|
59
|
+
v = child.attrib["v"]
|
|
60
|
+
tags[k] = v
|
|
61
|
+
elif child.tag == "nd":
|
|
62
|
+
node_id = int(child.attrib.get("ref"))
|
|
63
|
+
node_ids.append(node_id)
|
|
64
|
+
|
|
65
|
+
tags = OSMTags.from_any_tags(tags)
|
|
66
|
+
|
|
67
|
+
ways[way_id] = OSMWay(way_id, node_ids, tags)
|
|
68
|
+
|
|
69
|
+
return OSMFile(nodes, ways)
|
|
70
|
+
|
|
71
|
+
@classmethod
|
|
72
|
+
def from_coords(cls, coords: list[Coord], way_tags: dict[str, Any] = None) -> Self:
|
|
73
|
+
"""
|
|
74
|
+
Constructs a single-way OSM file from the given coords
|
|
75
|
+
|
|
76
|
+
:param coords: coords on a single way
|
|
77
|
+
:param way_tags: tags of the corresponding way
|
|
78
|
+
|
|
79
|
+
:return: OSM file contains one way
|
|
80
|
+
"""
|
|
81
|
+
osm = OSMFile()
|
|
82
|
+
osm.add_way_from_coords(coords, way_tags or {})
|
|
83
|
+
|
|
84
|
+
return osm
|
|
85
|
+
|
|
86
|
+
@classmethod
|
|
87
|
+
def from_coords_list(cls, coords_list: list[list[Coord]], way_tags_list: list[dict[str, Any]] = None) -> Self:
|
|
88
|
+
"""
|
|
89
|
+
Constructs a multi-way OSM file from the given coords
|
|
90
|
+
|
|
91
|
+
:param coords_list: coords of each way
|
|
92
|
+
:param way_tags_list: tags of each corresponding way
|
|
93
|
+
|
|
94
|
+
:return: OSM file contains multiple ways
|
|
95
|
+
"""
|
|
96
|
+
osm = OSMFile()
|
|
97
|
+
|
|
98
|
+
if not way_tags_list or len(way_tags_list) != len(coords_list):
|
|
99
|
+
for coords in coords_list:
|
|
100
|
+
osm.add_way_from_coords(coords)
|
|
101
|
+
else:
|
|
102
|
+
for coords, way_tags in zip(coords_list, way_tags_list):
|
|
103
|
+
osm.add_way_from_coords(coords, way_tags or {})
|
|
104
|
+
|
|
105
|
+
return osm
|
|
106
|
+
|
|
107
|
+
def __init__(self, nodes: dict[int, OSMNode] = None, ways: dict[int, OSMWay] = None):
|
|
108
|
+
"""
|
|
109
|
+
Represents an editable general purpose OSM file
|
|
110
|
+
|
|
111
|
+
:param nodes: nodes
|
|
112
|
+
:param ways: ways
|
|
113
|
+
"""
|
|
114
|
+
self.nodes: dict[int, OSMNode] = {}
|
|
115
|
+
self.ways: dict[int, OSMWay] = {}
|
|
116
|
+
|
|
117
|
+
self.next_node_id = 1
|
|
118
|
+
self.next_way_id = 1
|
|
119
|
+
|
|
120
|
+
if nodes:
|
|
121
|
+
self.nodes = nodes
|
|
122
|
+
self.next_node_id = max(nodes.keys()) + 1
|
|
123
|
+
if ways:
|
|
124
|
+
self.ways = ways
|
|
125
|
+
self.next_way_id = max(ways.keys()) + 1
|
|
126
|
+
|
|
127
|
+
def add_node(self, node: OSMNode) -> OSMNode:
|
|
128
|
+
"""
|
|
129
|
+
Adds the given node
|
|
130
|
+
|
|
131
|
+
:param node: the node to be added
|
|
132
|
+
|
|
133
|
+
:return: added node
|
|
134
|
+
"""
|
|
135
|
+
self.nodes[node.node_id] = node
|
|
136
|
+
if node.node_id >= self.next_node_id:
|
|
137
|
+
self.next_node_id = node.node_id + 1
|
|
138
|
+
return node
|
|
139
|
+
|
|
140
|
+
def add_node_from_coord(self, coord: Coord, tags: dict[str, Any] = None) -> OSMNode:
|
|
141
|
+
"""
|
|
142
|
+
Adds node given the coord and tags
|
|
143
|
+
|
|
144
|
+
:param coord: coord of the node
|
|
145
|
+
:param tags: tags of the node
|
|
146
|
+
|
|
147
|
+
:return: added node
|
|
148
|
+
"""
|
|
149
|
+
return self.add_node(OSMNode(self.next_node_id, coord, OSMTags.from_any_tags(tags)))
|
|
150
|
+
|
|
151
|
+
def add_way(self, way: OSMWay) -> OSMWay:
|
|
152
|
+
"""
|
|
153
|
+
Adds the given way
|
|
154
|
+
|
|
155
|
+
:param way: the way to be added
|
|
156
|
+
|
|
157
|
+
:return: added way
|
|
158
|
+
"""
|
|
159
|
+
self.ways[way.way_id] = way
|
|
160
|
+
if way.way_id >= self.next_way_id:
|
|
161
|
+
self.next_way_id = way.way_id + 1
|
|
162
|
+
return way
|
|
163
|
+
|
|
164
|
+
def add_way_from_coords(self, coords: list[Coord], tags: dict[str, Any] = None) -> OSMWay:
|
|
165
|
+
"""
|
|
166
|
+
Adds way given the coords of the nodes and tags
|
|
167
|
+
|
|
168
|
+
:param coords: coords of the nodes on the way
|
|
169
|
+
:param tags: tags of the way
|
|
170
|
+
|
|
171
|
+
:return: added way
|
|
172
|
+
"""
|
|
173
|
+
return self.add_way_from_nodes(coords, tags)
|
|
174
|
+
|
|
175
|
+
def add_way_from_node_ids(self, node_ids: list[int], tags: dict[str, Any] = None) -> OSMWay:
|
|
176
|
+
"""
|
|
177
|
+
Adds way given the ids of the nodes and tags
|
|
178
|
+
|
|
179
|
+
:param node_ids: ids of the nodes on the way
|
|
180
|
+
:param tags: tags of the way
|
|
181
|
+
|
|
182
|
+
:return: added way
|
|
183
|
+
"""
|
|
184
|
+
return self.add_way_from_nodes(node_ids, tags)
|
|
185
|
+
|
|
186
|
+
def add_way_from_nodes(self, elements: list[OSMNode | Coord | int], tags: dict[str, Any] = None) -> OSMWay:
|
|
187
|
+
"""
|
|
188
|
+
Adds way given list of the nodes, the coords, or the ids of the nodes and tags
|
|
189
|
+
|
|
190
|
+
:param elements: a list of the nodes, the coords, or the ids of the nodes on the way
|
|
191
|
+
:param tags: tags of the way
|
|
192
|
+
|
|
193
|
+
:return: added way
|
|
194
|
+
"""
|
|
195
|
+
node_ids = []
|
|
196
|
+
for elem in elements:
|
|
197
|
+
if isinstance(elem, OSMNode):
|
|
198
|
+
node_ids.append(self.add_node_from_coord(elem.coord, elem.tags.tags).node_id)
|
|
199
|
+
elif isinstance(elem, Coord):
|
|
200
|
+
node_ids.append(self.add_node_from_coord(elem, {}).node_id)
|
|
201
|
+
else:
|
|
202
|
+
node_ids.append(elem)
|
|
203
|
+
return self.add_way(OSMWay(self.next_way_id, node_ids, OSMTags.from_any_tags(tags)))
|
|
204
|
+
|
|
205
|
+
def write(self, filename: str):
|
|
206
|
+
"""
|
|
207
|
+
Writes this OSM file instance to the given file name
|
|
208
|
+
|
|
209
|
+
:param filename: file path to write into
|
|
210
|
+
"""
|
|
211
|
+
root = lxml.etree.Element("osm")
|
|
212
|
+
root.attrib.update({
|
|
213
|
+
"version": "0.6",
|
|
214
|
+
"generator": "Plexus",
|
|
215
|
+
})
|
|
216
|
+
|
|
217
|
+
for _, node in self.nodes.items():
|
|
218
|
+
node_elem = lxml.etree.Element("node")
|
|
219
|
+
node_elem.attrib.update(
|
|
220
|
+
{
|
|
221
|
+
"id": str(node.node_id),
|
|
222
|
+
"lat": str(node.coord.lat),
|
|
223
|
+
"lon": str(node.coord.lon),
|
|
224
|
+
"version": "1",
|
|
225
|
+
}
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
for k, v in node.tags.items():
|
|
229
|
+
tag_elem = lxml.etree.Element("tag")
|
|
230
|
+
tag_elem.attrib.update({"k": str(k), "v": str(v)})
|
|
231
|
+
node_elem.append(tag_elem)
|
|
232
|
+
|
|
233
|
+
root.append(node_elem)
|
|
234
|
+
|
|
235
|
+
for _, way in self.ways.items():
|
|
236
|
+
way_elem = lxml.etree.Element("way")
|
|
237
|
+
way_elem.attrib.update(
|
|
238
|
+
{
|
|
239
|
+
"id": str(way.way_id),
|
|
240
|
+
"version": "1",
|
|
241
|
+
}
|
|
242
|
+
)
|
|
243
|
+
|
|
244
|
+
for k, v in way.tags.items():
|
|
245
|
+
tag_elem = lxml.etree.Element("tag")
|
|
246
|
+
tag_elem.attrib.update({"k": str(k), "v": str(v)})
|
|
247
|
+
way_elem.append(tag_elem)
|
|
248
|
+
|
|
249
|
+
for node_id in way.node_ids:
|
|
250
|
+
nd_elem = lxml.etree.Element("nd")
|
|
251
|
+
nd_elem.attrib.update({"ref": str(node_id)})
|
|
252
|
+
way_elem.append(nd_elem)
|
|
253
|
+
|
|
254
|
+
root.append(way_elem)
|
|
255
|
+
|
|
256
|
+
s = lxml.etree.tostring(root, pretty_print=True, encoding="unicode")
|
|
257
|
+
|
|
258
|
+
with open(filename, "w") as fh:
|
|
259
|
+
fh.write(s)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from plexus.common.utils.strutils import repr_data
|
|
2
|
+
|
|
3
|
+
from plexus.pulse.common.carto.OSMTags import OSMTags
|
|
4
|
+
from plexus.pulse.common.utils.gisutils import Coord
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class OSMNode(object):
|
|
8
|
+
"""
|
|
9
|
+
Represents node in OSM
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
def __init__(self, node_id: int, coord: Coord, tags: OSMTags):
|
|
13
|
+
"""
|
|
14
|
+
Creates an instance from the given node id, coord, and tags
|
|
15
|
+
|
|
16
|
+
:param node_id: id
|
|
17
|
+
:param coord: node coordinate
|
|
18
|
+
:param tags: tags
|
|
19
|
+
"""
|
|
20
|
+
self.node_id = node_id
|
|
21
|
+
self.coord = coord
|
|
22
|
+
self.tags = tags
|
|
23
|
+
|
|
24
|
+
def __str__(self):
|
|
25
|
+
return repr_data(self)
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import datetime
|
|
2
|
+
from typing import Any, Self
|
|
3
|
+
|
|
4
|
+
from plexus.common.utils.strutils import repr_data, str_conv
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class OSMTags(object):
|
|
8
|
+
"""
|
|
9
|
+
Represents tag in OSM
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
@classmethod
|
|
13
|
+
def from_any_tags(cls, any_tags: dict[str, Any] = None) -> Self:
|
|
14
|
+
"""
|
|
15
|
+
Creates an instance from any-typed tags by automatically inferring data types
|
|
16
|
+
|
|
17
|
+
:param any_tags: tags with any-typed values
|
|
18
|
+
|
|
19
|
+
:return: OSM tag instance
|
|
20
|
+
"""
|
|
21
|
+
if any_tags is None:
|
|
22
|
+
return OSMTags({})
|
|
23
|
+
return OSMTags({k: str_conv(v) for k, v in any_tags.items()})
|
|
24
|
+
|
|
25
|
+
def __init__(self, tags: dict[str, Any]):
|
|
26
|
+
"""
|
|
27
|
+
Creates an instance from the given tags
|
|
28
|
+
|
|
29
|
+
:param tags: given tags
|
|
30
|
+
"""
|
|
31
|
+
self.tags = tags
|
|
32
|
+
|
|
33
|
+
def __str__(self):
|
|
34
|
+
return repr_data(self)
|
|
35
|
+
|
|
36
|
+
def __iter__(self):
|
|
37
|
+
return self.tags.__iter__()
|
|
38
|
+
|
|
39
|
+
def __getitem__(self, k: str):
|
|
40
|
+
return self.tags.__getitem__(k)
|
|
41
|
+
|
|
42
|
+
def items(self):
|
|
43
|
+
return self.tags.items()
|
|
44
|
+
|
|
45
|
+
def set(self, key: str, value: Any) -> Any:
|
|
46
|
+
old_value = self.tags.get(key)
|
|
47
|
+
self.tags[key] = str_conv(value)
|
|
48
|
+
return old_value
|
|
49
|
+
|
|
50
|
+
def get(self, key: str, default: Any | None = None) -> Any | None:
|
|
51
|
+
return self.tags.get(key, default)
|
|
52
|
+
|
|
53
|
+
def getint(self, key: str, default: int | None = None) -> int | None:
|
|
54
|
+
value = self.tags.get(key, default)
|
|
55
|
+
if isinstance(value, int) and not isinstance(value, bool):
|
|
56
|
+
return value
|
|
57
|
+
if default is None:
|
|
58
|
+
return None
|
|
59
|
+
if isinstance(default, int) and not isinstance(default, bool):
|
|
60
|
+
return default
|
|
61
|
+
raise TypeError("type of either the value or the given default is incompatible, should be 'int'")
|
|
62
|
+
|
|
63
|
+
def getfloat(self, key: str, default: float | None = None) -> float | None:
|
|
64
|
+
value = self.tags.get(key, default)
|
|
65
|
+
if isinstance(value, float):
|
|
66
|
+
return value
|
|
67
|
+
if default is None:
|
|
68
|
+
return None
|
|
69
|
+
if isinstance(default, float):
|
|
70
|
+
return default
|
|
71
|
+
raise TypeError("type of either the value or the given default is incompatible, should be 'float'")
|
|
72
|
+
|
|
73
|
+
def getboolean(self, key: str, default: bool | None = None) -> bool | None:
|
|
74
|
+
value = self.tags.get(key, default)
|
|
75
|
+
if isinstance(value, bool):
|
|
76
|
+
return value
|
|
77
|
+
if default is None:
|
|
78
|
+
return None
|
|
79
|
+
if isinstance(default, bool):
|
|
80
|
+
return default
|
|
81
|
+
raise TypeError("type of either the value or the given default is incompatible, should be 'bool'")
|
|
82
|
+
|
|
83
|
+
def getdatetime(self, key: str, default: datetime.datetime | None = None) -> datetime.datetime | None:
|
|
84
|
+
value = self.tags.get(key, default)
|
|
85
|
+
if isinstance(value, datetime.datetime):
|
|
86
|
+
return value
|
|
87
|
+
if default is None:
|
|
88
|
+
return None
|
|
89
|
+
if isinstance(default, datetime.datetime):
|
|
90
|
+
return default
|
|
91
|
+
raise TypeError("type of either the value or the given default is incompatible, should be 'datetime.datetime'")
|
|
92
|
+
|
|
93
|
+
def getstring(self, key: str, default: str | None = None) -> str | None:
|
|
94
|
+
value = self.tags.get(key, default)
|
|
95
|
+
if isinstance(value, str):
|
|
96
|
+
return value
|
|
97
|
+
if default is None:
|
|
98
|
+
return None
|
|
99
|
+
if isinstance(default, str):
|
|
100
|
+
return default
|
|
101
|
+
raise TypeError("type of either the value or the given default is incompatible, should be 'str'")
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
from plexus.common.utils.strutils import repr_data
|
|
2
|
+
|
|
3
|
+
from plexus.pulse.common.carto.OSMTags import OSMTags
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class OSMWay(object):
|
|
7
|
+
"""
|
|
8
|
+
Represents way in OSM
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
def __init__(self, way_id: int, node_ids: list[int], tags: OSMTags):
|
|
12
|
+
"""
|
|
13
|
+
Creates an instance from the given way id, node ids, and tags
|
|
14
|
+
|
|
15
|
+
:param way_id: id
|
|
16
|
+
:param node_ids: nodes ids
|
|
17
|
+
:param tags: tags
|
|
18
|
+
"""
|
|
19
|
+
self.way_id = way_id
|
|
20
|
+
self.node_ids = node_ids
|
|
21
|
+
self.tags = tags
|
|
22
|
+
|
|
23
|
+
def __str__(self):
|
|
24
|
+
return repr_data(self)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
__all__ = [
|
|
2
|
+
"OSMFile",
|
|
3
|
+
"OSMNode",
|
|
4
|
+
"OSMTags",
|
|
5
|
+
"OSMWay",
|
|
6
|
+
]
|
|
7
|
+
|
|
8
|
+
from plexus.pulse.common.carto.OSMFile import OSMFile
|
|
9
|
+
from plexus.pulse.common.carto.OSMNode import OSMNode
|
|
10
|
+
from plexus.pulse.common.carto.OSMTags import OSMTags
|
|
11
|
+
from plexus.pulse.common.carto.OSMWay import OSMWay
|
|
File without changes
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
import markdown_it as mdit
|
|
4
|
+
import yaml
|
|
5
|
+
from plexus.common.utils.funcutils import singleton
|
|
6
|
+
from plexus.common.utils.jsonutils import JsonObject
|
|
7
|
+
|
|
8
|
+
__all__ = [
|
|
9
|
+
"predefined_tagset_specs",
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@singleton
|
|
14
|
+
def predefined_tagset_specs() -> list[tuple[Path, JsonObject]]:
|
|
15
|
+
# Register simple constructors for !markdown tags yaml.load can parse them.
|
|
16
|
+
def markdown_constructor(loader: yaml.Loader, node: yaml.ScalarNode | yaml.MappingNode):
|
|
17
|
+
text = loader.construct_scalar(node)
|
|
18
|
+
tokens = mdit.MarkdownIt().parse(text)
|
|
19
|
+
for token in tokens:
|
|
20
|
+
if token.type.startswith("heading"):
|
|
21
|
+
raise ValueError("markdown content in tagset specifications cannot contain headings.")
|
|
22
|
+
return {
|
|
23
|
+
"type": "markdown",
|
|
24
|
+
"text": text,
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
yaml.SafeLoader.add_constructor("!markdown", markdown_constructor)
|
|
28
|
+
|
|
29
|
+
def load():
|
|
30
|
+
root = Path(__file__).parent
|
|
31
|
+
for path in root.glob("**/*.tagset.yaml"):
|
|
32
|
+
text = path.read_text(encoding="utf-8")
|
|
33
|
+
yield path, yaml.load(text, yaml.SafeLoader)
|
|
34
|
+
|
|
35
|
+
return list(load())
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
$namespace: "unittest"
|
|
2
|
+
$version: "1.0.0"
|
|
3
|
+
# language=markdown
|
|
4
|
+
$desc: !markdown |
|
|
5
|
+
**Unit Test Tagset**
|
|
6
|
+
|
|
7
|
+
A collection of tags designed for annotating and categorizing data in unit tests. This tagset includes categories
|
|
8
|
+
for camera views, radar views, LiDAR views, environmental conditions, and roadway characteristics. Each tag is
|
|
9
|
+
defined with a description that provides context for its use in unit testing scenarios, helping to ensure that
|
|
10
|
+
test cases are accurately annotated and can be easily understood by developers and testers.
|
|
11
|
+
$def:
|
|
12
|
+
anchored_tags:
|
|
13
|
+
&anchored_tags
|
|
14
|
+
anchored:
|
|
15
|
+
# language=markdown
|
|
16
|
+
$desc: !markdown |
|
|
17
|
+
Anchored tags that describe specific perspectives or viewpoints from which data is captured. These tags are
|
|
18
|
+
typically associated with sensor data and provide critical context for understanding the scene and the
|
|
19
|
+
information being analyzed. For example, camera views may include front center, front left, front right, side
|
|
20
|
+
left, side right, rear left, and rear right perspectives, while radar and LiDAR views may include unified,
|
|
21
|
+
bumper center, bumper left, bumper right, and similar perspectives.
|
|
22
|
+
$schema:
|
|
23
|
+
type: object
|
|
24
|
+
properties:
|
|
25
|
+
dummy_property:
|
|
26
|
+
description: "This is a dummy property that serves as a placeholder for the actual properties that would be defined under the anchored tags."
|
|
27
|
+
type: string
|
|
28
|
+
additionalProperties: true
|
|
29
|
+
another_anchored:
|
|
30
|
+
# language=markdown
|
|
31
|
+
$desc: !markdown |
|
|
32
|
+
Another set of anchored tags that describe specific perspectives or viewpoints from which data is captured.
|
|
33
|
+
These tags may be used in different contexts or for different types of sensors, but they serve a similar
|
|
34
|
+
purpose in providing critical context for understanding the scene and the information being analyzed.
|
|
35
|
+
$tags:
|
|
36
|
+
level_1_tag:
|
|
37
|
+
$desc: "This is a level 1 tag that provides a high-level categorization for the data."
|
|
38
|
+
$schema:
|
|
39
|
+
type: object
|
|
40
|
+
properties:
|
|
41
|
+
dummy_property:
|
|
42
|
+
description: "This is a dummy property that serves as a placeholder for the actual properties that would be defined under this level 1 tag."
|
|
43
|
+
type: string
|
|
44
|
+
additionalProperties: true
|
|
45
|
+
level_2_tag:
|
|
46
|
+
$desc: "This is a level 2 tag that provides a more specific categorization for the data."
|
|
47
|
+
level_3_tag: { $desc: "level 3 tag description", <<: *anchored_tags }
|
|
48
|
+
another_level_3_tag: { $desc: "another level 3 tag description" }
|
|
49
|
+
another_level_2_tag:
|
|
50
|
+
$desc: "This is another level 2 tag that provides a different specific categorization for the data."
|
|
51
|
+
$schema:
|
|
52
|
+
type: object
|
|
53
|
+
properties:
|
|
54
|
+
dummy_property:
|
|
55
|
+
description: "This is a dummy property that serves as a placeholder for the actual properties that would be defined under this level 2 tag."
|
|
56
|
+
type: object
|
|
57
|
+
properties:
|
|
58
|
+
dummy_sub_property:
|
|
59
|
+
description: "This is a dummy sub-property that serves as a placeholder for the actual sub-properties that would be defined under this dummy property."
|
|
60
|
+
type: string
|
|
61
|
+
additionalProperties: false
|
|
62
|
+
required: [ dummy_property ]
|
|
63
|
+
additionalProperties: true
|
|
64
|
+
<<: *anchored_tags
|
|
65
|
+
another_level_1_tag:
|
|
66
|
+
# language=markdown
|
|
67
|
+
$desc: !markdown |
|
|
68
|
+
This is another level 1 tag that provides a different high-level categorization for the data. It may be used
|
|
69
|
+
to group data based on different criteria or characteristics, such as environmental conditions, roadway
|
|
70
|
+
characteristics, or other relevant factors that are important for unit testing scenarios.
|
|
71
|
+
$schema:
|
|
72
|
+
type: object
|
|
73
|
+
properties:
|
|
74
|
+
dummy_elements:
|
|
75
|
+
description: "This is a dummy array property that serves as a placeholder for the actual array properties that would be defined under this level 1 tag."
|
|
76
|
+
type: array
|
|
77
|
+
items:
|
|
78
|
+
type: integer
|
|
79
|
+
minimum: 0
|
|
80
|
+
minItems: 1
|
|
81
|
+
maxItems: 3
|
|
82
|
+
required: [ dummy_elements ]
|
|
83
|
+
additionalProperties: true
|
|
84
|
+
level_2_tag:
|
|
85
|
+
# language=markdown
|
|
86
|
+
$desc: !markdown |
|
|
87
|
+
This is a level 2 tag that provides a more specific categorization for the data under the second level 1 tag.
|
|
88
|
+
It may be used to further refine the categorization based on specific criteria or characteristics relevant to
|
|
89
|
+
the second level 1 tag, such as different types of environmental conditions or roadway characteristics.
|
|
90
|
+
level_3_tag:
|
|
91
|
+
# language=markdown
|
|
92
|
+
$desc: !markdown |
|
|
93
|
+
This is a level 3 tag that provides an even more specific categorization for the data under the level 2 tag
|
|
94
|
+
of the second level 1 tag. It may be used to further refine the categorization based on very specific
|
|
95
|
+
criteria or characteristics relevant to the level 2 tag, such as specific weather conditions, road types,
|
|
96
|
+
or other detailed factors that are important for unit testing scenarios.
|
|
97
|
+
level_4_tag:
|
|
98
|
+
$desc: "This is a level 4 tag that provides an even more specific categorization for the data under the level 3 tag. Actually, you can have as many levels as you want, but for the sake of this example, we will stop at level 4."
|