overture-schema-common 0.1.1.dev0__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.
- overture_schema_common-0.1.1.dev0/PKG-INFO +13 -0
- overture_schema_common-0.1.1.dev0/pyproject.toml +41 -0
- overture_schema_common-0.1.1.dev0/pyproject.toml.orig +41 -0
- overture_schema_common-0.1.1.dev0/src/overture/schema/common/__init__.py +50 -0
- overture_schema_common-0.1.1.dev0/src/overture/schema/common/cartography.py +114 -0
- overture_schema_common-0.1.1.dev0/src/overture/schema/common/confidence.py +17 -0
- overture_schema_common-0.1.1.dev0/src/overture/schema/common/feature.py +103 -0
- overture_schema_common-0.1.1.dev0/src/overture/schema/common/level.py +23 -0
- overture_schema_common-0.1.1.dev0/src/overture/schema/common/names.py +230 -0
- overture_schema_common-0.1.1.dev0/src/overture/schema/common/perspectives.py +40 -0
- overture_schema_common-0.1.1.dev0/src/overture/schema/common/py.typed +0 -0
- overture_schema_common-0.1.1.dev0/src/overture/schema/common/scoping/__init__.py +394 -0
- overture_schema_common-0.1.1.dev0/src/overture/schema/common/scoping/heading.py +14 -0
- overture_schema_common-0.1.1.dev0/src/overture/schema/common/scoping/lr.py +105 -0
- overture_schema_common-0.1.1.dev0/src/overture/schema/common/scoping/opening_hours.py +21 -0
- overture_schema_common-0.1.1.dev0/src/overture/schema/common/scoping/purpose_of_use.py +18 -0
- overture_schema_common-0.1.1.dev0/src/overture/schema/common/scoping/recognized_status.py +18 -0
- overture_schema_common-0.1.1.dev0/src/overture/schema/common/scoping/scoped.py +495 -0
- overture_schema_common-0.1.1.dev0/src/overture/schema/common/scoping/side.py +16 -0
- overture_schema_common-0.1.1.dev0/src/overture/schema/common/scoping/travel_mode.py +24 -0
- overture_schema_common-0.1.1.dev0/src/overture/schema/common/scoping/vehicle.py +139 -0
- overture_schema_common-0.1.1.dev0/src/overture/schema/common/sources.py +139 -0
- overture_schema_common-0.1.1.dev0/src/overture/schema/common/tag_providers.py +130 -0
- overture_schema_common-0.1.1.dev0/src/overture/schema/common/unit.py +46 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: overture-schema-common
|
|
3
|
+
Version: 0.1.1.dev0
|
|
4
|
+
Summary: Common components that are shared across Overture theme schemas
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
Requires-Dist: overture-schema-system>=0.1.1
|
|
7
|
+
Requires-Dist: pydantic>=2.13.0
|
|
8
|
+
Requires-Dist: shapely>=2.1.1
|
|
9
|
+
Maintainer: Overture Maps Schema Working Group
|
|
10
|
+
Requires-Python: >=3.10
|
|
11
|
+
Project-URL: Homepage, https://overturemaps.org
|
|
12
|
+
Project-URL: Source, https://github.com/OvertureMaps/schema
|
|
13
|
+
Project-URL: Issues, https://github.com/OvertureMaps/schema/issues
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["uv_build>=0.11.32,<0.13"]
|
|
3
|
+
build-backend = "uv_build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "overture-schema-common"
|
|
7
|
+
version = "0.1.1.dev0"
|
|
8
|
+
description = "Common components that are shared across Overture theme schemas"
|
|
9
|
+
requires-python = ">=3.10"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
dependencies = [
|
|
12
|
+
"overture-schema-system>=0.1.1",
|
|
13
|
+
"pydantic>=2.13.0",
|
|
14
|
+
"shapely>=2.1.1",
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
[[project.maintainers]]
|
|
18
|
+
name = "Overture Maps Schema Working Group"
|
|
19
|
+
|
|
20
|
+
[project.urls]
|
|
21
|
+
Homepage = "https://overturemaps.org"
|
|
22
|
+
Source = "https://github.com/OvertureMaps/schema"
|
|
23
|
+
Issues = "https://github.com/OvertureMaps/schema/issues"
|
|
24
|
+
|
|
25
|
+
[project.entry-points."overture.tag_providers"]
|
|
26
|
+
overture = "overture.schema.common.tag_providers:overture_provider"
|
|
27
|
+
theme = "overture.schema.common.tag_providers:theme_provider"
|
|
28
|
+
|
|
29
|
+
[tool.uv.sources.overture-schema-system]
|
|
30
|
+
workspace = true
|
|
31
|
+
|
|
32
|
+
[tool.uv.build-backend]
|
|
33
|
+
module-name = "overture.schema.common"
|
|
34
|
+
|
|
35
|
+
[dependency-groups]
|
|
36
|
+
dev = [
|
|
37
|
+
"deepdiff>=8.6.0",
|
|
38
|
+
"jsonpath-ng>=1.7.0",
|
|
39
|
+
"types-pyyaml>=6.0.12.20250516",
|
|
40
|
+
"types-shapely>=2.1.0.20250710",
|
|
41
|
+
]
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["uv_build>=0.11.32,<0.13"]
|
|
3
|
+
build-backend = "uv_build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "overture-schema-common"
|
|
7
|
+
maintainers = [
|
|
8
|
+
{name = "Overture Maps Schema Working Group"},
|
|
9
|
+
]
|
|
10
|
+
version = "0.1.1.dev0"
|
|
11
|
+
description = "Common components that are shared across Overture theme schemas"
|
|
12
|
+
requires-python = ">=3.10"
|
|
13
|
+
license = "MIT"
|
|
14
|
+
dependencies = [
|
|
15
|
+
"overture-schema-system>=0.1.1",
|
|
16
|
+
"pydantic>=2.13.0",
|
|
17
|
+
"shapely>=2.1.1",
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
[project.urls]
|
|
21
|
+
Homepage = "https://overturemaps.org"
|
|
22
|
+
Source = "https://github.com/OvertureMaps/schema"
|
|
23
|
+
Issues = "https://github.com/OvertureMaps/schema/issues"
|
|
24
|
+
|
|
25
|
+
[tool.uv.sources]
|
|
26
|
+
overture-schema-system = { workspace = true }
|
|
27
|
+
|
|
28
|
+
[tool.uv.build-backend]
|
|
29
|
+
module-name = "overture.schema.common"
|
|
30
|
+
|
|
31
|
+
[dependency-groups]
|
|
32
|
+
dev = [
|
|
33
|
+
"deepdiff>=8.6.0",
|
|
34
|
+
"jsonpath-ng>=1.7.0",
|
|
35
|
+
"types-pyyaml>=6.0.12.20250516",
|
|
36
|
+
"types-shapely>=2.1.0.20250710",
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
[project.entry-points."overture.tag_providers"]
|
|
40
|
+
overture = "overture.schema.common.tag_providers:overture_provider"
|
|
41
|
+
theme = "overture.schema.common.tag_providers:theme_provider"
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Shared building blocks common to all Overture theme packages.
|
|
3
|
+
|
|
4
|
+
The `OvertureFeature` base class and the reusable feature components — naming, sources,
|
|
5
|
+
cartographic hints, scoping, and more — that theme packages compose to define their
|
|
6
|
+
feature types.
|
|
7
|
+
|
|
8
|
+
Subpackages
|
|
9
|
+
-----------
|
|
10
|
+
- :mod:`cartography <overture.schema.common.cartography>` Cartographic display hints.
|
|
11
|
+
- :mod:`confidence <overture.schema.common.confidence>` The `ConfidenceScore` type.
|
|
12
|
+
- :mod:`feature <overture.schema.common.feature>` The `OvertureFeature` base class and its
|
|
13
|
+
supporting types (`FeatureVersion`, `ThemeT`, `TypeT`).
|
|
14
|
+
- :mod:`level <overture.schema.common.level>` Feature Z-order / stacking (`Level`, `Stacked`).
|
|
15
|
+
- :mod:`names <overture.schema.common.names>` Multilingual naming with variants and rules.
|
|
16
|
+
- :mod:`perspectives <overture.schema.common.perspectives>` Political perspectives on disputed
|
|
17
|
+
data.
|
|
18
|
+
- :mod:`scoping <overture.schema.common.scoping>` Scoped, conditionally-applicable field values.
|
|
19
|
+
- :mod:`sources <overture.schema.common.sources>` Data provenance and source attribution.
|
|
20
|
+
- :mod:`unit <overture.schema.common.unit>` Units of measure.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
from . import (
|
|
24
|
+
cartography,
|
|
25
|
+
confidence,
|
|
26
|
+
feature,
|
|
27
|
+
level,
|
|
28
|
+
names,
|
|
29
|
+
perspectives,
|
|
30
|
+
scoping,
|
|
31
|
+
sources,
|
|
32
|
+
unit,
|
|
33
|
+
)
|
|
34
|
+
from .feature import FeatureVersion, OvertureFeature, ThemeT, TypeT
|
|
35
|
+
|
|
36
|
+
__all__ = [
|
|
37
|
+
"cartography",
|
|
38
|
+
"confidence",
|
|
39
|
+
"feature",
|
|
40
|
+
"FeatureVersion",
|
|
41
|
+
"level",
|
|
42
|
+
"names",
|
|
43
|
+
"OvertureFeature",
|
|
44
|
+
"perspectives",
|
|
45
|
+
"scoping",
|
|
46
|
+
"sources",
|
|
47
|
+
"ThemeT",
|
|
48
|
+
"TypeT",
|
|
49
|
+
"unit",
|
|
50
|
+
]
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Specify cartographic hints for features and fields of features.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import textwrap
|
|
6
|
+
from typing import Annotated, NewType
|
|
7
|
+
|
|
8
|
+
from pydantic import BaseModel, Field
|
|
9
|
+
|
|
10
|
+
from overture.schema.system.model_constraint import no_extra_fields
|
|
11
|
+
from overture.schema.system.numeric import int32
|
|
12
|
+
|
|
13
|
+
Prominence = NewType(
|
|
14
|
+
"Prominence",
|
|
15
|
+
Annotated[
|
|
16
|
+
int32,
|
|
17
|
+
Field(
|
|
18
|
+
ge=1,
|
|
19
|
+
le=100,
|
|
20
|
+
description=textwrap.dedent("""
|
|
21
|
+
Subjective scale of feature significance or importance, with 1 being the least, and
|
|
22
|
+
100 being the most, significant.
|
|
23
|
+
|
|
24
|
+
This value can be used to help drive decisions about how and when to display a
|
|
25
|
+
feature, and how to treat it relative to neighboring features.
|
|
26
|
+
|
|
27
|
+
When populated by Overture, this value is derived from various factors including,
|
|
28
|
+
but not limited to: feature and subtype, population, and capital status.
|
|
29
|
+
""").strip(),
|
|
30
|
+
),
|
|
31
|
+
],
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
MinZoom = NewType(
|
|
35
|
+
"MinZoom",
|
|
36
|
+
Annotated[
|
|
37
|
+
int32,
|
|
38
|
+
Field(
|
|
39
|
+
ge=0,
|
|
40
|
+
le=23,
|
|
41
|
+
description=textwrap.dedent("""
|
|
42
|
+
Recommended minimum tile zoom level in which this feature should be displayed.
|
|
43
|
+
|
|
44
|
+
It is recommended that the feature be hidden at zoom levels below this value.
|
|
45
|
+
|
|
46
|
+
Zoom levels follow the Slippy Maps convention, documented in the following
|
|
47
|
+
references:
|
|
48
|
+
- https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames
|
|
49
|
+
- https://www.maptiler.com/google-maps-coordinates-tile-bounds-projection
|
|
50
|
+
""").strip(),
|
|
51
|
+
),
|
|
52
|
+
],
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
MaxZoom = NewType(
|
|
56
|
+
"MaxZoom",
|
|
57
|
+
Annotated[
|
|
58
|
+
int32,
|
|
59
|
+
Field(
|
|
60
|
+
ge=0,
|
|
61
|
+
le=23,
|
|
62
|
+
description=textwrap.dedent("""
|
|
63
|
+
Recommended maximum tile zoom level in which this feature should be displayed.
|
|
64
|
+
|
|
65
|
+
It is recommended that the feature be hidden at zoom levels above this value.
|
|
66
|
+
|
|
67
|
+
Zoom levels follow the Slippy Maps convention, documented in the following
|
|
68
|
+
references:
|
|
69
|
+
- https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames
|
|
70
|
+
- https://www.maptiler.com/google-maps-coordinates-tile-bounds-projection
|
|
71
|
+
""").strip(),
|
|
72
|
+
),
|
|
73
|
+
],
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
SortKey = NewType(
|
|
77
|
+
"SortKey",
|
|
78
|
+
Annotated[
|
|
79
|
+
int32,
|
|
80
|
+
Field(
|
|
81
|
+
description=textwrap.dedent("""
|
|
82
|
+
Integer indicating the recommended order in which to draw features.
|
|
83
|
+
|
|
84
|
+
Features with a lower number should be drawn "in front" of features with a higher
|
|
85
|
+
number.
|
|
86
|
+
""").strip(),
|
|
87
|
+
),
|
|
88
|
+
],
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
@no_extra_fields
|
|
93
|
+
class CartographicHints(BaseModel):
|
|
94
|
+
"""Cartographic hints for optimal use of Overture features in map-making."""
|
|
95
|
+
|
|
96
|
+
# Optional
|
|
97
|
+
|
|
98
|
+
prominence: Prominence | None = None
|
|
99
|
+
min_zoom: MinZoom | None = None
|
|
100
|
+
max_zoom: MaxZoom | None = None
|
|
101
|
+
sort_key: SortKey | None = None
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
class CartographicallyHinted(BaseModel):
|
|
105
|
+
"""
|
|
106
|
+
Properties for adding cartographic hints to a model.
|
|
107
|
+
"""
|
|
108
|
+
|
|
109
|
+
cartography: Annotated[
|
|
110
|
+
CartographicHints | None,
|
|
111
|
+
Field(
|
|
112
|
+
description="Cartographic hints useful when including the feature in maps"
|
|
113
|
+
),
|
|
114
|
+
] = None
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Confidence scores for machine-generated or machine-augmented data.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import Annotated, NewType
|
|
6
|
+
|
|
7
|
+
from pydantic import Field
|
|
8
|
+
|
|
9
|
+
from overture.schema.system.numeric import float64
|
|
10
|
+
|
|
11
|
+
ConfidenceScore = NewType(
|
|
12
|
+
"ConfidenceScore",
|
|
13
|
+
Annotated[
|
|
14
|
+
float64,
|
|
15
|
+
Field(description="Confidence score between 0.0 and 1.0", ge=0.0, le=1.0),
|
|
16
|
+
],
|
|
17
|
+
)
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"""
|
|
2
|
+
The Overture feature, an Overture-specific refinement of the base `Feature` type defined in the
|
|
3
|
+
system package.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import textwrap
|
|
7
|
+
from typing import Annotated, Generic, NewType, TypeVar
|
|
8
|
+
|
|
9
|
+
from pydantic import (
|
|
10
|
+
ConfigDict,
|
|
11
|
+
Field,
|
|
12
|
+
GetJsonSchemaHandler,
|
|
13
|
+
model_validator,
|
|
14
|
+
)
|
|
15
|
+
from pydantic.json_schema import JsonSchemaValue
|
|
16
|
+
from pydantic_core import core_schema
|
|
17
|
+
from typing_extensions import Self
|
|
18
|
+
|
|
19
|
+
from overture.schema.system.feature import Feature
|
|
20
|
+
from overture.schema.system.numeric import int32
|
|
21
|
+
from overture.schema.system.ref import Id, Identified
|
|
22
|
+
|
|
23
|
+
from .sources import Sources
|
|
24
|
+
|
|
25
|
+
ThemeT = TypeVar("ThemeT", bound=str)
|
|
26
|
+
TypeT = TypeVar("TypeT", bound=str)
|
|
27
|
+
|
|
28
|
+
FeatureVersion = NewType(
|
|
29
|
+
"FeatureVersion", Annotated[int32, Field(ge=0, description="")]
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class OvertureFeature(Identified, Feature, Generic[ThemeT, TypeT]):
|
|
34
|
+
"""
|
|
35
|
+
Overture feature, the base class for all Overture features types.
|
|
36
|
+
|
|
37
|
+
An `OvertureFeature` extends the fundamental `Feature` type by:
|
|
38
|
+
- Making the basic ``id`` field required instead of optional.
|
|
39
|
+
- Adding required fields ``theme``, ``type``, and ``version``.
|
|
40
|
+
- Adding the optional field ``sources``.
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
# Only used to support `ext_*` fields, which are on a deprecation path.
|
|
44
|
+
model_config = ConfigDict(extra="allow")
|
|
45
|
+
|
|
46
|
+
# Required
|
|
47
|
+
|
|
48
|
+
# Repeating `id` from the superclass `Feature` to make it mandatory: it is optional in the
|
|
49
|
+
# superclass.
|
|
50
|
+
id: Id = Field(
|
|
51
|
+
description="A feature ID. This may be an ID associated with the Global Entity Reference System (GERS) if—and-only-if the feature represents an entity that is part of GERS."
|
|
52
|
+
) # type: ignore[assignment]
|
|
53
|
+
theme: ThemeT
|
|
54
|
+
type: TypeT
|
|
55
|
+
# Superclass `Feature` provides `geometry` and `bbox`.
|
|
56
|
+
version: FeatureVersion
|
|
57
|
+
|
|
58
|
+
# Optional
|
|
59
|
+
|
|
60
|
+
sources: Sources | None = None
|
|
61
|
+
|
|
62
|
+
@model_validator(mode="after")
|
|
63
|
+
def __validate_ext_fields__(self) -> Self:
|
|
64
|
+
extra = self.model_extra
|
|
65
|
+
invalid_extra_fields = (
|
|
66
|
+
[f for f in extra.keys() if not f.startswith("ext_")] if extra else ()
|
|
67
|
+
)
|
|
68
|
+
if invalid_extra_fields:
|
|
69
|
+
maybe_plural = "s" if len(invalid_extra_fields) > 1 else ""
|
|
70
|
+
raise ValueError(
|
|
71
|
+
f"invalid extra field name{maybe_plural}: {', '.join(invalid_extra_fields)} "
|
|
72
|
+
f"(extra fields are temporarily allowed, but only if their names start with 'ext_', "
|
|
73
|
+
f"but all extra field name support in {self.__class__.__name__} is on a deprecation path "
|
|
74
|
+
f"and will be removed)"
|
|
75
|
+
)
|
|
76
|
+
return self
|
|
77
|
+
|
|
78
|
+
@classmethod
|
|
79
|
+
def __get_pydantic_json_schema__(
|
|
80
|
+
cls,
|
|
81
|
+
schema: core_schema.CoreSchema,
|
|
82
|
+
handler: GetJsonSchemaHandler,
|
|
83
|
+
) -> JsonSchemaValue:
|
|
84
|
+
# Get the main Feature JSON schema.
|
|
85
|
+
json_schema = super().__get_pydantic_json_schema__(schema, handler)
|
|
86
|
+
|
|
87
|
+
# Explicitly allow `ext_*` properties, but no other properties, in the properties object.
|
|
88
|
+
# This feature only exists to get to initial parity between the hand-written JSON Schema and
|
|
89
|
+
# the Pydantic port. Once Pydantic is the primary, it will be deprecated.
|
|
90
|
+
properties_object_schema = json_schema["properties"]["properties"]
|
|
91
|
+
properties_object_schema["patternProperties"] = {
|
|
92
|
+
"^ext_.*$": {
|
|
93
|
+
"description": textwrap.dedent("""
|
|
94
|
+
Additional top-level properties are allowed if prefixed by `ext_`.
|
|
95
|
+
|
|
96
|
+
This feature is on a deprecation path and will be removed once the schema is
|
|
97
|
+
fully migrated to Pydantic.
|
|
98
|
+
""").strip(),
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
properties_object_schema["additionalProperties"] = False
|
|
102
|
+
|
|
103
|
+
return json_schema
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Z-order stacking.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import Annotated, NewType
|
|
6
|
+
|
|
7
|
+
from pydantic import BaseModel, Field
|
|
8
|
+
|
|
9
|
+
from overture.schema.system.numeric import int32
|
|
10
|
+
|
|
11
|
+
Level = NewType(
|
|
12
|
+
"Level",
|
|
13
|
+
Annotated[
|
|
14
|
+
int32,
|
|
15
|
+
Field(description="Z-order of the feature where 0 is visual level"),
|
|
16
|
+
],
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class Stacked(BaseModel):
|
|
21
|
+
"""Properties defining feature Z-order, i.e., stacking order."""
|
|
22
|
+
|
|
23
|
+
level: Level | None = 0 # type: ignore[assignment]
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Names for features and their child attributes.
|
|
3
|
+
|
|
4
|
+
This module includes all Overture's standard naming types. It supports multi-language names,
|
|
5
|
+
multiple name variants, and naming rules for specifying conditional or partial names to things.
|
|
6
|
+
|
|
7
|
+
Examples
|
|
8
|
+
--------
|
|
9
|
+
Create a feature type that can have a name:
|
|
10
|
+
|
|
11
|
+
>>> from typing import Literal
|
|
12
|
+
>>> from overture.schema.common import OvertureFeature
|
|
13
|
+
>>> from overture.schema.system.geometric import Geometry
|
|
14
|
+
>>> class MyFeature(OvertureFeature[Literal["mytheme"], Literal["mytype"]], Named):
|
|
15
|
+
... pass
|
|
16
|
+
...
|
|
17
|
+
>>> my_feature = MyFeature(
|
|
18
|
+
... id='12345678-1234-5678-9abc-123456789012',
|
|
19
|
+
... geometry=Geometry.from_wkt('POINT(0 0)'),
|
|
20
|
+
... theme='mytheme',
|
|
21
|
+
... type='mytype',
|
|
22
|
+
... version=1,
|
|
23
|
+
... names=Names(primary='my feature primary name')
|
|
24
|
+
... )
|
|
25
|
+
|
|
26
|
+
Create an arbitrary Pydantic model that can have a name:
|
|
27
|
+
|
|
28
|
+
>>> from pydantic import BaseModel
|
|
29
|
+
>>> from overture.schema.system.model_constraint import no_extra_fields
|
|
30
|
+
>>> @no_extra_fields
|
|
31
|
+
... class MyModel(Named):
|
|
32
|
+
... myfield: int
|
|
33
|
+
...
|
|
34
|
+
>>> MyModel(names=Names(primary='foo'), myfield=42)
|
|
35
|
+
MyModel(names=Names(primary='foo', common=None, rules=None), myfield=42)
|
|
36
|
+
|
|
37
|
+
Create a simple names structure with names in multiple languages:
|
|
38
|
+
|
|
39
|
+
>>> names = Names(
|
|
40
|
+
... primary='Le Léman',
|
|
41
|
+
... common={
|
|
42
|
+
... 'de': 'Genfersee',
|
|
43
|
+
... 'en': 'Lake Geneva',
|
|
44
|
+
... 'fr': 'Le Léman',
|
|
45
|
+
... }
|
|
46
|
+
... )
|
|
47
|
+
|
|
48
|
+
Create a name structure with official, alternate, and short names:
|
|
49
|
+
|
|
50
|
+
>>> names = Names(
|
|
51
|
+
... primary='City of New York',
|
|
52
|
+
... rules=[
|
|
53
|
+
... NameRule(value='New York', variant='official', language='en'),
|
|
54
|
+
... NameRule(value='New York City', variant='alternate', language='en'),
|
|
55
|
+
... NameRule(value='The Big Apple', variant='alternate', language='en'),
|
|
56
|
+
... NameRule(value='NYC', variant='alternate'),
|
|
57
|
+
... ]
|
|
58
|
+
... )
|
|
59
|
+
|
|
60
|
+
Create a name structure for a street where the name changes based on the side of the street.
|
|
61
|
+
|
|
62
|
+
>>> from overture.schema.common.scoping import Side
|
|
63
|
+
>>> names = Names(
|
|
64
|
+
... primary='Fir St',
|
|
65
|
+
... rules=[
|
|
66
|
+
... NameRule(value='2 Ave', variant='common', between=[0, 0.3], side=Side.LEFT),
|
|
67
|
+
... NameRule(value='Fir St', variant='common', between=[0.3, 1], side=Side.LEFT),
|
|
68
|
+
... NameRule(value='Fir St', variant='common', side=Side.RIGHT),
|
|
69
|
+
... ]
|
|
70
|
+
... )
|
|
71
|
+
"""
|
|
72
|
+
|
|
73
|
+
import textwrap
|
|
74
|
+
from typing import Annotated, NewType
|
|
75
|
+
|
|
76
|
+
from pydantic import BaseModel, Field
|
|
77
|
+
|
|
78
|
+
from overture.schema.common.perspectives import Perspectives
|
|
79
|
+
from overture.schema.common.scoping import Scope, scoped
|
|
80
|
+
from overture.schema.system.doc import DocumentedEnum
|
|
81
|
+
from overture.schema.system.model_constraint import no_extra_fields
|
|
82
|
+
from overture.schema.system.string import (
|
|
83
|
+
LanguageTag,
|
|
84
|
+
StrippedString,
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
CommonNames = NewType(
|
|
88
|
+
"CommonNames",
|
|
89
|
+
Annotated[
|
|
90
|
+
dict[
|
|
91
|
+
Annotated[
|
|
92
|
+
LanguageTag,
|
|
93
|
+
Field(
|
|
94
|
+
description=textwrap.dedent("""
|
|
95
|
+
A mapping from language to the most commonly used or recognized name in that
|
|
96
|
+
language.
|
|
97
|
+
|
|
98
|
+
Each entry consists of a key that is an IETF BCP 47 language tag; and a
|
|
99
|
+
value that reflects the common name in the language represented by the key's
|
|
100
|
+
language tag.
|
|
101
|
+
|
|
102
|
+
The validating regular expression for this property follows the pattern
|
|
103
|
+
described in https://www.rfc-editor.org/rfc/bcp/bcp47.txt with the exception
|
|
104
|
+
that private use tags are not supported.
|
|
105
|
+
""").strip(),
|
|
106
|
+
),
|
|
107
|
+
],
|
|
108
|
+
StrippedString,
|
|
109
|
+
],
|
|
110
|
+
Field(json_schema_extra={"additionalProperties": False}),
|
|
111
|
+
],
|
|
112
|
+
)
|
|
113
|
+
CommonNames.__doc__ = """A mapping from language to the most commonly used or recognized name in that language."""
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
class NameVariant(str, DocumentedEnum):
|
|
117
|
+
"""
|
|
118
|
+
Name variant used in a `NameRule`.
|
|
119
|
+
"""
|
|
120
|
+
|
|
121
|
+
COMMON = (
|
|
122
|
+
"common",
|
|
123
|
+
textwrap.dedent("""
|
|
124
|
+
The most commonly used or recognized name for a feature in the specified language.
|
|
125
|
+
|
|
126
|
+
In a `Names` value, most common names will appear in the `Names.common` field and will
|
|
127
|
+
not need to be specified as `NameRule` values in `Names.rules`. This member of the
|
|
128
|
+
enumeration should only be used to construct a `NameRule` if the common name needs to
|
|
129
|
+
be scoped in some way and therefore cannot be accurately represented in `CommonNames`.
|
|
130
|
+
""").strip(),
|
|
131
|
+
)
|
|
132
|
+
OFFICIAL = (
|
|
133
|
+
"official",
|
|
134
|
+
textwrap.dedent("""
|
|
135
|
+
The legally or administratively recognized name, often used by government agencies or
|
|
136
|
+
official documents.
|
|
137
|
+
""").strip(),
|
|
138
|
+
)
|
|
139
|
+
ALTERNATE = (
|
|
140
|
+
"alternate",
|
|
141
|
+
textwrap.dedent("""
|
|
142
|
+
An alternative name, which may be a historical name, a local colloquial name, or some
|
|
143
|
+
other well-known name is not the common name.
|
|
144
|
+
""").strip(),
|
|
145
|
+
)
|
|
146
|
+
SHORT = (
|
|
147
|
+
"short",
|
|
148
|
+
textwrap.dedent("""
|
|
149
|
+
An abbreviated or shortened version of the name, which may be an acronym or some other
|
|
150
|
+
commonly-used short form. An example is "NYC" for New York City.
|
|
151
|
+
""").strip(),
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
@no_extra_fields
|
|
156
|
+
@scoped(Scope.GEOMETRIC_RANGE, Scope.SIDE)
|
|
157
|
+
class NameRule(BaseModel):
|
|
158
|
+
"""
|
|
159
|
+
A rule that can be evaluated to determine the name in advanced scenarios.
|
|
160
|
+
|
|
161
|
+
Name rules are used for cases where the primary name is not sufficient; the common name is not
|
|
162
|
+
the right fit for the use case and another variant is needed; or where the name only applies in
|
|
163
|
+
certain specific circumstances.
|
|
164
|
+
|
|
165
|
+
Examples might include:
|
|
166
|
+
- An official, alternate, or short name.
|
|
167
|
+
- A name that only applies to part of a linear path like a road segment (geometric range
|
|
168
|
+
scoping).
|
|
169
|
+
- A name that only applies to the left or right side of a linear path like a road segment (side
|
|
170
|
+
scoping).
|
|
171
|
+
- A name that is only accepted by some political perspectives.
|
|
172
|
+
"""
|
|
173
|
+
|
|
174
|
+
# Required
|
|
175
|
+
|
|
176
|
+
value: Annotated[
|
|
177
|
+
StrippedString, Field(description="The actual name value.", min_length=1)
|
|
178
|
+
]
|
|
179
|
+
variant: NameVariant = Field(description="The name variant for this name rule.")
|
|
180
|
+
|
|
181
|
+
# Optional
|
|
182
|
+
|
|
183
|
+
language: Annotated[
|
|
184
|
+
LanguageTag | None,
|
|
185
|
+
Field(
|
|
186
|
+
description=textwrap.dedent("""
|
|
187
|
+
The language in which the name `value` is specified, if known, as an IETF BCP 47
|
|
188
|
+
language tag.
|
|
189
|
+
""").strip()
|
|
190
|
+
),
|
|
191
|
+
] = None
|
|
192
|
+
perspectives: (
|
|
193
|
+
Annotated[
|
|
194
|
+
Perspectives,
|
|
195
|
+
Field(
|
|
196
|
+
description="Political perspectives from which a named feature is viewed."
|
|
197
|
+
),
|
|
198
|
+
]
|
|
199
|
+
| None
|
|
200
|
+
) = None
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
@no_extra_fields
|
|
204
|
+
class Names(BaseModel):
|
|
205
|
+
"""Multilingual names container."""
|
|
206
|
+
|
|
207
|
+
# Required
|
|
208
|
+
|
|
209
|
+
primary: Annotated[
|
|
210
|
+
StrippedString, Field(min_length=1, description="The most commonly used name.")
|
|
211
|
+
]
|
|
212
|
+
|
|
213
|
+
# Optional
|
|
214
|
+
|
|
215
|
+
common: CommonNames | None = None
|
|
216
|
+
rules: Annotated[
|
|
217
|
+
list[NameRule] | None,
|
|
218
|
+
Field(
|
|
219
|
+
description="Rules for names that cannot be specified in the simple common names property. These rules can cover other name variants such as official, alternate, and short; and they can optionally include geometric scoping (linear referencing) and side-of-road scoping for complex cases.",
|
|
220
|
+
),
|
|
221
|
+
] = None
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
class Named(BaseModel):
|
|
225
|
+
"""Properties defining the names of a model."""
|
|
226
|
+
|
|
227
|
+
names: Annotated[
|
|
228
|
+
Names | None,
|
|
229
|
+
Field(description="All known names by which the feature is called"),
|
|
230
|
+
] = None
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Political perspectives.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from enum import Enum
|
|
6
|
+
from typing import Annotated
|
|
7
|
+
|
|
8
|
+
from pydantic import BaseModel, Field
|
|
9
|
+
|
|
10
|
+
from overture.schema.system.field_constraint import UniqueItemsConstraint
|
|
11
|
+
from overture.schema.system.model_constraint import no_extra_fields
|
|
12
|
+
from overture.schema.system.string import CountryCodeAlpha2
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class PerspectiveMode(str, Enum):
|
|
16
|
+
"""Perspective mode for disputed names."""
|
|
17
|
+
|
|
18
|
+
ACCEPTED_BY = "accepted_by"
|
|
19
|
+
DISPUTED_BY = "disputed_by"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@no_extra_fields
|
|
23
|
+
class Perspectives(BaseModel):
|
|
24
|
+
"""Political perspectives container."""
|
|
25
|
+
|
|
26
|
+
# Required
|
|
27
|
+
|
|
28
|
+
mode: Annotated[
|
|
29
|
+
PerspectiveMode,
|
|
30
|
+
Field(
|
|
31
|
+
description="Whether the perspective holder accepts or disputes this name."
|
|
32
|
+
),
|
|
33
|
+
]
|
|
34
|
+
countries: Annotated[
|
|
35
|
+
list[CountryCodeAlpha2],
|
|
36
|
+
Field(
|
|
37
|
+
min_length=1, description="Countries holding the given mode of perspective."
|
|
38
|
+
),
|
|
39
|
+
UniqueItemsConstraint(),
|
|
40
|
+
]
|
|
File without changes
|