xplan-tools 1.13.1__py3-none-any.whl → 1.14.0__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.
- xplan_tools/model/base.py +44 -1
- xplan_tools/model/migrations/versions/f8b74c08ec07_add_refs_indexes_ensure_polygon_ccw.py +1 -17
- xplan_tools/model/orm.py +1 -7
- xplan_tools/util/style.py +11 -2
- {xplan_tools-1.13.1.dist-info → xplan_tools-1.14.0.dist-info}/METADATA +1 -1
- {xplan_tools-1.13.1.dist-info → xplan_tools-1.14.0.dist-info}/RECORD +9 -9
- {xplan_tools-1.13.1.dist-info → xplan_tools-1.14.0.dist-info}/WHEEL +1 -1
- {xplan_tools-1.13.1.dist-info → xplan_tools-1.14.0.dist-info}/entry_points.txt +0 -0
- {xplan_tools-1.13.1.dist-info → xplan_tools-1.14.0.dist-info}/licenses/LICENSE.md +0 -0
xplan_tools/model/base.py
CHANGED
|
@@ -3,9 +3,12 @@
|
|
|
3
3
|
The classes provide some utility, (de-)serialization and/or validation methods to simplify access and manipulation.
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
6
8
|
import datetime
|
|
7
9
|
import logging
|
|
8
10
|
import re
|
|
11
|
+
from copy import deepcopy
|
|
9
12
|
from importlib import import_module
|
|
10
13
|
from pathlib import Path
|
|
11
14
|
from types import ModuleType, NoneType
|
|
@@ -22,7 +25,7 @@ from typing import (
|
|
|
22
25
|
get_args,
|
|
23
26
|
get_origin,
|
|
24
27
|
)
|
|
25
|
-
from uuid import UUID
|
|
28
|
+
from uuid import UUID, uuid4
|
|
26
29
|
|
|
27
30
|
from lxml.etree import _Element
|
|
28
31
|
from osgeo import ogr
|
|
@@ -312,6 +315,46 @@ class BaseCollection(BaseModel):
|
|
|
312
315
|
"""Yields features stored in the collection."""
|
|
313
316
|
return (feature for feature in self.features.values())
|
|
314
317
|
|
|
318
|
+
def make_copy(
|
|
319
|
+
self, with_id_map: bool = False
|
|
320
|
+
) -> "BaseCollection" | tuple["BaseCollection", dict]:
|
|
321
|
+
"""Return a copy of the collection with new IDs.
|
|
322
|
+
|
|
323
|
+
All feature IDs are renewed and respective references are updated.
|
|
324
|
+
|
|
325
|
+
Args:
|
|
326
|
+
with_id_map: whether to additionally return a map of old IDs to new IDs
|
|
327
|
+
"""
|
|
328
|
+
id_map = {key: uuid4() for key in self.features.keys()}
|
|
329
|
+
new_features = {}
|
|
330
|
+
for old_feature in self.features.values():
|
|
331
|
+
new_id = str(id_map[old_feature.id])
|
|
332
|
+
new_feature = deepcopy(old_feature)
|
|
333
|
+
new_feature.id = new_id
|
|
334
|
+
for assocation in old_feature.get_associations():
|
|
335
|
+
old_value = getattr(old_feature, assocation)
|
|
336
|
+
if isinstance(old_value, UUID):
|
|
337
|
+
new_value = id_map[str(old_value)]
|
|
338
|
+
setattr(new_feature, assocation, new_value)
|
|
339
|
+
elif isinstance(old_value, list):
|
|
340
|
+
new_list = [
|
|
341
|
+
id_map[str(item)] if isinstance(item, UUID) else item
|
|
342
|
+
for item in old_value
|
|
343
|
+
]
|
|
344
|
+
setattr(new_feature, assocation, new_list)
|
|
345
|
+
new_features[new_id] = new_feature
|
|
346
|
+
|
|
347
|
+
new_collection = BaseCollection(
|
|
348
|
+
features=new_features,
|
|
349
|
+
srid=self.srid,
|
|
350
|
+
version=self.version,
|
|
351
|
+
appschema=self.appschema,
|
|
352
|
+
)
|
|
353
|
+
if with_id_map:
|
|
354
|
+
return new_collection, id_map
|
|
355
|
+
else:
|
|
356
|
+
return new_collection
|
|
357
|
+
|
|
315
358
|
def add_style_properties(
|
|
316
359
|
self, to_text: bool = False, always_populate_schriftinhalt: bool = False
|
|
317
360
|
) -> None:
|
|
@@ -7,7 +7,6 @@ Create Date: 2026-01-08 10:58:26.988690
|
|
|
7
7
|
|
|
8
8
|
from typing import Sequence, Union
|
|
9
9
|
|
|
10
|
-
import sqlalchemy as sa
|
|
11
10
|
from alembic import op
|
|
12
11
|
|
|
13
12
|
from xplan_tools.settings import get_settings
|
|
@@ -25,9 +24,7 @@ schema = settings.db_schema
|
|
|
25
24
|
def upgrade() -> None:
|
|
26
25
|
"""Upgrade schema.
|
|
27
26
|
|
|
28
|
-
Creates indexes on `refs.base_id` and refs.related_id
|
|
29
|
-
geometries in `coretable.geometry` to counter-clockwise orientation
|
|
30
|
-
using `ST_ForcePolygonCCW` in-place.
|
|
27
|
+
Creates indexes on `refs.base_id` and refs.related_id`.
|
|
31
28
|
"""
|
|
32
29
|
op.create_index(
|
|
33
30
|
op.f("ix_refs_base_id"),
|
|
@@ -43,19 +40,6 @@ def upgrade() -> None:
|
|
|
43
40
|
schema=schema,
|
|
44
41
|
if_not_exists=True,
|
|
45
42
|
)
|
|
46
|
-
coretable = sa.Table(
|
|
47
|
-
"coretable",
|
|
48
|
-
sa.MetaData(),
|
|
49
|
-
sa.Column("geometry"),
|
|
50
|
-
sa.Column("geometry_type"),
|
|
51
|
-
schema=schema,
|
|
52
|
-
)
|
|
53
|
-
stmt = (
|
|
54
|
-
sa.update(coretable)
|
|
55
|
-
.values(geometry=sa.func.ST_ForcePolygonCCW(coretable.c.geometry))
|
|
56
|
-
.where(coretable.c.geometry_type == "polygon")
|
|
57
|
-
)
|
|
58
|
-
op.execute(stmt)
|
|
59
43
|
|
|
60
44
|
|
|
61
45
|
def downgrade() -> None:
|
xplan_tools/model/orm.py
CHANGED
|
@@ -20,7 +20,6 @@ from sqlalchemy import (
|
|
|
20
20
|
Text,
|
|
21
21
|
Uuid,
|
|
22
22
|
case,
|
|
23
|
-
cast,
|
|
24
23
|
literal,
|
|
25
24
|
select,
|
|
26
25
|
)
|
|
@@ -104,13 +103,8 @@ class PGGeometry(TypeDecorator):
|
|
|
104
103
|
|
|
105
104
|
def bind_expression(self, bindvalue):
|
|
106
105
|
"""Transform incoming geometries to the SRID of the DB and force CCW orientation for polygons."""
|
|
107
|
-
is_polygon = Geometry._is_polygon(cast(bindvalue, Geometry))
|
|
108
|
-
case_clause = case(
|
|
109
|
-
(is_polygon, func.ST_ForcePolygonCCW(bindvalue)),
|
|
110
|
-
else_=bindvalue,
|
|
111
|
-
)
|
|
112
106
|
return func.ST_Transform(
|
|
113
|
-
|
|
107
|
+
bindvalue,
|
|
114
108
|
func.Find_SRID(
|
|
115
109
|
get_settings().db_schema or "public", "coretable", "geometry"
|
|
116
110
|
),
|
xplan_tools/util/style.py
CHANGED
|
@@ -49,6 +49,10 @@ def add_style_properties_to_feature(
|
|
|
49
49
|
"alias", prop_info["enum_info"][value]["name"]
|
|
50
50
|
),
|
|
51
51
|
)
|
|
52
|
+
elif prop_info["stereotype"] == "Codelist":
|
|
53
|
+
text = str(value)
|
|
54
|
+
if text.startswith("urn:"):
|
|
55
|
+
text = text.split(f"urn:xplan:{prop_info['typename']}:")[1]
|
|
52
56
|
elif prop_info["stereotype"] == "Measure":
|
|
53
57
|
text = f"{value:n} {uom_map.get(prop_info['uom'], prop_info['uom'])}"
|
|
54
58
|
else:
|
|
@@ -63,8 +67,8 @@ def add_style_properties_to_feature(
|
|
|
63
67
|
remove_namespace = re.sub(
|
|
64
68
|
r"xplan:", "", remove_subindexes
|
|
65
69
|
) # xplan:|(.P_|SO_)[a-zA-Z]*\/
|
|
66
|
-
attr, path_index, datatype, sub_attr = re.match(
|
|
67
|
-
r"^(?P<attr>\w*)\[?(?P<index>\d)?]?/?(?P<datatype>\w{2}_\w*)?/?(?P<sub_attr>\w*)?$",
|
|
70
|
+
attr, path_index, datatype, sub_attr, sub_attr_index = re.match(
|
|
71
|
+
r"^(?P<attr>\w*)\[?(?P<index>\d)?]?/?(?P<datatype>\w{2}_\w*)?/?(?P<sub_attr>\w*)?\[?(?P<sub_attr_index>\d)?]?$",
|
|
68
72
|
remove_namespace,
|
|
69
73
|
).groups()
|
|
70
74
|
|
|
@@ -83,6 +87,11 @@ def add_style_properties_to_feature(
|
|
|
83
87
|
if sub_attr:
|
|
84
88
|
name = sub_attr
|
|
85
89
|
value = getattr(value, sub_attr)
|
|
90
|
+
if isinstance(value, list):
|
|
91
|
+
index = 0
|
|
92
|
+
if sub_attr_index:
|
|
93
|
+
index = max(int(sub_attr_index) - 1, 0)
|
|
94
|
+
value = value[index]
|
|
86
95
|
|
|
87
96
|
prop_info = model.get_property_info(name)
|
|
88
97
|
|
|
@@ -21,12 +21,12 @@ xplan_tools/model/appschema/xplan60.py,sha256=W85nw3dWYFYCPi0B3MR_BYCSyL7F-amw0Y
|
|
|
21
21
|
xplan_tools/model/appschema/xplan61.py,sha256=J0ZhbgyZD5ZOvIOYXWCo2R4AygCe0QC5u5Ope2XPoM0,1319028
|
|
22
22
|
xplan_tools/model/appschema/xtrasse20.py,sha256=5zRbkFOOSOKqy5h8INzI6UvCmG0KqGAzNBQWXmfgaQw,537890
|
|
23
23
|
xplan_tools/model/appschema/xwp09.py,sha256=fYpLgKnL6vEscSPWxBWmB_VU4bidyQv0C3w91I_nmms,218518
|
|
24
|
-
xplan_tools/model/base.py,sha256=
|
|
24
|
+
xplan_tools/model/base.py,sha256=Zjs1svwzXcRM9nz5JdQZna44C5Zk4pqdHlHLnRmbq_U,29614
|
|
25
25
|
xplan_tools/model/migrations/env.py,sha256=dJw3GH3_pJn2LuiflD1wwJi7Dq-9avm56xdRc50Wzpg,1974
|
|
26
26
|
xplan_tools/model/migrations/script.py.mako,sha256=04kgeBtNMa4cCnG8CfQcKt6P6rnloIfj8wy0u_DBydM,704
|
|
27
27
|
xplan_tools/model/migrations/versions/3c3445a58565_base_schema.py,sha256=nsgcqTDFkcejdT4YqRfyQeDbWAHMqZJKVyZnUm5BY9A,7857
|
|
28
|
-
xplan_tools/model/migrations/versions/f8b74c08ec07_add_refs_indexes_ensure_polygon_ccw.py,sha256=
|
|
29
|
-
xplan_tools/model/orm.py,sha256=
|
|
28
|
+
xplan_tools/model/migrations/versions/f8b74c08ec07_add_refs_indexes_ensure_polygon_ccw.py,sha256=7qE9tkGeOKD1zxTiNxkiZNmF_1CNwylAblQC3c8aWzU,1239
|
|
29
|
+
xplan_tools/model/orm.py,sha256=THjjxFmmnIqfwYOZ_89AQJcOZdO3wM_mOk3QaG7J2rY,11720
|
|
30
30
|
xplan_tools/resources/styles.py,sha256=h0ezUqZrsXMQz2bTcF0nIyoI-IxMItstHx1j1xYGi3c,45010
|
|
31
31
|
xplan_tools/settings/__init__.py,sha256=yQdL0KFclWVUBE0ZMUTkktKMa9D78RDcPrHkK23Z9m8,89
|
|
32
32
|
xplan_tools/settings/settings.py,sha256=bABcqw7--TU-khpE9l-2XkavlQ-xuVZwmBmJiD0yRVw,462
|
|
@@ -40,10 +40,10 @@ xplan_tools/transform/migrate_60_61.py,sha256=S-fdnTjQUf8LGnEvsOY73zZYDvyVgIhVew
|
|
|
40
40
|
xplan_tools/transform/migrate_6x_plu.py,sha256=3w5UfjdUKFUiLma3Ppc9fAogPVxVshtUzzve0Dv0nWM,216797
|
|
41
41
|
xplan_tools/transform/transformer.py,sha256=2O4Aq_eTo9e2JOUwq9tJnfv6dwOxqNDdTGPtV_SAL1w,26216
|
|
42
42
|
xplan_tools/util/__init__.py,sha256=OqOorl5s8BZANbLeFE9wWlozvA64RINn9wigMkds2u8,11704
|
|
43
|
-
xplan_tools/util/style.py,sha256=
|
|
43
|
+
xplan_tools/util/style.py,sha256=xFAK-QH2XEEUo7AxXWx35s7hJtmrr1XaRHiqPH3YEMM,7959
|
|
44
44
|
xplan_tools/util/validate.py,sha256=3inTRLHrVonfQ9FDjtvSNKlAGem5DKtEvLqW7NxwWQs,3327
|
|
45
|
-
xplan_tools-1.
|
|
46
|
-
xplan_tools-1.
|
|
47
|
-
xplan_tools-1.
|
|
48
|
-
xplan_tools-1.
|
|
49
|
-
xplan_tools-1.
|
|
45
|
+
xplan_tools-1.14.0.dist-info/METADATA,sha256=_LdrPenkuJh4E1in4U4Jenh61EMwE1gZ4_j1wx7ohbE,4824
|
|
46
|
+
xplan_tools-1.14.0.dist-info/WHEEL,sha256=kJCRJT_g0adfAJzTx2GUMmS80rTJIVHRCfG0DQgLq3o,88
|
|
47
|
+
xplan_tools-1.14.0.dist-info/entry_points.txt,sha256=NV98QKVV3vDuWnJtWsKZvcpEH2N7SF1yHXvVMet23Ps,52
|
|
48
|
+
xplan_tools-1.14.0.dist-info/licenses/LICENSE.md,sha256=b8nnCcy_4Nd_v_okJ6mDKCvi64jkexzbSfIag7TR5mU,13827
|
|
49
|
+
xplan_tools-1.14.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|