diff --git a/PYDANTIC_GUIDE.md b/PYDANTIC_GUIDE.md index 98dbf5005..e7b4e8dbc 100644 --- a/PYDANTIC_GUIDE.md +++ b/PYDANTIC_GUIDE.md @@ -42,7 +42,7 @@ from pydantic import BaseModel, Field # Overture common models from overture.schema.common import OvertureFeature -from overture.schema.system.primitive import Geometry, GeometryType, GeometryTypeConstraint +from overture.schema.system.geometric import Geometry, GeometryType, GeometryTypeConstraint # Validation system from overture.schema.system.field_constraint import UniqueItemsConstraint @@ -57,8 +57,8 @@ from overture.schema.system.string import ( from overture.schema.common.types import ConfidenceScore from overture.schema.system.string import LanguageTag -# Numeric primitives (use these instead of int/float) -from overture.schema.system.primitive import ( +# Numeric types (use these instead of int/float) +from overture.schema.system.numeric import ( int8, int32, int64, uint8, uint16, uint32, float32, float64 @@ -71,7 +71,7 @@ from overture.schema.system.primitive import ( from typing import Annotated from pydantic import BaseModel, Field from overture.schema.system.model_constraint import no_extra_fields -from overture.schema.system.primitive import int8, float64 +from overture.schema.system.numeric import int8, float64 @no_extra_fields class MyCustomType(BaseModel): @@ -101,7 +101,7 @@ class MyCustomType(BaseModel): from typing import Annotated, Literal from pydantic import Field from overture.schema.common import OvertureFeature -from overture.schema.system.primitive import Geometry, GeometryType, GeometryTypeConstraint +from overture.schema.system.geometric import Geometry, GeometryType, GeometryTypeConstraint class MyFeature(OvertureFeature[Literal["my_theme"], Literal["my_type"]]): """Description of what this feature represents.""" @@ -152,7 +152,7 @@ class Address(BaseModel): ```python from typing import Literal from overture.schema.common import OvertureFeature -from overture.schema.system.primitive import float64 +from overture.schema.system.numeric import float64 class Building(OvertureFeature[Literal["buildings"], Literal["building"]]): """A building feature with strongly-typed theme and type.""" @@ -180,7 +180,7 @@ from typing import Literal from overture.schema.common import OvertureFeature from overture.schema.common.models import Stacked from overture.schema.common.names import Named -from overture.schema.system.primitive import float64 +from overture.schema.system.numeric import float64 class Building(OvertureFeature[Literal["buildings"], Literal["building"]], Named, Stacked): # Gets fields from Feature: id, theme, type, geometry, etc. @@ -259,13 +259,13 @@ class Building(OvertureFeature): Keep the schema separate from business logic. The schema describes the shape of data, not the business rules about what missing values mean. -#### Numeric Primitives +#### Numeric Types **Always use specific numeric types instead of Python's generic `int`/`float`:** ```python from overture.schema.system.model_constraint import no_extra_fields -from overture.schema.system.primitive import ( +from overture.schema.system.numeric import ( int8, int32, int64, # Signed integers uint8, uint16, uint32, # Unsigned integers float32, float64 # Floating point @@ -1174,7 +1174,7 @@ JSON Schema containers become **mixin classes** in Pydantic that you inherit fro from typing import Annotated from pydantic import BaseModel, Field from overture.schema.system.model_constraint import no_extra_fields -from overture.schema.system.primitive import int8, float64 +from overture.schema.system.numeric import int8, float64 @no_extra_fields class MyCustomType(BaseModel): @@ -1204,7 +1204,7 @@ class MyCustomType(BaseModel): from typing import Annotated, Literal from pydantic import Field from overture.schema.common import OvertureFeature -from overture.schema.system.primitive import Geometry, GeometryType, GeometryTypeConstraint +from overture.schema.system.geometric import Geometry, GeometryType, GeometryTypeConstraint class MyFeature(OvertureFeature[Literal["my_theme"], Literal["my_type"]]): """Description of what this feature represents.""" @@ -1263,7 +1263,7 @@ class Contact(BaseModel): from typing import Annotated, Literal from pydantic import Field from overture.schema.common import OvertureFeature -from overture.schema.system.primitive import float64 +from overture.schema.system.numeric import float64 from overture.schema.system.ref import Id, Reference, Relationship class MyAssociation(OvertureFeature[Literal["associations"], Literal["my_association"]]): @@ -1349,7 +1349,7 @@ from pydantic import Field from overture.schema.common import OvertureFeature from overture.schema.system.field_constraint import UniqueItemsConstraint from overture.schema.system.model_constraint import no_extra_fields -from overture.schema.system.primitive import int32, float64 +from overture.schema.system.numeric import int32, float64 # For associations and references from overture.schema.system.ref import Id, Reference, Relationship diff --git a/README.pydantic.md b/README.pydantic.md index 76bd78e1f..e03afba56 100644 --- a/README.pydantic.md +++ b/README.pydantic.md @@ -90,9 +90,9 @@ This workspace contains the following packages: convenient usage - **`overture-schema-common`** - Overture-specific models shared across themes: base feature class, scoping framework, names, sources, and cartographic hints -- **`overture-schema-system`** - Portable primitive types, constraints, and a - GeoJSON-aware base model for building Pydantic schemas that serialize to - JSON, Parquet, and Spark +- **`overture-schema-system`** - Portable numeric, geometric, and string types, + constraints, and a GeoJSON-aware base model for building Pydantic schemas that + serialize to JSON, Parquet, and Spark ### Theme Packages diff --git a/packages/overture-schema-addresses-theme/src/overture/schema/addresses/address.py b/packages/overture-schema-addresses-theme/src/overture/schema/addresses/address.py index baf93f839..a6565dad5 100644 --- a/packages/overture-schema-addresses-theme/src/overture/schema/addresses/address.py +++ b/packages/overture-schema-addresses-theme/src/overture/schema/addresses/address.py @@ -10,12 +10,12 @@ from overture.schema.common import ( OvertureFeature, ) -from overture.schema.system.model_constraint import no_extra_fields -from overture.schema.system.primitive import ( +from overture.schema.system.geometric import ( Geometry, GeometryType, GeometryTypeConstraint, ) +from overture.schema.system.model_constraint import no_extra_fields from overture.schema.system.string import CountryCodeAlpha2, StrippedString diff --git a/packages/overture-schema-base-theme/src/overture/schema/base/_common.py b/packages/overture-schema-base-theme/src/overture/schema/base/_common.py index e0b777947..2d0523a1d 100644 --- a/packages/overture-schema-base-theme/src/overture/schema/base/_common.py +++ b/packages/overture-schema-base-theme/src/overture/schema/base/_common.py @@ -4,7 +4,7 @@ from pydantic import BaseModel, Field -from overture.schema.system.primitive import float64, int32 +from overture.schema.system.numeric import float64, int32 from overture.schema.system.string import WikidataId Depth = NewType( diff --git a/packages/overture-schema-base-theme/src/overture/schema/base/bathymetry.py b/packages/overture-schema-base-theme/src/overture/schema/base/bathymetry.py index 9f525728a..d8f3ec8f7 100644 --- a/packages/overture-schema-base-theme/src/overture/schema/base/bathymetry.py +++ b/packages/overture-schema-base-theme/src/overture/schema/base/bathymetry.py @@ -10,7 +10,7 @@ OvertureFeature, ) from overture.schema.common.cartography import CartographicallyHinted -from overture.schema.system.primitive import ( +from overture.schema.system.geometric import ( Geometry, GeometryType, GeometryTypeConstraint, 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 fee9d67c4..f9639657d 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 @@ -14,7 +14,7 @@ ) from overture.schema.common.models import Stacked from overture.schema.common.names import Named -from overture.schema.system.primitive import ( +from overture.schema.system.geometric import ( Geometry, GeometryType, GeometryTypeConstraint, 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 6775842b7..6bc908ef2 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 @@ -14,7 +14,7 @@ ) from overture.schema.common.models import Stacked from overture.schema.common.names import Named -from overture.schema.system.primitive import ( +from overture.schema.system.geometric import ( Geometry, GeometryType, GeometryTypeConstraint, diff --git a/packages/overture-schema-base-theme/src/overture/schema/base/land_cover.py b/packages/overture-schema-base-theme/src/overture/schema/base/land_cover.py index 29eeb5e19..4ea176e14 100644 --- a/packages/overture-schema-base-theme/src/overture/schema/base/land_cover.py +++ b/packages/overture-schema-base-theme/src/overture/schema/base/land_cover.py @@ -11,7 +11,7 @@ OvertureFeature, ) from overture.schema.common.cartography import CartographicallyHinted -from overture.schema.system.primitive import ( +from overture.schema.system.geometric import ( Geometry, GeometryType, GeometryTypeConstraint, 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 20a99c06a..0bbf55617 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 @@ -14,7 +14,7 @@ ) from overture.schema.common.models import Stacked from overture.schema.common.names import Named -from overture.schema.system.primitive import ( +from overture.schema.system.geometric import ( Geometry, GeometryType, GeometryTypeConstraint, 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 d90971bb4..ca831c655 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 @@ -12,7 +12,7 @@ ) from overture.schema.common.models import Stacked from overture.schema.common.names import Named -from overture.schema.system.primitive import ( +from overture.schema.system.geometric import ( Geometry, GeometryType, GeometryTypeConstraint, diff --git a/packages/overture-schema-buildings-theme/src/overture/schema/buildings/_common.py b/packages/overture-schema-buildings-theme/src/overture/schema/buildings/_common.py index b2b558718..9f02c1bb0 100644 --- a/packages/overture-schema-buildings-theme/src/overture/schema/buildings/_common.py +++ b/packages/overture-schema-buildings-theme/src/overture/schema/buildings/_common.py @@ -5,7 +5,7 @@ from pydantic import BaseModel, Field from overture.schema.system.doc import DocumentedEnum -from overture.schema.system.primitive import float64, int32 +from overture.schema.system.numeric import float64, int32 from overture.schema.system.string import HexColor 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 d40d3e296..43ed4883c 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 @@ -12,7 +12,7 @@ from overture.schema.common import OvertureFeature from overture.schema.common.models import Stacked from overture.schema.common.names import Named -from overture.schema.system.primitive import ( +from overture.schema.system.geometric import ( Geometry, GeometryType, GeometryTypeConstraint, 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 ce0ed2c46..9d83d01a2 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 @@ -11,7 +11,7 @@ from overture.schema.common import OvertureFeature from overture.schema.common.models import Stacked from overture.schema.common.names import Named -from overture.schema.system.primitive import ( +from overture.schema.system.geometric import ( Geometry, GeometryType, GeometryTypeConstraint, diff --git a/packages/overture-schema-codegen/README.md b/packages/overture-schema-codegen/README.md index 61c029505..67c35002e 100644 --- a/packages/overture-schema-codegen/README.md +++ b/packages/overture-schema-codegen/README.md @@ -65,7 +65,7 @@ module structure. Link computation and reverse references enable cross-page navi **Rendering** consumes specs and owns all presentation decisions. Markdown output uses Jinja2 templates for feature pages (with field tables, constraint sections, and -examples), enum pages, NewType pages, and aggregate primitive/geometry reference pages. +examples), enum pages, NewType pages, and aggregate numeric/geometry reference pages. `markdown/pipeline.py` orchestrates the full pipeline without I/O, returning `list[RenderedPage]`. The CLI writes files to disk with Docusaurus frontmatter. diff --git a/packages/overture-schema-codegen/docs/design.md b/packages/overture-schema-codegen/docs/design.md index f7387c96e..b58dad1b7 100644 --- a/packages/overture-schema-codegen/docs/design.md +++ b/packages/overture-schema-codegen/docs/design.md @@ -258,7 +258,7 @@ to registered primitives. ### Markdown renderer -Jinja2 templates for feature, enum, NewType, primitives, and geometry pages. +Jinja2 templates for feature, enum, NewType, numeric, and geometry pages. `render_model()` walks each field's `FieldShape` tree and expands `ModelRef` terminals inline with dot-notation (e.g., `sources[].dataset`), stopping at `ModelRef.starts_cycle`. `format_type()` in `markdown/type_format.py` converts a diff --git a/packages/overture-schema-codegen/docs/walkthrough.md b/packages/overture-schema-codegen/docs/walkthrough.md index 7cfabf84e..4c13e0d8a 100644 --- a/packages/overture-schema-codegen/docs/walkthrough.md +++ b/packages/overture-schema-codegen/docs/walkthrough.md @@ -351,12 +351,13 @@ discriminator attribute. For Segment, it finds `subtype` and builds the mapping: `{"road": RoadSegment, "rail": RailSegment, "water": WaterSegment}` by checking each member for single-value `Literal` fields on the discriminator. -### Primitive extraction +### Numeric and geometry extraction -`partition_numeric_and_geometry_types` reads a module's `__all__` exports. NewType -exports are numeric primitives; non-constraint class exports are geometry types. +`partition_numeric_and_geometry_types` reads the numeric and geometric modules' +`__all__` exports. NewType exports of the numeric module are numeric types; +non-constraint class exports of the geometric module are geometry types. -`extract_numerics` builds `NumericSpec` objects. For each primitive name it resolves +`extract_numerics` builds `NumericSpec` objects. For each numeric type name it resolves the object from the module, calls `extract_newtype` for the type analysis, then extracts numeric bounds from constraints. `extract_numeric_bounds` scans constraint objects for `ge`/`gt`/`le`/`lt` attributes and packs them into an `Interval`. @@ -443,9 +444,9 @@ independent `if` statements, not `elif`. `build_placement_registry` builds the complete `dict[TypeIdentity, PurePosixPath]` mapping each type to its output file path. Four tiers: -Aggregate pages come first. All numeric primitives point to -`system/primitive/primitives.md`. All geometry types point to -`system/primitive/geometry.md`. These are hardcoded paths since the types share a single +Aggregate pages come first. All numeric types point to +`system/numeric.md`. All geometry types point to +`system/geometric.md`. These are hardcoded paths since the types share a single reference page. Feature specs get individual pages. Output directories derive from @@ -533,7 +534,7 @@ Six Jinja2 templates in `markdown/templates/`. `feature.md.jinja2` renders a fie with Name, Type, and Description columns, an optional Constraints section, an optional Examples section, and a "Used By" partial. `enum.md.jinja2` renders a bullet list of values. `newtype.md.jinja2` shows underlying type and constraints with provenance links. -`primitives.md.jinja2` and `geometry.md.jinja2` render aggregate reference pages. +`numeric.md.jinja2` and `geometric.md.jinja2` render aggregate reference pages. `_used_by.md.jinja2` is an included partial. The Jinja2 environment registers `linkify_urls` as a filter, which wraps bare URLs in @@ -575,7 +576,7 @@ truncate at 100 characters. Lists and dicts use compact bracket/brace notation. ### Aggregate pages -`render_primitives_from_specs` sorts primitives by bit-width key (prefix then numeric +`render_numeric_from_specs` sorts numeric types by bit-width key (prefix then numeric width), groups into signed integers, unsigned integers, and floats, and formats ranges. Integer ranges show both bounds as a compact "lower to upper" form; `int64`-scale bounds use `2^63` notation for readability. `render_geometry_from_values` produces a @@ -628,8 +629,8 @@ pipeline. feature specs and a schema root, returns rendered pages without touching the filesystem. Seven steps (tree expansion happens inside `extract_model`): -1. **Partition primitive and geometry names** from the system primitive module's - `__all__` exports. +1. **Partition numeric and geometry names** from the system numeric and geometric + modules' `__all__` exports. 2. **Collect supplementary types** by walking feature trees. @@ -642,7 +643,7 @@ Seven steps (tree expansion happens inside `extract_model`): 6. **Render each supplementary type** -- dispatching to `render_enum`, `render_newtype`, `render_model` (for sub-models), or `render_pydantic_type` based on spec type. -7. **Render aggregate pages** for primitives and geometry. +7. **Render aggregate pages** for numeric types and geometry. The return value is `list[RenderedPage]` -- frozen dataclasses carrying content, output path, and a boolean `is_model` flag. The caller decides what to do with them. @@ -703,7 +704,8 @@ values. Sub-model `FieldShape` trees are fully resolved -- `ModelRef` nodes already carry their `RecordSpec` from recursive `extract_model` calls. No separate expansion pass is needed. -**Layout.** `partition_numeric_and_geometry_types` reads the system module's exports. +**Layout.** `partition_numeric_and_geometry_types` reads the system numeric and +geometric modules' exports. `collect_all_supplementary_types` walks Segment's field shapes and discovers referenced enums (like `Subtype`), semantic NewTypes (like `Id`, `Sources`), and sub-models. The walk follows `ModelRef.model` references down the tree, and for `UnionRef` shapes, diff --git a/packages/overture-schema-codegen/src/overture/schema/codegen/extraction/field_constraints.py b/packages/overture-schema-codegen/src/overture/schema/codegen/extraction/field_constraints.py index 1cf1f2f15..cf77e5274 100644 --- a/packages/overture-schema-codegen/src/overture/schema/codegen/extraction/field_constraints.py +++ b/packages/overture-schema-codegen/src/overture/schema/codegen/extraction/field_constraints.py @@ -13,7 +13,7 @@ from annotated_types import Ge, Gt, Interval, Le, Lt, MultipleOf -from overture.schema.system.primitive import GeometryTypeConstraint +from overture.schema.system.geometric import GeometryTypeConstraint from overture.schema.system.ref import Reference from .docstring import first_docstring_line diff --git a/packages/overture-schema-codegen/src/overture/schema/codegen/markdown/path_assignment.py b/packages/overture-schema-codegen/src/overture/schema/codegen/markdown/path_assignment.py index 7113ab8ca..e4d2f61a1 100644 --- a/packages/overture-schema-codegen/src/overture/schema/codegen/markdown/path_assignment.py +++ b/packages/overture-schema-codegen/src/overture/schema/codegen/markdown/path_assignment.py @@ -18,15 +18,15 @@ from ..layout.module_layout import compute_output_dir, output_dir_for_entry_point __all__ = [ - "GEOMETRY_PAGE", - "PRIMITIVES_PAGE", + "GEOMETRIC_PAGE", + "NUMERIC_PAGE", "build_placement_registry", "resolve_output_path", ] # Aggregate page paths. -PRIMITIVES_PAGE = PurePosixPath("system/primitive/primitives.md") -GEOMETRY_PAGE = PurePosixPath("system/primitive/geometry.md") +NUMERIC_PAGE = PurePosixPath("system/numeric.md") +GEOMETRIC_PAGE = PurePosixPath("system/geometric.md") def build_placement_registry( @@ -85,9 +85,9 @@ def _aggregate_page_entries( ) -> dict[TypeIdentity, PurePosixPath]: """Pre-populate registry entries for types documented on aggregate pages.""" entries: dict[TypeIdentity, PurePosixPath] = dict.fromkeys( - numeric_names, PRIMITIVES_PAGE + numeric_names, NUMERIC_PAGE ) - entries.update(dict.fromkeys(geometry_names, GEOMETRY_PAGE)) + entries.update(dict.fromkeys(geometry_names, GEOMETRIC_PAGE)) return entries diff --git a/packages/overture-schema-codegen/src/overture/schema/codegen/markdown/pipeline.py b/packages/overture-schema-codegen/src/overture/schema/codegen/markdown/pipeline.py index 262782609..d159060de 100644 --- a/packages/overture-schema-codegen/src/overture/schema/codegen/markdown/pipeline.py +++ b/packages/overture-schema-codegen/src/overture/schema/codegen/markdown/pipeline.py @@ -10,8 +10,9 @@ from dataclasses import dataclass from pathlib import PurePosixPath -import overture.schema.system.primitive as _system_primitive -from overture.schema.system.primitive import GeometryType +import overture.schema.system.geometric as _system_geometric +import overture.schema.system.numeric as _system_numeric +from overture.schema.system.geometric import GeometryType from ..extraction.examples import ExampleRecord, load_examples from ..extraction.numeric_extraction import extract_numerics @@ -29,8 +30,8 @@ from ..layout.type_collection import collect_all_supplementary_types from .link_computation import LinkContext from .path_assignment import ( - GEOMETRY_PAGE, - PRIMITIVES_PAGE, + GEOMETRIC_PAGE, + NUMERIC_PAGE, build_placement_registry, resolve_output_path, ) @@ -39,7 +40,7 @@ render_geometry_from_values, render_model, render_newtype, - render_primitives_from_specs, + render_numeric_from_specs, render_pydantic_type, ) from .reverse_references import UsedByEntry, compute_reverse_references @@ -114,22 +115,24 @@ def _render_supplement( def partition_numeric_and_geometry_types( - types_module: object, + numeric_module: object, + geometric_module: object, ) -> tuple[list[TypeIdentity], list[TypeIdentity]]: - """Discover numeric and geometry types from a module's exports. + """Discover numeric and geometry types from their source modules' exports. - NewType exports are numeric types. - Non-constraint class/enum exports are geometry types. + NewType exports of *numeric_module* are numeric types. + Non-constraint class/enum exports of *geometric_module* are geometry types. """ - module_all: list[str] = getattr(types_module, "__all__", []) numerics: list[TypeIdentity] = [] - geometries: list[TypeIdentity] = [] - - for name in module_all: - obj = getattr(types_module, name) + for name in getattr(numeric_module, "__all__", []): + obj = getattr(numeric_module, name) if is_newtype(obj): numerics.append(TypeIdentity(obj, name)) - elif isinstance(obj, type) and not name.endswith("Constraint"): + + geometries: list[TypeIdentity] = [] + for name in getattr(geometric_module, "__all__", []): + obj = getattr(geometric_module, name) + if isinstance(obj, type) and not name.endswith("Constraint"): geometries.append(TypeIdentity(obj, name)) return numerics, geometries @@ -146,7 +149,7 @@ def generate_markdown_pages( (like Docusaurus category files). """ numeric_names, geometry_names = partition_numeric_and_geometry_types( - _system_primitive + _system_numeric, _system_geometric ) all_specs = collect_all_supplementary_types(model_specs) registry = build_placement_registry( @@ -170,15 +173,15 @@ def generate_markdown_pages( pages.append( RenderedPage( - content=render_primitives_from_specs(extract_numerics(numeric_names)), - path=PRIMITIVES_PAGE, + content=render_numeric_from_specs(extract_numerics(numeric_names)), + path=NUMERIC_PAGE, ) ) pages.append( RenderedPage( content=render_geometry_from_values([m.value for m in GeometryType]), - path=GEOMETRY_PAGE, + path=GEOMETRIC_PAGE, ) ) diff --git a/packages/overture-schema-codegen/src/overture/schema/codegen/markdown/renderer.py b/packages/overture-schema-codegen/src/overture/schema/codegen/markdown/renderer.py index 10c96a803..8f0911ab8 100644 --- a/packages/overture-schema-codegen/src/overture/schema/codegen/markdown/renderer.py +++ b/packages/overture-schema-codegen/src/overture/schema/codegen/markdown/renderer.py @@ -48,7 +48,7 @@ "render_model", "render_geometry_from_values", "render_newtype", - "render_primitives_from_specs", + "render_numeric_from_specs", "render_pydantic_type", ] @@ -532,7 +532,7 @@ def render_pydantic_type( ) -# Matches the ge/le bounds of the int64 NewType in overture.schema.system.primitive. +# Matches the ge/le bounds of the int64 NewType in overture.schema.system.numeric. _INT64_MIN = -(2**63) _INT64_MAX = 2**63 - 1 @@ -597,9 +597,9 @@ def _bit_width_key(name: str) -> tuple[str, int]: return (prefix, int(digits) if digits else 0) -def render_primitives_from_specs(specs: list[NumericSpec]) -> str: - """Render the primitives.md page from pre-extracted NumericSpecs.""" - template = _get_jinja_env().get_template("primitives.md.jinja2") +def render_numeric_from_specs(specs: list[NumericSpec]) -> str: + """Render the numeric.md page from pre-extracted NumericSpecs.""" + template = _get_jinja_env().get_template("numeric.md.jinja2") signed_ints: list[dict[str, str | None]] = [] unsigned_ints: list[dict[str, str | None]] = [] @@ -635,7 +635,7 @@ def render_primitives_from_specs(specs: list[NumericSpec]) -> str: def render_geometry_from_values(geometry_type_values: list[str]) -> str: - """Render the geometry.md page from pre-extracted geometry type values.""" - template = _get_jinja_env().get_template("geometry.md.jinja2") + """Render the geometric.md page from pre-extracted geometry type values.""" + template = _get_jinja_env().get_template("geometric.md.jinja2") geometry_types = ", ".join(f"`{v}`" for v in geometry_type_values) return template.render(geometry_types=geometry_types) diff --git a/packages/overture-schema-codegen/src/overture/schema/codegen/markdown/templates/geometry.md.jinja2 b/packages/overture-schema-codegen/src/overture/schema/codegen/markdown/templates/geometric.md.jinja2 similarity index 100% rename from packages/overture-schema-codegen/src/overture/schema/codegen/markdown/templates/geometry.md.jinja2 rename to packages/overture-schema-codegen/src/overture/schema/codegen/markdown/templates/geometric.md.jinja2 diff --git a/packages/overture-schema-codegen/src/overture/schema/codegen/markdown/templates/primitives.md.jinja2 b/packages/overture-schema-codegen/src/overture/schema/codegen/markdown/templates/numeric.md.jinja2 similarity index 97% rename from packages/overture-schema-codegen/src/overture/schema/codegen/markdown/templates/primitives.md.jinja2 rename to packages/overture-schema-codegen/src/overture/schema/codegen/markdown/templates/numeric.md.jinja2 index fd87a1ec0..947256bf4 100644 --- a/packages/overture-schema-codegen/src/overture/schema/codegen/markdown/templates/primitives.md.jinja2 +++ b/packages/overture-schema-codegen/src/overture/schema/codegen/markdown/templates/numeric.md.jinja2 @@ -1,4 +1,4 @@ -# Primitive Types +# Numeric Types Numeric types used for schema field definitions. diff --git a/packages/overture-schema-codegen/src/overture/schema/codegen/pyspark/constraint_dispatch.py b/packages/overture-schema-codegen/src/overture/schema/codegen/pyspark/constraint_dispatch.py index 72baa5b88..e346f1082 100644 --- a/packages/overture-schema-codegen/src/overture/schema/codegen/pyspark/constraint_dispatch.py +++ b/packages/overture-schema-codegen/src/overture/schema/codegen/pyspark/constraint_dispatch.py @@ -24,6 +24,7 @@ StrippedConstraint, ) from overture.schema.system.field_path import FieldPath +from overture.schema.system.geometric import GeometryTypeConstraint from overture.schema.system.model_constraint import ( Condition, FieldEqCondition, @@ -36,7 +37,6 @@ RequireAnyTrueConstraint, RequireIfConstraint, ) -from overture.schema.system.primitive import GeometryTypeConstraint from overture.schema.system.ref import Reference from ..extraction.docstring import first_docstring_line diff --git a/packages/overture-schema-codegen/src/overture/schema/codegen/pyspark/pipeline.py b/packages/overture-schema-codegen/src/overture/schema/codegen/pyspark/pipeline.py index 9bb2a9daa..d375a097f 100644 --- a/packages/overture-schema-codegen/src/overture/schema/codegen/pyspark/pipeline.py +++ b/packages/overture-schema-codegen/src/overture/schema/codegen/pyspark/pipeline.py @@ -13,7 +13,7 @@ from overture.schema.system.case import to_snake_case from overture.schema.system.discovery import entry_point_to_path -from overture.schema.system.primitive import GeometryType +from overture.schema.system.geometric import GeometryType from ..extraction.specs import ModelSpec, UnionSpec from .check_builder import build_checks diff --git a/packages/overture-schema-codegen/src/overture/schema/codegen/pyspark/renderer.py b/packages/overture-schema-codegen/src/overture/schema/codegen/pyspark/renderer.py index 6fb48f3e1..44c5d85d2 100644 --- a/packages/overture-schema-codegen/src/overture/schema/codegen/pyspark/renderer.py +++ b/packages/overture-schema-codegen/src/overture/schema/codegen/pyspark/renderer.py @@ -13,7 +13,7 @@ MapProjection, ScalarPath, ) -from overture.schema.system.primitive import GeometryType +from overture.schema.system.geometric import GeometryType from ._render_common import ( FieldCheckRow, diff --git a/packages/overture-schema-codegen/src/overture/schema/codegen/pyspark/templates/model_module.py.jinja2 b/packages/overture-schema-codegen/src/overture/schema/codegen/pyspark/templates/model_module.py.jinja2 index 8c91646c4..101b1abfd 100644 --- a/packages/overture-schema-codegen/src/overture/schema/codegen/pyspark/templates/model_module.py.jinja2 +++ b/packages/overture-schema-codegen/src/overture/schema/codegen/pyspark/templates/model_module.py.jinja2 @@ -14,7 +14,7 @@ from pyspark.sql.types import ( ) {% endif %} {% if geometry_type %} -from overture.schema.system.primitive import GeometryType +from overture.schema.system.geometric import GeometryType {% endif %} from overture.schema.pyspark.check import Check, CheckShape, ModelValidation diff --git a/packages/overture-schema-codegen/src/overture/schema/codegen/pyspark/test_data/base_row.py b/packages/overture-schema-codegen/src/overture/schema/codegen/pyspark/test_data/base_row.py index a9c56a359..2fb3db912 100644 --- a/packages/overture-schema-codegen/src/overture/schema/codegen/pyspark/test_data/base_row.py +++ b/packages/overture-schema-codegen/src/overture/schema/codegen/pyspark/test_data/base_row.py @@ -15,6 +15,11 @@ from typing import Any from overture.schema.common.scoping.lr import LinearReferenceRangeConstraint +from overture.schema.system.geometric.geom import ( + Geometry, + GeometryType, + GeometryTypeConstraint, +) from overture.schema.system.model_constraint import ( ForbidIfConstraint, MinFieldsSetConstraint, @@ -23,11 +28,6 @@ RequireAnyTrueConstraint, RequireIfConstraint, ) -from overture.schema.system.primitive.geom import ( - Geometry, - GeometryType, - GeometryTypeConstraint, -) from ...extraction.field import ( AnyScalar, diff --git a/packages/overture-schema-codegen/src/overture/schema/codegen/pyspark/test_data/invalid_value.py b/packages/overture-schema-codegen/src/overture/schema/codegen/pyspark/test_data/invalid_value.py index e54081a6c..078a1763f 100644 --- a/packages/overture-schema-codegen/src/overture/schema/codegen/pyspark/test_data/invalid_value.py +++ b/packages/overture-schema-codegen/src/overture/schema/codegen/pyspark/test_data/invalid_value.py @@ -7,7 +7,7 @@ from __future__ import annotations -from overture.schema.system.primitive.geom import GeometryType +from overture.schema.system.geometric.geom import GeometryType from ..constraint_dispatch import ExpressionDescriptor from .constraint_values import ( diff --git a/packages/overture-schema-codegen/tests/codegen_test_support.py b/packages/overture-schema-codegen/tests/codegen_test_support.py index c30bffebb..0ded56a3c 100644 --- a/packages/overture-schema-codegen/tests/codegen_test_support.py +++ b/packages/overture-schema-codegen/tests/codegen_test_support.py @@ -41,19 +41,18 @@ from overture.schema.system.discovery.tag import get_values_for_key from overture.schema.system.doc import DocumentedEnum from overture.schema.system.field_constraint import UniqueItemsConstraint +from overture.schema.system.geometric import ( + Geometry, + GeometryType, + GeometryTypeConstraint, +) from overture.schema.system.model_constraint import ( FieldEqCondition, radio_group, require_any_of, require_any_true, ) -from overture.schema.system.primitive import ( - Geometry, - GeometryType, - GeometryTypeConstraint, - float64, - int32, -) +from overture.schema.system.numeric import float64, int32 from overture.schema.system.ref import Id, Identified, Reference, Relationship from overture.schema.system.string import HexColor, LanguageTag, StrippedString from pydantic import BaseModel, EmailStr, Field, HttpUrl diff --git a/packages/overture-schema-codegen/tests/conftest.py b/packages/overture-schema-codegen/tests/conftest.py index fbd1f0f1e..db4ccde63 100644 --- a/packages/overture-schema-codegen/tests/conftest.py +++ b/packages/overture-schema-codegen/tests/conftest.py @@ -1,6 +1,7 @@ """Shared pytest fixtures for overture-schema-codegen tests.""" -import overture.schema.system.primitive as _system_primitive +import overture.schema.system.geometric as _system_geometric +import overture.schema.system.numeric as _system_numeric import pytest from click.testing import CliRunner from codegen_test_support import find_model_class @@ -12,10 +13,10 @@ ) from overture.schema.codegen.markdown.renderer import ( render_geometry_from_values, - render_primitives_from_specs, + render_numeric_from_specs, ) from overture.schema.system.discovery import discover_models -from overture.schema.system.primitive import GeometryType +from overture.schema.system.geometric import GeometryType from pydantic import BaseModel @@ -70,13 +71,15 @@ def division_class(all_discovered_models: dict) -> type[BaseModel]: @pytest.fixture(scope="module") -def primitives_markdown() -> str: - """Render the primitives.md page from the system primitive module.""" - numeric_names, _ = partition_numeric_and_geometry_types(_system_primitive) - return render_primitives_from_specs(extract_numerics(numeric_names)) +def numeric_markdown() -> str: + """Render the numeric.md page from the system numeric module.""" + numeric_names, _ = partition_numeric_and_geometry_types( + _system_numeric, _system_geometric + ) + return render_numeric_from_specs(extract_numerics(numeric_names)) @pytest.fixture(scope="module") def geometry_markdown() -> str: - """Render the geometry.md page from system GeometryType values.""" + """Render the geometric.md page from system GeometryType values.""" return render_geometry_from_values([m.value for m in GeometryType]) diff --git a/packages/overture-schema-codegen/tests/test_constraint_description.py b/packages/overture-schema-codegen/tests/test_constraint_description.py index ff693960c..a9af9fc4e 100644 --- a/packages/overture-schema-codegen/tests/test_constraint_description.py +++ b/packages/overture-schema-codegen/tests/test_constraint_description.py @@ -25,6 +25,7 @@ CountryCodeAlpha2Constraint, PatternConstraint, ) +from overture.schema.system.geometric import GeometryType, GeometryTypeConstraint from overture.schema.system.model_constraint import ( FieldEqCondition, ForbidIfConstraint, @@ -37,7 +38,6 @@ RequireAnyTrueConstraint, RequireIfConstraint, ) -from overture.schema.system.primitive import GeometryType, GeometryTypeConstraint from overture.schema.system.ref import Reference, Relationship from overture.schema.system.ref.id import Identified diff --git a/packages/overture-schema-codegen/tests/test_example_loader.py b/packages/overture-schema-codegen/tests/test_example_loader.py index 541b81282..6db506b0b 100644 --- a/packages/overture-schema-codegen/tests/test_example_loader.py +++ b/packages/overture-schema-codegen/tests/test_example_loader.py @@ -21,7 +21,7 @@ resolve_pyproject_path, validate_example, ) -from overture.schema.system.primitive import BBox, Geometry +from overture.schema.system.geometric import BBox, Geometry from overture.schema.transportation import Segment from overture.schema.transportation.segment.models import ( RoadSegment, diff --git a/packages/overture-schema-codegen/tests/test_markdown_renderer.py b/packages/overture-schema-codegen/tests/test_markdown_renderer.py index 271347ca2..76f527fb8 100644 --- a/packages/overture-schema-codegen/tests/test_markdown_renderer.py +++ b/packages/overture-schema-codegen/tests/test_markdown_renderer.py @@ -45,7 +45,7 @@ render_enum, render_model, render_newtype, - render_primitives_from_specs, + render_numeric_from_specs, render_pydantic_type, ) from overture.schema.codegen.markdown.reverse_references import UsedByEntry, UsedByKind @@ -55,7 +55,7 @@ UniqueItemsConstraint, ) from overture.schema.system.model_constraint import no_extra_fields -from overture.schema.system.primitive import int32 +from overture.schema.system.numeric import int32 from overture.schema.system.ref import Id from overture.schema.system.string import HexColor, NoWhitespaceString from pydantic import BaseModel, Field @@ -1162,50 +1162,50 @@ def test_empty_examples_list_omits_section(self) -> None: assert "## Examples" not in result -class TestRenderPrimitivesPage: - """Tests for the aggregate primitives page.""" +class TestRenderNumericPage: + """Tests for the aggregate numeric types page.""" - def test_contains_title(self, primitives_markdown: str) -> None: - assert "# Primitive Types" in primitives_markdown + def test_contains_title(self, numeric_markdown: str) -> None: + assert "# Numeric Types" in numeric_markdown - def test_contains_signed_integers(self, primitives_markdown: str) -> None: - assert "| `int8` |" in primitives_markdown - assert "| `int16` |" in primitives_markdown - assert "| `int32` |" in primitives_markdown - assert "| `int64` |" in primitives_markdown + def test_contains_signed_integers(self, numeric_markdown: str) -> None: + assert "| `int8` |" in numeric_markdown + assert "| `int16` |" in numeric_markdown + assert "| `int32` |" in numeric_markdown + assert "| `int64` |" in numeric_markdown - def test_contains_unsigned_integers(self, primitives_markdown: str) -> None: - assert "| `uint8` |" in primitives_markdown - assert "| `uint16` |" in primitives_markdown - assert "| `uint32` |" in primitives_markdown + def test_contains_unsigned_integers(self, numeric_markdown: str) -> None: + assert "| `uint8` |" in numeric_markdown + assert "| `uint16` |" in numeric_markdown + assert "| `uint32` |" in numeric_markdown - def test_contains_floats(self, primitives_markdown: str) -> None: - assert "| `float32` |" in primitives_markdown - assert "| `float64` |" in primitives_markdown + def test_contains_floats(self, numeric_markdown: str) -> None: + assert "| `float32` |" in numeric_markdown + assert "| `float64` |" in numeric_markdown - def test_ranges_match_schema_constraints(self, primitives_markdown: str) -> None: + def test_ranges_match_schema_constraints(self, numeric_markdown: str) -> None: """Range strings derive from ge/le constraints in the schema.""" - assert "-128 to 127" in primitives_markdown - assert "-32,768 to 32,767" in primitives_markdown - assert "-2,147,483,648 to 2,147,483,647" in primitives_markdown - assert "-2^63 to 2^63-1" in primitives_markdown - assert "0 to 255" in primitives_markdown - assert "0 to 65,535" in primitives_markdown - assert "0 to 4,294,967,295" in primitives_markdown - - def test_descriptions_from_docstrings(self, primitives_markdown: str) -> None: + assert "-128 to 127" in numeric_markdown + assert "-32,768 to 32,767" in numeric_markdown + assert "-2,147,483,648 to 2,147,483,647" in numeric_markdown + assert "-2^63 to 2^63-1" in numeric_markdown + assert "0 to 255" in numeric_markdown + assert "0 to 65,535" in numeric_markdown + assert "0 to 4,294,967,295" in numeric_markdown + + def test_descriptions_from_docstrings(self, numeric_markdown: str) -> None: """Descriptions derive from first line of NewType docstrings.""" - assert "Portable 8-bit signed integer." in primitives_markdown - assert "Portable 16-bit unsigned integer." in primitives_markdown - assert "Portable IEEE 32-bit floating point number." in primitives_markdown + assert "Portable 8-bit signed integer." in numeric_markdown + assert "Portable 16-bit unsigned integer." in numeric_markdown + assert "Portable IEEE 32-bit floating point number." in numeric_markdown - def test_float_precision(self, primitives_markdown: str) -> None: + def test_float_precision(self, numeric_markdown: str) -> None: """Float entries show IEEE 754 precision.""" - assert "~7 decimal digits" in primitives_markdown - assert "~15 decimal digits" in primitives_markdown + assert "~7 decimal digits" in numeric_markdown + assert "~15 decimal digits" in numeric_markdown def test_pipe_in_description_escaped(self) -> None: - """Pipe characters in primitive descriptions are escaped.""" + """Pipe characters in numeric type descriptions are escaped.""" specs = [ NumericSpec( name="int8", @@ -1213,7 +1213,7 @@ def test_pipe_in_description_escaped(self) -> None: bounds=Interval(ge=-128, le=127), ), ] - result = render_primitives_from_specs(specs) + result = render_numeric_from_specs(specs) assert "Range: -128 \\| 127" in result diff --git a/packages/overture-schema-codegen/tests/test_markdown_type_format.py b/packages/overture-schema-codegen/tests/test_markdown_type_format.py index b10a69451..9e4597133 100644 --- a/packages/overture-schema-codegen/tests/test_markdown_type_format.py +++ b/packages/overture-schema-codegen/tests/test_markdown_type_format.py @@ -25,7 +25,8 @@ format_type, format_underlying_type, ) -from overture.schema.system.primitive import BBox, Geometry, int32 +from overture.schema.system.geometric import BBox, Geometry +from overture.schema.system.numeric import int32 from pydantic import BaseModel, HttpUrl @@ -101,27 +102,18 @@ def test_geometry_links_to_aggregate_page(self) -> None: ctx = LinkContext( page_path=PurePosixPath("buildings/building/building.md"), registry={ - TypeIdentity(Geometry, "Geometry"): PurePosixPath( - "system/primitive/geometry.md" - ) + TypeIdentity(Geometry, "Geometry"): PurePosixPath("system/geometric.md") }, ) - assert ( - format_type(field, ctx) - == "[`geometry`](../../system/primitive/geometry.md)" - ) + assert format_type(field, ctx) == "[`geometry`](../../system/geometric.md)" def test_bbox_links_to_aggregate_page(self) -> None: field = _make_field(BBox) ctx = LinkContext( page_path=PurePosixPath("base/feature/feature.md"), - registry={ - TypeIdentity(BBox, "BBox"): PurePosixPath( - "system/primitive/geometry.md" - ) - }, + registry={TypeIdentity(BBox, "BBox"): PurePosixPath("system/geometric.md")}, ) - assert format_type(field, ctx) == "[`bbox`](../../system/primitive/geometry.md)" + assert format_type(field, ctx) == "[`bbox`](../../system/geometric.md)" def test_geometry_without_context_renders_plain_code(self) -> None: assert format_type(_make_field(Geometry)) == "`geometry`" @@ -298,18 +290,14 @@ def test_list_of_pydantic_type_linked(self) -> None: assert "pydantic/networks/http_url.md" in result def test_registered_primitive_links_to_aggregate_page(self) -> None: - """int32 links to the primitives aggregate page when in registry.""" + """int32 links to the numeric types aggregate page when in registry.""" ctx = LinkContext( page_path=PurePosixPath("places/place/place.md"), - registry={ - TypeIdentity(int32, "int32"): PurePosixPath( - "system/primitive/primitives.md" - ) - }, + registry={TypeIdentity(int32, "int32"): PurePosixPath("system/numeric.md")}, ) result = format_type(_make_field(int32), ctx) assert "[`int32`]" in result - assert "system/primitive/primitives.md" in result + assert "system/numeric.md" in result class TestListOfSemanticNewtype: @@ -491,10 +479,10 @@ def test_map_value_geometry_links_in_field_cell(self) -> None: The map-side link decision shares `_scalar_identity`'s coverage, so a Geometry value links rather than rendering bare. """ - ctx = _link_ctx((Geometry, "geometry", "system/primitive/geometry.md")) + ctx = _link_ctx((Geometry, "geometry", "system/geometric.md")) result = format_type(_make_field(dict[str, Geometry]), ctx) assert "[`geometry`]" in result - assert "system/primitive/geometry.md" in result + assert "system/geometric.md" in result assert "``" not in result def test_map_value_pydantic_type_links_in_field_cell(self) -> None: @@ -520,13 +508,11 @@ def test_geometry_underlying_type_links(self) -> None: ctx = LinkContext( page_path=PurePosixPath("system/types/geom_alias.md"), registry={ - TypeIdentity(Geometry, "geometry"): PurePosixPath( - "system/primitive/geometry.md" - ) + TypeIdentity(Geometry, "geometry"): PurePosixPath("system/geometric.md") }, ) result = format_underlying_type(shape, ctx) - assert "[`geometry`](../primitive/geometry.md)" in result + assert "[`geometry`](../geometric.md)" in result def test_numeric_underlying_type_stays_bare(self) -> None: """A NewType over a numeric primitive renders bare, not over-linked. diff --git a/packages/overture-schema-codegen/tests/test_model_extractor.py b/packages/overture-schema-codegen/tests/test_model_extractor.py index 981d7bf78..6356d30d3 100644 --- a/packages/overture-schema-codegen/tests/test_model_extractor.py +++ b/packages/overture-schema-codegen/tests/test_model_extractor.py @@ -20,17 +20,17 @@ ) from overture.schema.codegen.extraction.model_extraction import extract_model from overture.schema.system.field_constraint import UniqueItemsConstraint +from overture.schema.system.geometric import ( + Geometry, + GeometryType, + GeometryTypeConstraint, +) from overture.schema.system.model_constraint import ( FieldEqCondition, FieldGroupConstraint, require_any_of, require_if, ) -from overture.schema.system.primitive import ( - Geometry, - GeometryType, - GeometryTypeConstraint, -) from overture.schema.system.string import HexColor from pydantic import BaseModel, Field diff --git a/packages/overture-schema-codegen/tests/test_numeric_extraction.py b/packages/overture-schema-codegen/tests/test_numeric_extraction.py index 6f3a5767f..b9e4f5b4e 100644 --- a/packages/overture-schema-codegen/tests/test_numeric_extraction.py +++ b/packages/overture-schema-codegen/tests/test_numeric_extraction.py @@ -2,7 +2,8 @@ from typing import Annotated, NewType -import overture.schema.system.primitive as _system_primitive +import overture.schema.system.geometric as _system_geometric +import overture.schema.system.numeric as _system_numeric from overture.schema.codegen.extraction.newtype_extraction import extract_newtype from overture.schema.codegen.extraction.numeric_extraction import ( extract_numeric_bounds, @@ -13,7 +14,7 @@ from overture.schema.codegen.markdown.pipeline import ( partition_numeric_and_geometry_types, ) -from overture.schema.system.primitive import float32, int32, int64, uint8 +from overture.schema.system.numeric import float32, int32, int64, uint8 from pydantic import Field @@ -21,28 +22,36 @@ class TestPartitionNumericAndGeometryTypes: """Tests for partition_numeric_and_geometry_types function.""" def test_returns_type_identities(self) -> None: - nums, geoms = partition_numeric_and_geometry_types(_system_primitive) + nums, geoms = partition_numeric_and_geometry_types( + _system_numeric, _system_geometric + ) assert all(isinstance(p, TypeIdentity) for p in nums) assert all(isinstance(g, TypeIdentity) for g in geoms) def test_identity_obj_is_actual_callable(self) -> None: - nums, _ = partition_numeric_and_geometry_types(_system_primitive) + nums, _ = partition_numeric_and_geometry_types( + _system_numeric, _system_geometric + ) int32_id = next(p for p in nums if p.name == "int32") - assert int32_id.obj is _system_primitive.int32 + assert int32_id.obj is _system_numeric.int32 class TestExtractNumerics: """Tests for extract_numerics function.""" def test_accepts_type_identities(self) -> None: - nums, _ = partition_numeric_and_geometry_types(_system_primitive) + nums, _ = partition_numeric_and_geometry_types( + _system_numeric, _system_geometric + ) specs = extract_numerics(nums) assert len(specs) > 0 names = [s.name for s in specs] assert "int32" in names def test_extracts_bounds(self) -> None: - nums, _ = partition_numeric_and_geometry_types(_system_primitive) + nums, _ = partition_numeric_and_geometry_types( + _system_numeric, _system_geometric + ) specs = extract_numerics(nums) int32_spec = next(s for s in specs if s.name == "int32") assert int32_spec.bounds.ge == -(2**31) diff --git a/packages/overture-schema-codegen/tests/test_pyspark_check_builder.py b/packages/overture-schema-codegen/tests/test_pyspark_check_builder.py index 77b2acd62..88d8dc5da 100644 --- a/packages/overture-schema-codegen/tests/test_pyspark_check_builder.py +++ b/packages/overture-schema-codegen/tests/test_pyspark_check_builder.py @@ -64,7 +64,7 @@ forbid_if, require_any_of, ) -from overture.schema.system.primitive import float64 +from overture.schema.system.numeric import float64 from overture.schema.system.string import CountryCodeAlpha2 from pydantic import BaseModel, Field from pydantic.fields import FieldInfo diff --git a/packages/overture-schema-codegen/tests/test_pyspark_constraint_dispatch.py b/packages/overture-schema-codegen/tests/test_pyspark_constraint_dispatch.py index 1e3d2275e..c87524925 100644 --- a/packages/overture-schema-codegen/tests/test_pyspark_constraint_dispatch.py +++ b/packages/overture-schema-codegen/tests/test_pyspark_constraint_dispatch.py @@ -37,6 +37,7 @@ SnakeCaseConstraint, StrippedConstraint, ) +from overture.schema.system.geometric import GeometryType, GeometryTypeConstraint from overture.schema.system.model_constraint import ( FieldEqCondition, ForbidIfConstraint, @@ -48,7 +49,6 @@ RequireAnyTrueConstraint, RequireIfConstraint, ) -from overture.schema.system.primitive import GeometryType, GeometryTypeConstraint from overture.schema.system.ref import Identified, Reference, Relationship from pydantic import Field, Strict diff --git a/packages/overture-schema-codegen/tests/test_pyspark_invalid_value.py b/packages/overture-schema-codegen/tests/test_pyspark_invalid_value.py index 77a4a3ef2..0db68c8e4 100644 --- a/packages/overture-schema-codegen/tests/test_pyspark_invalid_value.py +++ b/packages/overture-schema-codegen/tests/test_pyspark_invalid_value.py @@ -10,7 +10,7 @@ RegionCodeConstraint, StrippedConstraint, ) -from overture.schema.system.primitive.geom import GeometryType +from overture.schema.system.geometric.geom import GeometryType class TestInvalidValueRequired: diff --git a/packages/overture-schema-codegen/tests/test_pyspark_pipeline.py b/packages/overture-schema-codegen/tests/test_pyspark_pipeline.py index d84fe7199..74ba280b2 100644 --- a/packages/overture-schema-codegen/tests/test_pyspark_pipeline.py +++ b/packages/overture-schema-codegen/tests/test_pyspark_pipeline.py @@ -22,7 +22,7 @@ ) from overture.schema.codegen.spec_discovery import extract_model_spec from overture.schema.system.field_path import ScalarPath -from overture.schema.system.primitive import GeometryType +from overture.schema.system.geometric import GeometryType from pydantic import BaseModel diff --git a/packages/overture-schema-codegen/tests/test_pyspark_renderer.py b/packages/overture-schema-codegen/tests/test_pyspark_renderer.py index 54d865d21..a7f2c9497 100644 --- a/packages/overture-schema-codegen/tests/test_pyspark_renderer.py +++ b/packages/overture-schema-codegen/tests/test_pyspark_renderer.py @@ -51,6 +51,11 @@ ScalarPath, parse, ) +from overture.schema.system.geometric import ( + Geometry, + GeometryType, + GeometryTypeConstraint, +) from overture.schema.system.model_constraint import ( FieldEqCondition, Not, @@ -58,12 +63,7 @@ require_any_of, require_if, ) -from overture.schema.system.primitive import ( - Geometry, - GeometryType, - GeometryTypeConstraint, - int32, -) +from overture.schema.system.numeric import int32 from overture.schema.system.string import CountryCodeAlpha2 from pydantic import BaseModel, HttpUrl from pydantic.fields import FieldInfo @@ -574,7 +574,7 @@ def test_geometry_type_imported_when_only_constant_needs_it(self) -> None: schema_fields, geometry_types=(GeometryType.POINT,), ) - assert "from overture.schema.system.primitive import GeometryType" in source + assert "from overture.schema.system.geometric import GeometryType" in source class TestImports: @@ -776,7 +776,7 @@ def test_geometry_type_uses_qualified_name(self) -> None: def test_geometry_type_import_present(self) -> None: source = _render(GeomModel, "geom") - assert "from overture.schema.system.primitive import GeometryType" in source + assert "from overture.schema.system.geometric import GeometryType" in source def test_no_geometry_type_import_without_geometry_field( self, literal_subtype_source: str diff --git a/packages/overture-schema-codegen/tests/test_pyspark_test_renderer.py b/packages/overture-schema-codegen/tests/test_pyspark_test_renderer.py index 485684d96..54a27291e 100644 --- a/packages/overture-schema-codegen/tests/test_pyspark_test_renderer.py +++ b/packages/overture-schema-codegen/tests/test_pyspark_test_renderer.py @@ -41,8 +41,8 @@ StrippedConstraint, ) from overture.schema.system.field_path import ArrayPath, ScalarPath, parse +from overture.schema.system.geometric.geom import GeometryType from overture.schema.system.model_constraint import FieldEqCondition, Not -from overture.schema.system.primitive.geom import GeometryType _path = parse diff --git a/packages/overture-schema-codegen/tests/test_specs.py b/packages/overture-schema-codegen/tests/test_specs.py index 51da3a20a..99cbe2780 100644 --- a/packages/overture-schema-codegen/tests/test_specs.py +++ b/packages/overture-schema-codegen/tests/test_specs.py @@ -20,7 +20,7 @@ TypeIdentity, is_union_alias, ) -from overture.schema.system.primitive import int32 +from overture.schema.system.numeric import int32 from pydantic import BaseModel, Field diff --git a/packages/overture-schema-codegen/tests/test_type_analyzer.py b/packages/overture-schema-codegen/tests/test_type_analyzer.py index 144214b75..b3a81cb8c 100644 --- a/packages/overture-schema-codegen/tests/test_type_analyzer.py +++ b/packages/overture-schema-codegen/tests/test_type_analyzer.py @@ -38,7 +38,7 @@ unwrap_list, ) from overture.schema.common.scoping.vehicle import VehicleSelector -from overture.schema.system.primitive import int32 +from overture.schema.system.numeric import int32 from overture.schema.system.ref import Id from overture.schema.system.string import ( HexColor, diff --git a/packages/overture-schema-codegen/tests/test_type_collection.py b/packages/overture-schema-codegen/tests/test_type_collection.py index 66cbbcbd5..71907e719 100644 --- a/packages/overture-schema-codegen/tests/test_type_collection.py +++ b/packages/overture-schema-codegen/tests/test_type_collection.py @@ -21,7 +21,7 @@ from overture.schema.codegen.layout.type_collection import ( collect_all_supplementary_types, ) -from overture.schema.system.primitive import uint8 +from overture.schema.system.numeric import uint8 from overture.schema.system.string import HexColor from pydantic import BaseModel diff --git a/packages/overture-schema-codegen/tests/test_type_placement.py b/packages/overture-schema-codegen/tests/test_type_placement.py index 5ae07dbbd..bf3d5528a 100644 --- a/packages/overture-schema-codegen/tests/test_type_placement.py +++ b/packages/overture-schema-codegen/tests/test_type_placement.py @@ -2,7 +2,8 @@ from pathlib import PurePosixPath -import overture.schema.system.primitive as _system_primitive +import overture.schema.system.geometric as _system_geometric +import overture.schema.system.numeric as _system_numeric from codegen_test_support import ( EMAIL_STR_SPEC, HTTP_URL_SPEC, @@ -24,8 +25,8 @@ ) from overture.schema.codegen.markdown.link_computation import LinkContext, relative_link from overture.schema.codegen.markdown.path_assignment import ( - GEOMETRY_PAGE, - PRIMITIVES_PAGE, + GEOMETRIC_PAGE, + NUMERIC_PAGE, build_placement_registry, ) from overture.schema.codegen.markdown.pipeline import ( @@ -34,7 +35,7 @@ from pydantic import BaseModel _NUMERIC_NAMES, _GEOMETRY_NAMES = partition_numeric_and_geometry_types( - _system_primitive + _system_numeric, _system_geometric ) _SCHEMA_ROOT = "overture.schema" @@ -71,8 +72,8 @@ def test_within_common(self) -> None: def test_to_aggregate_page(self) -> None: source = PurePosixPath("common/names/names.md") - target = PurePosixPath("system/primitive/primitives.md") - assert relative_link(source, target) == "../../system/primitive/primitives.md" + target = PurePosixPath("system/numeric.md") + assert relative_link(source, target) == "../../system/numeric.md" class TestBuildPlacementRegistry: @@ -105,18 +106,18 @@ def test_no_duplicate_paths(self) -> None: registry, _ = _build_registry(specs) aggregate_pages = { - PurePosixPath("system/primitive/primitives.md"), - PurePosixPath("system/primitive/geometry.md"), + PurePosixPath("system/numeric.md"), + PurePosixPath("system/geometric.md"), } individual = [p for p in registry.values() if p not in aggregate_pages] assert len(individual) == len(set(individual)), ( "Duplicate output paths detected" ) - def test_aggregate_pages_at_system_primitive(self) -> None: - """Primitive and geometry aggregate pages under system/primitive/.""" - assert PRIMITIVES_PAGE == PurePosixPath("system/primitive/primitives.md") - assert GEOMETRY_PAGE == PurePosixPath("system/primitive/geometry.md") + def test_aggregate_pages_under_system(self) -> None: + """Numeric and geometry aggregate pages sit directly under system/.""" + assert NUMERIC_PAGE == PurePosixPath("system/numeric.md") + assert GEOMETRIC_PAGE == PurePosixPath("system/geometric.md") def test_supplementary_types_nested_under_types(self) -> None: """Supplementary types in a feature directory go under types/.""" diff --git a/packages/overture-schema-common/README.md b/packages/overture-schema-common/README.md index ebb4a4534..177aaf834 100644 --- a/packages/overture-schema-common/README.md +++ b/packages/overture-schema-common/README.md @@ -27,7 +27,7 @@ Many Overture values only apply under specific conditions -- a speed limit that ```python from pydantic import BaseModel from overture.schema.common.scoping import Scope, scoped -from overture.schema.system.primitive import float32 +from overture.schema.system.numeric import float32 @scoped(Scope.GEOMETRIC_RANGE, Scope.TEMPORAL) class SpeedLimit(BaseModel): @@ -92,6 +92,6 @@ Rendering hints for map-making: `prominence` (1--100 significance scale), `min_z ## Also Included -- **Types** -- domain-specific aliases built on system primitives: `ConfidenceScore` (0.0--1.0), `Level` (z-order), `FeatureVersion`. +- **Types** -- domain-specific aliases built on system numeric types: `ConfidenceScore` (0.0--1.0), `Level` (z-order), `FeatureVersion`. - **Units** -- measurement enumerations: `SpeedUnit`, `LengthUnit`, `WeightUnit`. - **Tag providers** -- `theme` provider for the discovery system in `overture-schema-system`. Tags `OvertureFeature`-derived models with `overture:theme={theme}`. diff --git a/packages/overture-schema-common/src/overture/schema/common/cartography.py b/packages/overture-schema-common/src/overture/schema/common/cartography.py index 71cd60dbf..f0a52e870 100644 --- a/packages/overture-schema-common/src/overture/schema/common/cartography.py +++ b/packages/overture-schema-common/src/overture/schema/common/cartography.py @@ -8,7 +8,7 @@ from pydantic import BaseModel, Field from overture.schema.system.model_constraint import no_extra_fields -from overture.schema.system.primitive import int32 +from overture.schema.system.numeric import int32 Prominence = NewType( "Prominence", diff --git a/packages/overture-schema-common/src/overture/schema/common/models.py b/packages/overture-schema-common/src/overture/schema/common/models.py index 9a364f639..64fabc546 100644 --- a/packages/overture-schema-common/src/overture/schema/common/models.py +++ b/packages/overture-schema-common/src/overture/schema/common/models.py @@ -14,10 +14,10 @@ from overture.schema.system.feature import Feature from overture.schema.system.field_constraint import UniqueItemsConstraint -from overture.schema.system.model_constraint import no_extra_fields -from overture.schema.system.primitive import ( +from overture.schema.system.geometric import ( Geometry, ) +from overture.schema.system.model_constraint import no_extra_fields from overture.schema.system.ref import Id, Identified from overture.schema.system.string import ( CountryCodeAlpha2, 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 75c0decf3..80b5aa4e8 100644 --- a/packages/overture-schema-common/src/overture/schema/common/names.py +++ b/packages/overture-schema-common/src/overture/schema/common/names.py @@ -10,7 +10,7 @@ >>> from typing import Literal >>> from overture.schema.common import OvertureFeature ->>> from overture.schema.system.primitive import Geometry +>>> from overture.schema.system.geometric import Geometry >>> class MyFeature(OvertureFeature[Literal["mytheme"], Literal["mytype"]], Named): ... pass ... 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 b7e703b5d..bed8ef3f2 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 @@ -18,12 +18,12 @@ >>> from typing import Annotated, Literal >>> from pydantic import BaseModel >>> from overture.schema.common.models import OvertureFeature ->>> from overture.schema.system.primitive import ( -... float32, +>>> from overture.schema.system.geometric import ( ... Geometry, ... GeometryType, -... GeometryTypeConstraint +... GeometryTypeConstraint, ... ) +>>> from overture.schema.system.numeric import float32 ... >>> @scoped(Scope.GEOMETRIC_RANGE) ... class Depth(BaseModel): @@ -72,12 +72,12 @@ >>> from typing import Annotated, Literal >>> from pydantic import BaseModel >>> from overture.schema.common.models import OvertureFeature ->>> from overture.schema.system.primitive import ( +>>> from overture.schema.system.geometric import ( ... Geometry, ... GeometryType, ... GeometryTypeConstraint, -... uint32, ... ) +>>> from overture.schema.system.numeric import uint32 ... >>> @scoped(required=Scope.GEOMETRIC_POSITION) ... class Transformer(BaseModel): @@ -120,12 +120,12 @@ >>> from typing import Annotated, Literal >>> from pydantic import BaseModel, Field >>> from overture.schema.common.models import OvertureFeature ->>> from overture.schema.system.primitive import ( +>>> from overture.schema.system.geometric import ( ... Geometry, ... GeometryType, ... GeometryTypeConstraint, -... uint32, ... ) +>>> from overture.schema.system.numeric import uint32 >>> from overture.schema.system.string import StrippedString ... >>> @scoped(required=Scope.HEADING) @@ -213,7 +213,7 @@ >>> from typing import Annotated, Literal >>> from pydantic import BaseModel >>> from overture.schema.common.models import OvertureFeature ->>> from overture.schema.system.primitive import ( +>>> from overture.schema.system.geometric import ( ... Geometry, ... GeometryType, ... GeometryTypeConstraint, @@ -255,7 +255,7 @@ added to the model. >>> from overture.schema.common.unit import LengthUnit ->>> from overture.schema.system.primitive import float32 +>>> from overture.schema.system.numeric import float32 ... >>> @scoped(Scope.VEHICLE) ... class Fare(BaseModel): @@ -341,7 +341,7 @@ If a `when` field is added to the model, the model is also decorated with a nested `When` class to simplify instantiating values for the `when` field, for example: ->>> from overture.schema.system.primitive import uint8 +>>> from overture.schema.system.numeric import uint8 ... >>> @scoped(Scope.HEADING) ... class MyModel(BaseModel): diff --git a/packages/overture-schema-common/src/overture/schema/common/scoping/lr.py b/packages/overture-schema-common/src/overture/schema/common/scoping/lr.py index d1bc03b00..eb39b197c 100644 --- a/packages/overture-schema-common/src/overture/schema/common/scoping/lr.py +++ b/packages/overture-schema-common/src/overture/schema/common/scoping/lr.py @@ -8,7 +8,7 @@ from pydantic_core import InitErrorDetails, core_schema from overture.schema.system.field_constraint import CollectionConstraint -from overture.schema.system.primitive import float64 +from overture.schema.system.numeric import float64 LinearlyReferencedPosition = NewType( "LinearlyReferencedPosition", diff --git a/packages/overture-schema-common/src/overture/schema/common/scoping/vehicle.py b/packages/overture-schema-common/src/overture/schema/common/scoping/vehicle.py index 82330ecb1..fb791126f 100644 --- a/packages/overture-schema-common/src/overture/schema/common/scoping/vehicle.py +++ b/packages/overture-schema-common/src/overture/schema/common/scoping/vehicle.py @@ -9,7 +9,7 @@ from overture.schema.common.unit import LengthUnit, WeightUnit from overture.schema.system.model_constraint import no_extra_fields -from overture.schema.system.primitive import float64 +from overture.schema.system.numeric import float64 class VehicleDimension(str, Enum): diff --git a/packages/overture-schema-common/src/overture/schema/common/types.py b/packages/overture-schema-common/src/overture/schema/common/types.py index 8cbc8673f..4639d342c 100644 --- a/packages/overture-schema-common/src/overture/schema/common/types.py +++ b/packages/overture-schema-common/src/overture/schema/common/types.py @@ -4,7 +4,7 @@ Field, ) -from overture.schema.system.primitive import float64, int32 +from overture.schema.system.numeric import float64, int32 ConfidenceScore = NewType( "ConfidenceScore", diff --git a/packages/overture-schema-common/tests/test_models.py b/packages/overture-schema-common/tests/test_models.py index cc8003ae5..9d819de4e 100644 --- a/packages/overture-schema-common/tests/test_models.py +++ b/packages/overture-schema-common/tests/test_models.py @@ -6,11 +6,11 @@ from deepdiff import DeepDiff from overture.schema.common.models import OvertureFeature from overture.schema.common.sources import SourceItem -from overture.schema.system.json_schema import GenerateOmitNullableOptionalJsonSchema -from overture.schema.system.primitive import ( +from overture.schema.system.geometric import ( BBox, Geometry, ) +from overture.schema.system.json_schema import GenerateOmitNullableOptionalJsonSchema from pydantic import ValidationError from shapely.geometry import LineString, Point diff --git a/packages/overture-schema-common/tests/test_primitive_types.py b/packages/overture-schema-common/tests/test_numeric_types.py similarity index 94% rename from packages/overture-schema-common/tests/test_primitive_types.py rename to packages/overture-schema-common/tests/test_numeric_types.py index e35dc8ddd..698ed2082 100644 --- a/packages/overture-schema-common/tests/test_primitive_types.py +++ b/packages/overture-schema-common/tests/test_numeric_types.py @@ -1,9 +1,9 @@ -"""Tests for primitive data types functionality.""" +"""Tests for numeric data types functionality.""" from typing import Annotated import pytest -from overture.schema.system.primitive import ( +from overture.schema.system.numeric import ( float32, float64, int32, @@ -14,7 +14,7 @@ class TestValidation: - """Test validation behavior of primitive types.""" + """Test validation behavior of numeric types.""" def test_uint8_validation(self) -> None: """Test UInt8 validation constraints.""" @@ -51,7 +51,7 @@ class TestModel(BaseModel): TestModel(value=2**31) def test_optional_fields(self) -> None: - """Test optional primitive type fields.""" + """Test optional numeric type fields.""" class TestModel(BaseModel): required_value: uint8 @@ -68,7 +68,7 @@ class TestModel(BaseModel): assert model.optional_value is None def test_float_types(self) -> None: - """Test float primitive types.""" + """Test float numeric types.""" class TestModel(BaseModel): f32: float32 @@ -79,7 +79,7 @@ class TestModel(BaseModel): assert model.f64 == 2.71828 def test_conflicting_validation_criteria(self) -> None: - """Test that Field constraints closest to use take precedence over primitive + """Test that Field constraints closest to use take precedence over numeric type constraints.""" # Int32 has built-in constraints: ge=-(2**31), le=2**31-1 @@ -93,7 +93,7 @@ class TestModelRestrictive(BaseModel): assert TestModelRestrictive(value=5).value == 5 assert TestModelRestrictive(value=-5).value == -5 - # Should fail with the more restrictive constraint (le=5), not the primitive type constraint + # Should fail with the more restrictive constraint (le=5), not the numeric type constraint with pytest.raises(ValidationError) as exc_info: TestModelRestrictive(value=6) @@ -110,7 +110,7 @@ class TestModelPermissive(BaseModel): assert TestModelPermissive(value=-10).value == -10 assert TestModelPermissive(value=0).value == 0 - # Should fail with the closer constraint (ge=-10), not the primitive type constraint + # Should fail with the closer constraint (ge=-10), not the numeric type constraint with pytest.raises(ValidationError) as exc_info: TestModelPermissive(value=-11) diff --git a/packages/overture-schema-divisions-theme/src/overture/schema/divisions/_common.py b/packages/overture-schema-divisions-theme/src/overture/schema/divisions/_common.py index a2aaa9da0..69ddacc5d 100644 --- a/packages/overture-schema-divisions-theme/src/overture/schema/divisions/_common.py +++ b/packages/overture-schema-divisions-theme/src/overture/schema/divisions/_common.py @@ -5,7 +5,7 @@ from overture.schema.system.doc import DocumentedEnum from overture.schema.system.model_constraint import FieldEqCondition -from overture.schema.system.primitive import int32 +from overture.schema.system.numeric import int32 AdminLevel = NewType( "AdminLevel", 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 f0b00b246..3af64df23 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 @@ -22,18 +22,18 @@ from overture.schema.system.field_constraint import ( UniqueItemsConstraint, ) +from overture.schema.system.geometric import ( + Geometry, + GeometryType, + GeometryTypeConstraint, +) from overture.schema.system.model_constraint import ( FieldEqCondition, forbid_if, no_extra_fields, require_if, ) -from overture.schema.system.primitive import ( - Geometry, - GeometryType, - GeometryTypeConstraint, - int32, -) +from overture.schema.system.numeric import int32 from overture.schema.system.ref import Id, Reference, Relationship from overture.schema.system.string import ( CountryCodeAlpha2, diff --git a/packages/overture-schema-divisions-theme/src/overture/schema/divisions/division_area.py b/packages/overture-schema-divisions-theme/src/overture/schema/divisions/division_area.py index e1a92a94d..e910e3e4a 100644 --- a/packages/overture-schema-divisions-theme/src/overture/schema/divisions/division_area.py +++ b/packages/overture-schema-divisions-theme/src/overture/schema/divisions/division_area.py @@ -13,16 +13,16 @@ Names, ) from overture.schema.system.doc import DocumentedEnum +from overture.schema.system.geometric import ( + Geometry, + GeometryType, + GeometryTypeConstraint, +) from overture.schema.system.model_constraint import ( FieldEqCondition, require_any_true, require_if, ) -from overture.schema.system.primitive import ( - Geometry, - GeometryType, - GeometryTypeConstraint, -) from overture.schema.system.ref import Id, Reference, Relationship from overture.schema.system.string import CountryCodeAlpha2, RegionCode 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 974a928f4..60597cf29 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 @@ -11,17 +11,17 @@ from overture.schema.common.models import Perspectives from overture.schema.system.doc import DocumentedEnum from overture.schema.system.field_constraint import UniqueItemsConstraint +from overture.schema.system.geometric import ( + Geometry, + GeometryType, + GeometryTypeConstraint, +) from overture.schema.system.model_constraint import ( FieldEqCondition, forbid_if, require_any_true, require_if, ) -from overture.schema.system.primitive import ( - Geometry, - GeometryType, - GeometryTypeConstraint, -) from overture.schema.system.ref import Id, Reference, Relationship from overture.schema.system.string import CountryCodeAlpha2, RegionCode 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 f83e54e0b..3682e8f8a 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 @@ -20,12 +20,12 @@ from overture.schema.system.field_constraint import ( UniqueItemsConstraint, ) -from overture.schema.system.model_constraint import no_extra_fields -from overture.schema.system.primitive import ( +from overture.schema.system.geometric import ( Geometry, GeometryType, GeometryTypeConstraint, ) +from overture.schema.system.model_constraint import no_extra_fields from overture.schema.system.string import ( CountryCodeAlpha2, PhoneNumber, diff --git a/packages/overture-schema-pyspark/src/overture/schema/pyspark/check.py b/packages/overture-schema-pyspark/src/overture/schema/pyspark/check.py index ac6d993b2..71e09ad2f 100644 --- a/packages/overture-schema-pyspark/src/overture/schema/pyspark/check.py +++ b/packages/overture-schema-pyspark/src/overture/schema/pyspark/check.py @@ -9,7 +9,7 @@ from pyspark.sql import Column from pyspark.sql.types import StructType -from overture.schema.system.primitive import GeometryType +from overture.schema.system.geometric import GeometryType class CheckShape(Enum): diff --git a/packages/overture-schema-pyspark/src/overture/schema/pyspark/cli.py b/packages/overture-schema-pyspark/src/overture/schema/pyspark/cli.py index ed8dae2b8..14fb70833 100644 --- a/packages/overture-schema-pyspark/src/overture/schema/pyspark/cli.py +++ b/packages/overture-schema-pyspark/src/overture/schema/pyspark/cli.py @@ -11,7 +11,7 @@ from pyspark.sql import DataFrame, SparkSession from overture.schema.system.discovery import resolve_entry_point_key -from overture.schema.system.primitive import GeometryType +from overture.schema.system.geometric import GeometryType from ._registry import PARTITION_MAP, REGISTRY from .validate import ( diff --git a/packages/overture-schema-pyspark/src/overture/schema/pyspark/expressions/constraint_expressions.py b/packages/overture-schema-pyspark/src/overture/schema/pyspark/expressions/constraint_expressions.py index abc459b28..9540c52bc 100644 --- a/packages/overture-schema-pyspark/src/overture/schema/pyspark/expressions/constraint_expressions.py +++ b/packages/overture-schema-pyspark/src/overture/schema/pyspark/expressions/constraint_expressions.py @@ -21,7 +21,7 @@ from pyspark.sql import Column from pyspark.sql import functions as F -from overture.schema.system.primitive import GeometryType +from overture.schema.system.geometric import GeometryType from .column_patterns import error_msg diff --git a/packages/overture-schema-pyspark/tests/expressions/test_constraint_expressions.py b/packages/overture-schema-pyspark/tests/expressions/test_constraint_expressions.py index b5565a4d7..d62936c30 100644 --- a/packages/overture-schema-pyspark/tests/expressions/test_constraint_expressions.py +++ b/packages/overture-schema-pyspark/tests/expressions/test_constraint_expressions.py @@ -31,7 +31,7 @@ check_url_length, except_literals, ) -from overture.schema.system.primitive import GeometryType +from overture.schema.system.geometric import GeometryType from pyspark.sql import Row, SparkSession from pyspark.sql import functions as F from pyspark.sql.types import DoubleType, StringType, StructField, StructType diff --git a/packages/overture-schema-system/README.md b/packages/overture-schema-system/README.md index 9733d105f..6dddfc8cc 100644 --- a/packages/overture-schema-system/README.md +++ b/packages/overture-schema-system/README.md @@ -1,6 +1,6 @@ # Overture Schema System -Write Pydantic models once, get validated data that serializes correctly to JSON, Parquet, and Spark. This package provides the primitive types, constraint decorators, and GeoJSON-aware base class that make Pydantic models portable across serialization targets. +Write Pydantic models once, get validated data that serializes correctly to JSON, Parquet, and Spark. This package provides the numeric and geometric types, constraint decorators, and GeoJSON-aware base class that make Pydantic models portable across serialization targets. ## Installation @@ -14,7 +14,8 @@ GeoJSON-compatible Pydantic base model. Subclasses serialize to the GeoJSON form ```python from overture.schema.system.feature import Feature -from overture.schema.system.primitive import Geometry, float32 +from overture.schema.system.geometric import Geometry +from overture.schema.system.numeric import float32 class Mountain(Feature): name: str @@ -27,20 +28,30 @@ m = Mountain( ) ``` -## Primitive Types +## Numeric Types -Using `int` and `float` in a Pydantic model produces valid Python but loses information downstream -- an `int` field becomes a 64-bit integer in Parquet, Arrow, and Spark StructTypes, even when the domain is 0--255. The primitive types (`uint8`, `int32`, `float32`, etc.) carry range constraints and map to the correct wire type so data round-trips cleanly between Python, Parquet files, PostgreSQL, and JSON Schema: +Using `int` and `float` in a Pydantic model produces valid Python but loses information downstream -- an `int` field becomes a 64-bit integer in Parquet, Arrow, and Spark StructTypes, even when a single byte would hold every value. How wide a field needs to be is the schema author's choice, but `int` and `float` give Pydantic no way to record it. The numeric types (`uint8`, `int32`, `float32`, etc.) do: each declares a width that maps to the correct wire type in every serialization target, so a single portable declaration round-trips cleanly between Python, Parquet, Spark, and JSON Schema: ```python from pydantic import BaseModel -from overture.schema.system.primitive import uint8, float32 +from overture.schema.system.numeric import uint8, float32 class Building(BaseModel): height: float32 | None = None num_floors: uint8 | None = None ``` -Integer types: `uint8`, `uint16`, `uint32`, `int8`, `int16`, `int32`, `int64`. Float types: `float32`, `float64`. Geometry types: `Geometry`, `BBox`, `GeometryType`, `GeometryTypeConstraint`. +Integer types: `uint8`, `uint16`, `uint32`, `int8`, `int16`, `int32`, `int64`. Float types: `float32`, `float64`. + +## Geometric Types + +`Geometry` and `BBox` wrap Shapely and GeoJSON-compatible geometry and bounding box values so they can participate in a Pydantic model as fields, with `GeometryType` and `GeometryTypeConstraint` available to restrict a `Geometry` field to specific geometry types: + +```python +from overture.schema.system.geometric import Geometry, GeometryType, GeometryTypeConstraint +``` + +Types: `Geometry`, `BBox`, `GeometryType`, `GeometryTypeConstraint`. ## String Types diff --git a/packages/overture-schema-system/src/overture/schema/system/__init__.py b/packages/overture-schema-system/src/overture/schema/system/__init__.py index a491d860f..1a8c6e1dd 100644 --- a/packages/overture-schema-system/src/overture/schema/system/__init__.py +++ b/packages/overture-schema-system/src/overture/schema/system/__init__.py @@ -1,8 +1,8 @@ r""" Foundational types at the base of the Overture schema system. -A set of primitive types, constraint rules, and Pydantic model classes, and annotations that can be -used to create strongly-typed, predictably validated, data. +A set of numeric and geometric types, constraint rules, and Pydantic model classes, and annotations +that can be used to create strongly-typed, predictably validated, data. Subpackages ----------- @@ -13,15 +13,17 @@ - :mod:`field_constraint ` Constraints that can be annotated onto Pydantic model fields to force them to conform to well-known rules, for example "a collection that contains unique items" or "a string that is a valid country code". +- :mod:`geometric ` Geometric types, including `Geometry` and + `BBox`. - :mod:`json_schema ` Overture-flavored JSON Schema generation for Pydantic models. - :mod:`model_constraint ` Constraints that can be decorated onto Pydantic model classes to add cross-field validation rules, for example "these two fields are mutually-exclusive" or "if this field is set, then that field must also be set". +- :mod:`numeric ` Portable numeric types with specific bit widths, + for example `int32` and `float64`. - :mod:`optionality` ` The `Omitable` type hint, syntax sugar to help a Pydantic model's optional fields behave closer to JSON Schema semantics. -- :mod:`primitive ` Primitive data types, including numeric and - geometry types. - :mod:`ref ` Unique IDs and annotations to describe relationships between models based on unique IDs. (*i.e.*, foreign key relationships). - :mod:`string ` String types with built-in validation to conform to @@ -36,7 +38,7 @@ Parquet.) - Tightly integrated with Pydantic's JSON Schema system, providing rich JSON Schemas and maximum parity between Pydantic, generated JSON Schemas, and Overture's code generation tools. -- First-class support for geospatial data using the geometry primitives and the +- First-class support for geospatial data using the geometry types and the `overture.schema.system.feature.Feature` class. - Conditional fields and validation on relationships between fields (*e.g.*, if the type field contains "region", then region code field must also be set). @@ -49,7 +51,7 @@ rejects invalid input: >>> from pydantic import BaseModel, ValidationError ->>> from overture.schema.system.primitive import uint32; +>>> from overture.schema.system.numeric import uint32; >>> from overture.schema.system.string import SnakeCaseString; >>> class MyModel(BaseModel): ... index: uint32 @@ -63,7 +65,7 @@ Valid inputs to the same model are accepted: >>> from pydantic import BaseModel, ValidationError ->>> from overture.schema.system.primitive import uint32; +>>> from overture.schema.system.numeric import uint32; >>> from overture.schema.system.string import SnakeCaseString; >>> class MyModel(BaseModel): ... index: uint32 @@ -151,11 +153,12 @@ doc, feature, field_constraint, + geometric, json_schema, metadata, model_constraint, + numeric, optionality, - primitive, ref, string, ) @@ -166,11 +169,12 @@ "doc", "feature", "field_constraint", + "geometric", "json_schema", "metadata", "model_constraint", + "numeric", "optionality", - "primitive", "ref", "string", ] diff --git a/packages/overture-schema-system/src/overture/schema/system/feature.py b/packages/overture-schema-system/src/overture/schema/system/feature.py index 429582535..b3b2211ca 100644 --- a/packages/overture-schema-system/src/overture/schema/system/feature.py +++ b/packages/overture-schema-system/src/overture/schema/system/feature.py @@ -25,8 +25,8 @@ from typing_extensions import Self from overture.schema.system import _json_schema +from overture.schema.system.geometric import BBox, Geometry from overture.schema.system.optionality import Omitable -from overture.schema.system.primitive import BBox, Geometry from overture.schema.system.ref import Id @@ -70,7 +70,8 @@ class Feature(BaseModel): >>> from typing import Annotated >>> from pydantic import Field - >>> from overture.schema.system.primitive import Geometry, float32 + >>> from overture.schema.system.geometric import Geometry + >>> from overture.schema.system.numeric import float32 ... >>> class Mountain(Feature): ... name: str @@ -108,7 +109,7 @@ class Feature(BaseModel): This can help maximize validation and data integrity by preventing geometries that do not make sense from being stored. - >>> from overture.schema.system.primitive import GeometryType, GeometryTypeConstraint + >>> from overture.schema.system.geometric import GeometryType, GeometryTypeConstraint ... >>> class River(Feature): ... geometry: Annotated[ @@ -124,7 +125,7 @@ class Feature(BaseModel): union, use the `field_discriminator` method: >>> from typing import Annotated, Literal - >>> from overture.schema.system.primitive import float32 + >>> from overture.schema.system.numeric import float32 >>> import pydantic >>> >>> class Field(Feature): diff --git a/packages/overture-schema-system/src/overture/schema/system/geometric/__init__.py b/packages/overture-schema-system/src/overture/schema/system/geometric/__init__.py new file mode 100644 index 000000000..fd1ea6518 --- /dev/null +++ b/packages/overture-schema-system/src/overture/schema/system/geometric/__init__.py @@ -0,0 +1,25 @@ +""" +Geometric types. + +This module provides geometric types that can be used as fields in Pydantic models but are +not themselves models: `Geometry` for GeoJSON-compatible vector geometry, and `BBox` for bounding +boxes. + +These types have representations that can differ significantly between different serialization +targets, so they do not derive from the Pydantic `BaseModel` although they can participate in a +`BaseModel` as a field. +""" + +from .bbox import BBox +from .geom import ( + Geometry, + GeometryType, + GeometryTypeConstraint, +) + +__all__ = [ + "BBox", + "Geometry", + "GeometryType", + "GeometryTypeConstraint", +] diff --git a/packages/overture-schema-system/src/overture/schema/system/primitive/bbox.py b/packages/overture-schema-system/src/overture/schema/system/geometric/bbox.py similarity index 96% rename from packages/overture-schema-system/src/overture/schema/system/primitive/bbox.py rename to packages/overture-schema-system/src/overture/schema/system/geometric/bbox.py index c078290c5..5af086be9 100644 --- a/packages/overture-schema-system/src/overture/schema/system/primitive/bbox.py +++ b/packages/overture-schema-system/src/overture/schema/system/geometric/bbox.py @@ -1,5 +1,5 @@ """ -Bounding box primitive. +Bounding box type. """ from typing import Any @@ -15,11 +15,11 @@ class BBox: """ - Immutable 2D bounding box primitive. + Immutable 2D bounding box type. - This type is a geometric primitive with representations that can differ significantly between - different data formats. Consequently, does not derive from the Pydantic `BaseModel` although it - can participate in a `BaseModel` as a field. + Representations of this type can differ significantly between different data formats. + Consequently, it does not derive from the Pydantic `BaseModel` although it can participate in a + `BaseModel` as a field. Parameters ---------- diff --git a/packages/overture-schema-system/src/overture/schema/system/primitive/geom.py b/packages/overture-schema-system/src/overture/schema/system/geometric/geom.py similarity index 97% rename from packages/overture-schema-system/src/overture/schema/system/primitive/geom.py rename to packages/overture-schema-system/src/overture/schema/system/geometric/geom.py index 281abe59e..b543cbb6f 100644 --- a/packages/overture-schema-system/src/overture/schema/system/primitive/geom.py +++ b/packages/overture-schema-system/src/overture/schema/system/geometric/geom.py @@ -1,5 +1,5 @@ """ -Geometry primitive and geometry type constraint. +The `Geometry` value type and its geometry type constraint. Use `Geometry` as the type for fields containing geometry values. Use `GeometryTypeConstraint` if you need to constrain allowed types of geometries. @@ -10,7 +10,7 @@ >>> from typing import Annotated >>> from pydantic import BaseModel ->>> from overture.schema.system.primitive import float32 +>>> from overture.schema.system.numeric import float32 >>> class Peak(BaseModel): ... position: Annotated[ ... Geometry, @@ -210,11 +210,11 @@ def __get_pydantic_json_schema__( class Geometry: """ - Immutable vector geometry primitive. + Immutable vector geometry type. - This type is a geometric primitive with representations that can differ significantly between - different data formats. Consequently, does not derive from the Pydantic `BaseModel` although it - can participate in a `BaseModel` as a field. + Representations of this type can differ significantly between different data formats. + Consequently, it does not derive from the Pydantic `BaseModel` although it can participate in a + `BaseModel` as a field. Parameters ---------- @@ -407,7 +407,7 @@ def __get_pydantic_json_schema__( ######################################################################## -# JSON Schema primitives for GeoJSON geometry +# Base JSON Schema for GeoJSON geometry ######################################################################## # This is the `bbox` schema for a GeoJSON *geometry* object, not for a diff --git a/packages/overture-schema-system/src/overture/schema/system/primitive/__init__.py b/packages/overture-schema-system/src/overture/schema/system/numeric.py similarity index 77% rename from packages/overture-schema-system/src/overture/schema/system/primitive/__init__.py rename to packages/overture-schema-system/src/overture/schema/system/numeric.py index 2b27ef89e..ae53de77f 100644 --- a/packages/overture-schema-system/src/overture/schema/system/primitive/__init__.py +++ b/packages/overture-schema-system/src/overture/schema/system/numeric.py @@ -1,28 +1,22 @@ """ -Primitive data types. - -This module provides a set of primitive types that can be used as fields in Pydantic models but are -not themselves models. The primitive types include specific numeric types such as `int16` and -`float64`; and geometric types including `Geometry` and `BBox`. - -Primitives are intended to provide specific, well-defined behavior for a wide range of serialization -targets including not just Pydantic models and JSON, but also a range of other serialization -targets, for example, the Parquet format or Spark dataframes. They come with built-in Pydantic -constraints, but also specific documented behavior expectations so they can be supported by other -serialization targets. +Numeric types. + +This module provides a set of portable numeric types that can be used as fields in Pydantic models +but are not themselves models: unsigned and signed integers of specific bit widths, and 32- and +64-bit floating point numbers. + +These types are `int` or `float` at runtime, but using them for Pydantic model fields instead of the +bare Python types makes them portable across different serialization and validation targets, +including not just Pydantic models and JSON, but also a range of other serialization targets, for +example, the Parquet format or Spark dataframes. They come with built-in Pydantic constraints, but +also specific documented behavior expectations so they can be supported by other serialization +targets. """ from typing import Annotated, NewType from pydantic import Field -from .bbox import BBox -from .geom import ( - Geometry, - GeometryType, - GeometryTypeConstraint, -) - uint8 = NewType("uint8", Annotated[int, Field(ge=0, le=255)]) # type: ignore [type-arg] uint8.__doc__ = """ Portable 8-bit unsigned integer. @@ -97,16 +91,12 @@ __all__ = [ - "BBox", - "Geometry", - "GeometryType", - "GeometryTypeConstraint", + "float32", + "float64", "int8", "int16", "int32", "int64", - "float32", - "float64", "uint8", "uint16", "uint32", diff --git a/packages/overture-schema-system/src/overture/schema/system/string.py b/packages/overture-schema-system/src/overture/schema/system/string.py index 6533a192a..2de609445 100644 --- a/packages/overture-schema-system/src/overture/schema/system/string.py +++ b/packages/overture-schema-system/src/overture/schema/system/string.py @@ -5,9 +5,9 @@ Pydantic models to ensure the field values conform to well-known patterns, for example country codes, language tags, and color codes. -While not considered "primitives", the fundamental string types are intended to provide specific, -well-defined behavior for a wide range of serialization targets including not just Pydantic models -and JSON, but also including targets such as the Parquet data formats and Spark dataframes. +The fundamental string types are intended to provide specific, well-defined behavior for a wide +range of serialization targets including not just Pydantic models and JSON, but also including +targets such as the Parquet data formats and Spark dataframes. """ from typing import Annotated, NewType diff --git a/packages/overture-schema-system/tests/primitive/test_bbox.py b/packages/overture-schema-system/tests/geometric/test_bbox.py similarity index 99% rename from packages/overture-schema-system/tests/primitive/test_bbox.py rename to packages/overture-schema-system/tests/geometric/test_bbox.py index 31146720a..22e5d025a 100644 --- a/packages/overture-schema-system/tests/primitive/test_bbox.py +++ b/packages/overture-schema-system/tests/geometric/test_bbox.py @@ -4,7 +4,7 @@ import pytest from pydantic import BaseModel, ValidationError -from overture.schema.system.primitive.bbox import BBox +from overture.schema.system.geometric.bbox import BBox @pytest.mark.parametrize( diff --git a/packages/overture-schema-system/tests/primitive/test_geom.py b/packages/overture-schema-system/tests/geometric/test_geom.py similarity index 99% rename from packages/overture-schema-system/tests/primitive/test_geom.py rename to packages/overture-schema-system/tests/geometric/test_geom.py index 68dc5dd5b..b24c2de6c 100644 --- a/packages/overture-schema-system/tests/primitive/test_geom.py +++ b/packages/overture-schema-system/tests/geometric/test_geom.py @@ -8,7 +8,7 @@ from pydantic import BaseModel, ValidationError from shapely import wkt -from overture.schema.system.primitive import ( +from overture.schema.system.geometric import ( Geometry, GeometryType, GeometryTypeConstraint, diff --git a/packages/overture-schema-system/tests/test_feature.py b/packages/overture-schema-system/tests/test_feature.py index fc4a31751..008eedb5f 100644 --- a/packages/overture-schema-system/tests/test_feature.py +++ b/packages/overture-schema-system/tests/test_feature.py @@ -19,6 +19,12 @@ from util import assert_subset from overture.schema.system.feature import Feature, _FieldLevel, _maybe_refactor_schema +from overture.schema.system.geometric import ( + BBox, + Geometry, + GeometryType, + GeometryTypeConstraint, +) from overture.schema.system.model_constraint import ( FieldEqCondition, forbid_if, @@ -27,12 +33,6 @@ require_if, ) from overture.schema.system.optionality import Omitable -from overture.schema.system.primitive import ( - BBox, - Geometry, - GeometryType, - GeometryTypeConstraint, -) class TestFieldDiscriminator: diff --git a/packages/overture-schema-transportation-theme/src/overture/schema/transportation/connector/models.py b/packages/overture-schema-transportation-theme/src/overture/schema/transportation/connector/models.py index cb7d4e482..58964b628 100644 --- a/packages/overture-schema-transportation-theme/src/overture/schema/transportation/connector/models.py +++ b/packages/overture-schema-transportation-theme/src/overture/schema/transportation/connector/models.py @@ -7,7 +7,7 @@ from overture.schema.common import ( OvertureFeature, ) -from overture.schema.system.primitive import ( +from overture.schema.system.geometric import ( Geometry, GeometryType, GeometryTypeConstraint, 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 260fd4574..fc7554930 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 @@ -15,7 +15,7 @@ no_extra_fields, require_any_of, ) -from overture.schema.system.primitive import float64, int32 +from overture.schema.system.numeric import float64, int32 from overture.schema.system.ref import Id, Reference, Relationship from overture.schema.system.string import StrippedString, WikidataId diff --git a/packages/overture-schema-transportation-theme/src/overture/schema/transportation/segment/models.py b/packages/overture-schema-transportation-theme/src/overture/schema/transportation/segment/models.py index 3643fd572..6a7ad9b5f 100644 --- a/packages/overture-schema-transportation-theme/src/overture/schema/transportation/segment/models.py +++ b/packages/overture-schema-transportation-theme/src/overture/schema/transportation/segment/models.py @@ -12,7 +12,7 @@ ) from overture.schema.system.feature import Feature from overture.schema.system.field_constraint import UniqueItemsConstraint -from overture.schema.system.primitive import ( +from overture.schema.system.geometric import ( Geometry, GeometryType, GeometryTypeConstraint,