diff --git a/PYDANTIC_GUIDE.md b/PYDANTIC_GUIDE.md index e7b4e8dbc..487168b2a 100644 --- a/PYDANTIC_GUIDE.md +++ b/PYDANTIC_GUIDE.md @@ -54,7 +54,7 @@ from overture.schema.system.string import ( NoWhitespaceString, StrippedString, ) -from overture.schema.common.types import ConfidenceScore +from overture.schema.common.confidence import ConfidenceScore from overture.schema.system.string import LanguageTag # Numeric types (use these instead of int/float) @@ -178,7 +178,7 @@ By specifying `OvertureFeature[Literal["buildings"], Literal["building"]]`, you' ```python from typing import Literal from overture.schema.common import OvertureFeature -from overture.schema.common.models import Stacked +from overture.schema.common.level import Stacked from overture.schema.common.names import Named from overture.schema.system.numeric import float64 @@ -1088,7 +1088,7 @@ properties: **Pydantic approach:** ```python -# In overture-schema-common/src/overture/schema/common/models.py +# In overture-schema-addresses-theme/src/overture/schema/addresses/address.py @no_extra_fields class Address(BaseModel): """A postal address.""" @@ -1131,7 +1131,7 @@ allOf: **Pydantic equivalent** uses **mixin classes**: ```python -# In common/models.py +# In common/names.py class Named(BaseModel): """Properties defining the names of a feature.""" names: Names | None = None diff --git a/packages/overture-schema-base-theme/src/overture/schema/base/infrastructure.py b/packages/overture-schema-base-theme/src/overture/schema/base/infrastructure.py index f9639657d..d22c05551 100644 --- a/packages/overture-schema-base-theme/src/overture/schema/base/infrastructure.py +++ b/packages/overture-schema-base-theme/src/overture/schema/base/infrastructure.py @@ -12,7 +12,7 @@ from overture.schema.common import ( OvertureFeature, ) -from overture.schema.common.models import Stacked +from overture.schema.common.level import Stacked from overture.schema.common.names import Named from overture.schema.system.geometric import ( Geometry, diff --git a/packages/overture-schema-base-theme/src/overture/schema/base/land.py b/packages/overture-schema-base-theme/src/overture/schema/base/land.py index 6bc908ef2..d3119912e 100644 --- a/packages/overture-schema-base-theme/src/overture/schema/base/land.py +++ b/packages/overture-schema-base-theme/src/overture/schema/base/land.py @@ -12,7 +12,7 @@ from overture.schema.common import ( OvertureFeature, ) -from overture.schema.common.models import Stacked +from overture.schema.common.level import Stacked from overture.schema.common.names import Named from overture.schema.system.geometric import ( Geometry, diff --git a/packages/overture-schema-base-theme/src/overture/schema/base/land_use.py b/packages/overture-schema-base-theme/src/overture/schema/base/land_use.py index 0bbf55617..d9a7d4a10 100644 --- a/packages/overture-schema-base-theme/src/overture/schema/base/land_use.py +++ b/packages/overture-schema-base-theme/src/overture/schema/base/land_use.py @@ -12,7 +12,7 @@ from overture.schema.common import ( OvertureFeature, ) -from overture.schema.common.models import Stacked +from overture.schema.common.level import Stacked from overture.schema.common.names import Named from overture.schema.system.geometric import ( Geometry, diff --git a/packages/overture-schema-base-theme/src/overture/schema/base/water.py b/packages/overture-schema-base-theme/src/overture/schema/base/water.py index ca831c655..fbf5ab4b9 100644 --- a/packages/overture-schema-base-theme/src/overture/schema/base/water.py +++ b/packages/overture-schema-base-theme/src/overture/schema/base/water.py @@ -10,7 +10,7 @@ from overture.schema.common import ( OvertureFeature, ) -from overture.schema.common.models import Stacked +from overture.schema.common.level import Stacked from overture.schema.common.names import Named from overture.schema.system.geometric import ( Geometry, diff --git a/packages/overture-schema-buildings-theme/src/overture/schema/buildings/building.py b/packages/overture-schema-buildings-theme/src/overture/schema/buildings/building.py index 43ed4883c..92d6390c3 100644 --- a/packages/overture-schema-buildings-theme/src/overture/schema/buildings/building.py +++ b/packages/overture-schema-buildings-theme/src/overture/schema/buildings/building.py @@ -10,7 +10,7 @@ from overture.schema.buildings._common import Appearance from overture.schema.common import OvertureFeature -from overture.schema.common.models import Stacked +from overture.schema.common.level import Stacked from overture.schema.common.names import Named from overture.schema.system.geometric import ( Geometry, diff --git a/packages/overture-schema-buildings-theme/src/overture/schema/buildings/building_part.py b/packages/overture-schema-buildings-theme/src/overture/schema/buildings/building_part.py index 9d83d01a2..29203c2db 100644 --- a/packages/overture-schema-buildings-theme/src/overture/schema/buildings/building_part.py +++ b/packages/overture-schema-buildings-theme/src/overture/schema/buildings/building_part.py @@ -9,7 +9,7 @@ from overture.schema.buildings._common import Appearance from overture.schema.buildings.building import Building from overture.schema.common import OvertureFeature -from overture.schema.common.models import Stacked +from overture.schema.common.level import Stacked from overture.schema.common.names import Named from overture.schema.system.geometric import ( Geometry, diff --git a/packages/overture-schema-common/src/overture/schema/common/__init__.py b/packages/overture-schema-common/src/overture/schema/common/__init__.py index 735c794c7..47fcadcad 100644 --- a/packages/overture-schema-common/src/overture/schema/common/__init__.py +++ b/packages/overture-schema-common/src/overture/schema/common/__init__.py @@ -1,15 +1,50 @@ -from . import cartography, names, scoping, sources -from .models import OvertureFeature, ThemeT, TypeT -from .scoping import Scope, scoped +""" +Shared building blocks common to all Overture theme packages. + +The `OvertureFeature` base class and the reusable feature components — naming, sources, +cartographic hints, scoping, and more — that theme packages compose to define their +feature types. + +Subpackages +----------- +- :mod:`cartography ` Cartographic display hints. +- :mod:`confidence ` The `ConfidenceScore` type. +- :mod:`feature ` The `OvertureFeature` base class and its + supporting types (`FeatureVersion`, `ThemeT`, `TypeT`). +- :mod:`level ` Feature Z-order / stacking (`Level`, `Stacked`). +- :mod:`names ` Multilingual naming with variants and rules. +- :mod:`perspectives ` Political perspectives on disputed + data. +- :mod:`scoping ` Scoped, conditionally-applicable field values. +- :mod:`sources ` Data provenance and source attribution. +- :mod:`unit ` Units of measure. +""" + +from . import ( + cartography, + confidence, + feature, + level, + names, + perspectives, + scoping, + sources, + unit, +) +from .feature import FeatureVersion, OvertureFeature, ThemeT, TypeT __all__ = [ "cartography", + "confidence", + "feature", + "FeatureVersion", + "level", "names", "OvertureFeature", - "Scope", - "scoped", + "perspectives", "scoping", "sources", "ThemeT", "TypeT", + "unit", ] diff --git a/packages/overture-schema-common/src/overture/schema/common/confidence.py b/packages/overture-schema-common/src/overture/schema/common/confidence.py new file mode 100644 index 000000000..d631e1a3a --- /dev/null +++ b/packages/overture-schema-common/src/overture/schema/common/confidence.py @@ -0,0 +1,17 @@ +""" +Confidence scores for machine-generated or machine-augmented data. +""" + +from typing import Annotated, NewType + +from pydantic import Field + +from overture.schema.system.numeric import float64 + +ConfidenceScore = NewType( + "ConfidenceScore", + Annotated[ + float64, + Field(description="Confidence score between 0.0 and 1.0", ge=0.0, le=1.0), + ], +) diff --git a/packages/overture-schema-common/src/overture/schema/common/enums.py b/packages/overture-schema-common/src/overture/schema/common/enums.py deleted file mode 100644 index b70f4b67f..000000000 --- a/packages/overture-schema-common/src/overture/schema/common/enums.py +++ /dev/null @@ -1,8 +0,0 @@ -from enum import Enum - - -class PerspectiveMode(str, Enum): - """Perspective mode for disputed names.""" - - ACCEPTED_BY = "accepted_by" - DISPUTED_BY = "disputed_by" diff --git a/packages/overture-schema-common/src/overture/schema/common/models.py b/packages/overture-schema-common/src/overture/schema/common/feature.py similarity index 70% rename from packages/overture-schema-common/src/overture/schema/common/models.py rename to packages/overture-schema-common/src/overture/schema/common/feature.py index 64fabc546..42d98da79 100644 --- a/packages/overture-schema-common/src/overture/schema/common/models.py +++ b/packages/overture-schema-common/src/overture/schema/common/feature.py @@ -1,8 +1,12 @@ +""" +The Overture feature, an Overture-specific refinement of the base `Feature` type defined in the +system package. +""" + import textwrap -from typing import Annotated, Generic, TypeVar +from typing import Annotated, Generic, NewType, TypeVar from pydantic import ( - BaseModel, ConfigDict, Field, GetJsonSchemaHandler, @@ -13,42 +17,42 @@ from typing_extensions import Self from overture.schema.system.feature import Feature -from overture.schema.system.field_constraint import UniqueItemsConstraint -from overture.schema.system.geometric import ( - Geometry, -) -from overture.schema.system.model_constraint import no_extra_fields +from overture.schema.system.numeric import int32 from overture.schema.system.ref import Id, Identified -from overture.schema.system.string import ( - CountryCodeAlpha2, -) -from .enums import PerspectiveMode from .sources import Sources -from .types import ( - FeatureVersion, - Level, -) ThemeT = TypeVar("ThemeT", bound=str) TypeT = TypeVar("TypeT", bound=str) +FeatureVersion = NewType( + "FeatureVersion", Annotated[int32, Field(ge=0, description="")] +) + class OvertureFeature(Identified, Feature, Generic[ThemeT, TypeT]): - """Base class for all Overture features.""" + """ + Overture feature, the base class for all Overture features types. + + An `OvertureFeature` extends the fundamental `Feature` type by: + - Making the basic ``id`` field required instead of optional. + - Adding required fields ``theme``, ``type``, and ``version``. + - Adding the optional field ``sources``. + """ # Only used to support `ext_*` fields, which are on a deprecation path. model_config = ConfigDict(extra="allow") # Required + # Repeating `id` from the superclass `Feature` to make it mandatory: it is optional in the + # superclass. id: Id = Field( 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." ) # type: ignore[assignment] theme: ThemeT - # this is an enum in the JSON Schema, but that prevents OvertureFeature from being extended type: TypeT - geometry: Geometry + # Superclass `Feature` provides `geometry` and `bbox`. version: FeatureVersion # Optional @@ -97,30 +101,3 @@ def __get_pydantic_json_schema__( properties_object_schema["additionalProperties"] = False return json_schema - - -@no_extra_fields -class Perspectives(BaseModel): - """Political perspectives container.""" - - # Required - - mode: Annotated[ - PerspectiveMode, - Field( - description="Whether the perspective holder accepts or disputes this name." - ), - ] - countries: Annotated[ - list[CountryCodeAlpha2], - Field( - min_length=1, description="Countries holding the given mode of perspective." - ), - UniqueItemsConstraint(), - ] - - -class Stacked(BaseModel): - """Properties defining feature Z-order, i.e., stacking order.""" - - level: Level | None = 0 # type: ignore[assignment] diff --git a/packages/overture-schema-common/src/overture/schema/common/level.py b/packages/overture-schema-common/src/overture/schema/common/level.py new file mode 100644 index 000000000..14ea6f15d --- /dev/null +++ b/packages/overture-schema-common/src/overture/schema/common/level.py @@ -0,0 +1,23 @@ +""" +Z-order stacking. +""" + +from typing import Annotated, NewType + +from pydantic import BaseModel, Field + +from overture.schema.system.numeric import int32 + +Level = NewType( + "Level", + Annotated[ + int32, + Field(description="Z-order of the feature where 0 is visual level"), + ], +) + + +class Stacked(BaseModel): + """Properties defining feature Z-order, i.e., stacking order.""" + + level: Level | None = 0 # type: ignore[assignment] diff --git a/packages/overture-schema-common/src/overture/schema/common/names.py b/packages/overture-schema-common/src/overture/schema/common/names.py index 80b5aa4e8..bbab086d4 100644 --- a/packages/overture-schema-common/src/overture/schema/common/names.py +++ b/packages/overture-schema-common/src/overture/schema/common/names.py @@ -75,7 +75,7 @@ from pydantic import BaseModel, Field -from overture.schema.common.models import Perspectives +from overture.schema.common.perspectives import Perspectives from overture.schema.common.scoping import Scope, scoped from overture.schema.system.doc import DocumentedEnum from overture.schema.system.model_constraint import no_extra_fields diff --git a/packages/overture-schema-common/src/overture/schema/common/perspectives.py b/packages/overture-schema-common/src/overture/schema/common/perspectives.py new file mode 100644 index 000000000..f7f4695ee --- /dev/null +++ b/packages/overture-schema-common/src/overture/schema/common/perspectives.py @@ -0,0 +1,40 @@ +""" +Political perspectives. +""" + +from enum import Enum +from typing import Annotated + +from pydantic import BaseModel, Field + +from overture.schema.system.field_constraint import UniqueItemsConstraint +from overture.schema.system.model_constraint import no_extra_fields +from overture.schema.system.string import CountryCodeAlpha2 + + +class PerspectiveMode(str, Enum): + """Perspective mode for disputed names.""" + + ACCEPTED_BY = "accepted_by" + DISPUTED_BY = "disputed_by" + + +@no_extra_fields +class Perspectives(BaseModel): + """Political perspectives container.""" + + # Required + + mode: Annotated[ + PerspectiveMode, + Field( + description="Whether the perspective holder accepts or disputes this name." + ), + ] + countries: Annotated[ + list[CountryCodeAlpha2], + Field( + min_length=1, description="Countries holding the given mode of perspective." + ), + UniqueItemsConstraint(), + ] diff --git a/packages/overture-schema-common/src/overture/schema/common/scoping/__init__.py b/packages/overture-schema-common/src/overture/schema/common/scoping/__init__.py index bed8ef3f2..0d1f8b016 100644 --- a/packages/overture-schema-common/src/overture/schema/common/scoping/__init__.py +++ b/packages/overture-schema-common/src/overture/schema/common/scoping/__init__.py @@ -17,7 +17,7 @@ >>> from typing import Annotated, Literal >>> from pydantic import BaseModel ->>> from overture.schema.common.models import OvertureFeature +>>> from overture.schema.common.feature import OvertureFeature >>> from overture.schema.system.geometric import ( ... Geometry, ... GeometryType, @@ -71,7 +71,7 @@ >>> from typing import Annotated, Literal >>> from pydantic import BaseModel ->>> from overture.schema.common.models import OvertureFeature +>>> from overture.schema.common.feature import OvertureFeature >>> from overture.schema.system.geometric import ( ... Geometry, ... GeometryType, @@ -119,7 +119,7 @@ >>> from typing import Annotated, Literal >>> from pydantic import BaseModel, Field ->>> from overture.schema.common.models import OvertureFeature +>>> from overture.schema.common.feature import OvertureFeature >>> from overture.schema.system.geometric import ( ... Geometry, ... GeometryType, @@ -212,7 +212,7 @@ >>> from typing import Annotated, Literal >>> from pydantic import BaseModel ->>> from overture.schema.common.models import OvertureFeature +>>> from overture.schema.common.feature import OvertureFeature >>> from overture.schema.system.geometric import ( ... Geometry, ... GeometryType, diff --git a/packages/overture-schema-common/src/overture/schema/common/sources.py b/packages/overture-schema-common/src/overture/schema/common/sources.py index 0d1326be5..0b3dc4cdc 100644 --- a/packages/overture-schema-common/src/overture/schema/common/sources.py +++ b/packages/overture-schema-common/src/overture/schema/common/sources.py @@ -8,8 +8,8 @@ from pydantic import BaseModel, Field +from overture.schema.common.confidence import ConfidenceScore from overture.schema.common.scoping import Scope, scoped -from overture.schema.common.types import ConfidenceScore from overture.schema.system.field_constraint import UniqueItemsConstraint from overture.schema.system.model_constraint import no_extra_fields from overture.schema.system.string import ( diff --git a/packages/overture-schema-common/src/overture/schema/common/types.py b/packages/overture-schema-common/src/overture/schema/common/types.py deleted file mode 100644 index 4639d342c..000000000 --- a/packages/overture-schema-common/src/overture/schema/common/types.py +++ /dev/null @@ -1,44 +0,0 @@ -from typing import Annotated, NewType - -from pydantic import ( - Field, -) - -from overture.schema.system.numeric import float64, int32 - -ConfidenceScore = NewType( - "ConfidenceScore", - Annotated[ - float64, - Field(description="Confidence score between 0.0 and 1.0", ge=0.0, le=1.0), - ], -) - - -Level = NewType( - "Level", - Annotated[ - int32, - Field(description="Z-order of the feature where 0 is visual level"), - ], -) - -FeatureVersion = NewType( - "FeatureVersion", Annotated[int32, Field(ge=0, description="")] -) - -# this is an enum in the JSON Schema, but that prevents OvertureFeature from being extended -Theme = Annotated[ - str, Field(description="Top-level Overture theme this feature belongs to") -] - -# this is an enum in the JSON Schema, but that prevents OvertureFeature from being extended -Type = Annotated[str, Field(description="Specific feature type within the theme")] - -__all__ = [ - "ConfidenceScore", - "FeatureVersion", - "Level", - "Theme", - "Type", -] diff --git a/packages/overture-schema-common/tests/test_models.py b/packages/overture-schema-common/tests/test_models.py index 9d819de4e..d29d00df7 100644 --- a/packages/overture-schema-common/tests/test_models.py +++ b/packages/overture-schema-common/tests/test_models.py @@ -4,7 +4,7 @@ import pytest from deepdiff import DeepDiff -from overture.schema.common.models import OvertureFeature +from overture.schema.common.feature import OvertureFeature from overture.schema.common.sources import SourceItem from overture.schema.system.geometric import ( BBox, diff --git a/packages/overture-schema-divisions-theme/src/overture/schema/divisions/__init__.py b/packages/overture-schema-divisions-theme/src/overture/schema/divisions/__init__.py index 00e8cabc6..bbe796055 100644 --- a/packages/overture-schema-divisions-theme/src/overture/schema/divisions/__init__.py +++ b/packages/overture-schema-divisions-theme/src/overture/schema/divisions/__init__.py @@ -21,8 +21,8 @@ "CapitalOfDivisionItem", "Division", "DivisionArea", + "DivisionBoundary", "DivisionClass", "DivisionSubtype", - "DivisionBoundary", "Norms", ] diff --git a/packages/overture-schema-divisions-theme/src/overture/schema/divisions/division.py b/packages/overture-schema-divisions-theme/src/overture/schema/divisions/division.py index 3af64df23..a97e2e516 100644 --- a/packages/overture-schema-divisions-theme/src/overture/schema/divisions/division.py +++ b/packages/overture-schema-divisions-theme/src/overture/schema/divisions/division.py @@ -13,10 +13,10 @@ OvertureFeature, ) from overture.schema.common.cartography import CartographicallyHinted -from overture.schema.common.models import ( +from overture.schema.common.names import CommonNames, Named, Names +from overture.schema.common.perspectives import ( Perspectives, ) -from overture.schema.common.names import CommonNames, Named, Names from overture.schema.common.scoping.side import Side from overture.schema.system.doc import DocumentedEnum from overture.schema.system.field_constraint import ( diff --git a/packages/overture-schema-divisions-theme/src/overture/schema/divisions/division_boundary.py b/packages/overture-schema-divisions-theme/src/overture/schema/divisions/division_boundary.py index 60597cf29..5c7d29a95 100644 --- a/packages/overture-schema-divisions-theme/src/overture/schema/divisions/division_boundary.py +++ b/packages/overture-schema-divisions-theme/src/overture/schema/divisions/division_boundary.py @@ -8,7 +8,7 @@ from overture.schema.common import ( OvertureFeature, ) -from overture.schema.common.models import Perspectives +from overture.schema.common.perspectives import Perspectives from overture.schema.system.doc import DocumentedEnum from overture.schema.system.field_constraint import UniqueItemsConstraint from overture.schema.system.geometric import ( diff --git a/packages/overture-schema-places-theme/src/overture/schema/places/place.py b/packages/overture-schema-places-theme/src/overture/schema/places/place.py index 3682e8f8a..6d65b46cf 100644 --- a/packages/overture-schema-places-theme/src/overture/schema/places/place.py +++ b/packages/overture-schema-places-theme/src/overture/schema/places/place.py @@ -11,12 +11,12 @@ from overture.schema.common import ( OvertureFeature, ) +from overture.schema.common.confidence import ( + ConfidenceScore, +) from overture.schema.common.names import ( Named, ) -from overture.schema.common.types import ( - ConfidenceScore, -) from overture.schema.system.field_constraint import ( UniqueItemsConstraint, ) diff --git a/packages/overture-schema-transportation-theme/src/overture/schema/transportation/models.py b/packages/overture-schema-transportation-theme/src/overture/schema/transportation/models.py index fc7554930..4f1727a3a 100644 --- a/packages/overture-schema-transportation-theme/src/overture/schema/transportation/models.py +++ b/packages/overture-schema-transportation-theme/src/overture/schema/transportation/models.py @@ -5,10 +5,10 @@ from pydantic import BaseModel, ConfigDict, Field from overture.schema.common import OvertureFeature -from overture.schema.common.scoping import Heading, Scope, scoped -from overture.schema.common.types import ( +from overture.schema.common.level import ( Level, ) +from overture.schema.common.scoping import Heading, Scope, scoped from overture.schema.common.unit import SpeedUnit from overture.schema.system.field_constraint import UniqueItemsConstraint from overture.schema.system.model_constraint import (