From 5ea1eea7b0c38affa8c2c5087b75693c5096139c Mon Sep 17 00:00:00 2001 From: Seth Fitzsimmons Date: Fri, 10 Jul 2026 09:59:53 -0700 Subject: [PATCH 1/4] [REFACTOR](schema) Split system.primitive into numeric and geometric modules `overture.schema.system.primitive` mixed two unrelated concerns: portable numeric NewTypes (int8, uint32, float64, etc.) and geometric types (BBox, Geometry, GeometryType, GeometryTypeConstraint). The docs reference page this produced was titled "Primitive Types" at system/primitive/primitives even though it only covered numeric types. Numeric types move to a new numeric.py module; BBox and Geometry move to a new geometric package. The primitive package is removed and every import across the workspace (themes, common, codegen, and their tests, including several doctest examples) is updated to the correct module. The aggregate docs pages move with their source: system/numeric.md (title "Numeric Types") and system/geometry.md, both flat under system/ like the existing scalar type pages, rather than nested under primitive/. Fixes #464. Signed-off-by: Seth Fitzsimmons --- .../src/overture/schema/addresses/address.py | 4 +- .../src/overture/schema/base/_common.py | 2 +- .../src/overture/schema/base/bathymetry.py | 2 +- .../overture/schema/base/infrastructure.py | 2 +- .../src/overture/schema/base/land.py | 2 +- .../src/overture/schema/base/land_cover.py | 2 +- .../src/overture/schema/base/land_use.py | 2 +- .../src/overture/schema/base/water.py | 2 +- .../src/overture/schema/buildings/_common.py | 2 +- .../src/overture/schema/buildings/building.py | 2 +- .../schema/buildings/building_part.py | 2 +- packages/overture-schema-codegen/README.md | 2 +- .../overture-schema-codegen/docs/design.md | 2 +- .../docs/walkthrough.md | 28 ++++---- .../codegen/extraction/field_constraints.py | 2 +- .../codegen/markdown/path_assignment.py | 8 +-- .../schema/codegen/markdown/pipeline.py | 37 +++++----- .../schema/codegen/markdown/renderer.py | 10 +-- ...primitives.md.jinja2 => numeric.md.jinja2} | 2 +- .../tests/codegen_test_support.py | 7 +- .../overture-schema-codegen/tests/conftest.py | 17 +++-- .../tests/test_constraint_description.py | 2 +- .../tests/test_example_loader.py | 6 +- .../tests/test_markdown_renderer.py | 72 +++++++++---------- .../tests/test_markdown_type_format.py | 12 ++-- .../tests/test_model_extractor.py | 10 +-- .../tests/test_numeric_extraction.py | 23 ++++-- .../tests/test_specs.py | 2 +- .../tests/test_type_analyzer.py | 2 +- .../tests/test_type_placement.py | 23 +++--- packages/overture-schema-common/README.md | 4 +- .../src/overture/schema/common/cartography.py | 2 +- .../src/overture/schema/common/models.py | 4 +- .../src/overture/schema/common/names.py | 2 +- .../schema/common/scoping/__init__.py | 20 +++--- .../src/overture/schema/common/scoping/lr.py | 2 +- .../overture/schema/common/scoping/vehicle.py | 2 +- .../src/overture/schema/common/types.py | 2 +- .../tests/test_models.py | 4 +- ...imitive_types.py => test_numeric_types.py} | 16 ++--- .../src/overture/schema/divisions/_common.py | 2 +- .../src/overture/schema/divisions/division.py | 12 ++-- .../schema/divisions/division_area.py | 10 +-- .../schema/divisions/division_boundary.py | 10 +-- .../src/overture/schema/places/place.py | 4 +- packages/overture-schema-system/README.md | 23 ++++-- .../src/overture/schema/system/__init__.py | 16 +++-- .../src/overture/schema/system/feature.py | 9 +-- .../schema/system/geometric/__init__.py | 25 +++++++ .../system/{primitive => geometric}/bbox.py | 0 .../system/{primitive => geometric}/geom.py | 2 +- .../{primitive/__init__.py => numeric.py} | 38 ++++------ .../{primitive => geometric}/test_bbox.py | 2 +- .../{primitive => geometric}/test_geom.py | 2 +- .../tests/test_feature.py | 12 ++-- .../schema/transportation/connector/models.py | 2 +- .../overture/schema/transportation/models.py | 2 +- .../schema/transportation/segment/models.py | 2 +- 58 files changed, 283 insertions(+), 239 deletions(-) rename packages/overture-schema-codegen/src/overture/schema/codegen/markdown/templates/{primitives.md.jinja2 => numeric.md.jinja2} (97%) rename packages/overture-schema-common/tests/{test_primitive_types.py => test_numeric_types.py} (94%) create mode 100644 packages/overture-schema-system/src/overture/schema/system/geometric/__init__.py rename packages/overture-schema-system/src/overture/schema/system/{primitive => geometric}/bbox.py (100%) rename packages/overture-schema-system/src/overture/schema/system/{primitive => geometric}/geom.py (99%) rename packages/overture-schema-system/src/overture/schema/system/{primitive/__init__.py => numeric.py} (77%) rename packages/overture-schema-system/tests/{primitive => geometric}/test_bbox.py (99%) rename packages/overture-schema-system/tests/{primitive => geometric}/test_geom.py (99%) 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 9b820b92f..49fbef878 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 2cc340c17..b1c35a241 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 d83cb7967..2ce59f61e 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 662d77fc5..6977d023a 100644 --- a/packages/overture-schema-codegen/docs/design.md +++ b/packages/overture-schema-codegen/docs/design.md @@ -220,7 +220,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_feature()` expands MODEL-kind fields inline with dot-notation (e.g., `sources[].dataset`), stopping at cycle boundaries. `format_type()` in `markdown/type_format.py` converts `TypeInfo` into link-aware display strings using diff --git a/packages/overture-schema-codegen/docs/walkthrough.md b/packages/overture-schema-codegen/docs/walkthrough.md index 397e082f5..0160f3d29 100644 --- a/packages/overture-schema-codegen/docs/walkthrough.md +++ b/packages/overture-schema-codegen/docs/walkthrough.md @@ -361,12 +361,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`. @@ -454,9 +455,9 @@ independent `if` statements, not `elif`. `build_placement_registry` builds the complete mapping from type names to output file paths. Three 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/geometry.md`. These are hardcoded paths since the types share a single reference page. Feature specs get individual pages. Output directories derive from @@ -538,7 +539,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 `geometry.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 @@ -580,7 +581,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 @@ -636,8 +637,8 @@ Eight steps: 1. **Expand model trees** with a shared cache across all features, so sub-models referenced by multiple features extract once. -2. **Partition primitive and geometry names** from the system primitive module's - `__all__` exports. +2. **Partition numeric and geometry names** from the system numeric and geometric + modules' `__all__` exports. 3. **Collect supplementary types** by walking expanded feature trees. @@ -650,7 +651,7 @@ Eight steps: 7. **Render each supplementary type** -- dispatching to `render_enum`, `render_newtype`, or `render_feature` (for sub-models) based on spec type. -8. **Render aggregate pages** for primitives and geometry. +8. **Render aggregate pages** for numeric types and geometry. The return value is `list[RenderedPage]` -- frozen dataclasses carrying content, output path, and a boolean `is_feature` flag. The caller decides what to do with them. @@ -713,7 +714,8 @@ two NewType layers and an `Annotated` layer, producing a `TypeInfo` with `FieldSpec.model` references. The shared cache ensures sub-models referenced by multiple features (like `Sources`) extract once. Union-kind fields skip inline expansion. -**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 expanded fields and discovers referenced enums (like `Subtype`), semantic NewTypes (like `Id`, `Sources`), and sub-models. The walk follows `FieldSpec.model` references down the tree, and for 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 0db927065..6b12d98b4 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 @@ -11,7 +11,7 @@ from annotated_types import Ge, Gt, Interval, Le, Lt, MaxLen, MinLen -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 f0d224ee4..34a931141 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,14 +18,14 @@ __all__ = [ "GEOMETRY_PAGE", - "PRIMITIVES_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") +GEOMETRY_PAGE = PurePosixPath("system/geometry.md") def build_placement_registry( @@ -86,7 +86,7 @@ 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)) 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 f7c676c06..75d8bf60d 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.model_extraction import expand_model_tree @@ -31,7 +32,7 @@ from .link_computation import LinkContext from .path_assignment import ( GEOMETRY_PAGE, - PRIMITIVES_PAGE, + NUMERIC_PAGE, build_placement_registry, resolve_output_path, ) @@ -40,7 +41,7 @@ render_feature, render_geometry_from_values, render_newtype, - render_primitives_from_specs, + render_numeric_from_specs, render_pydantic_type, ) from .reverse_references import UsedByEntry, compute_reverse_references @@ -112,22 +113,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 @@ -148,7 +151,7 @@ def generate_markdown_pages( expand_model_tree(spec, cache) numeric_names, geometry_names = partition_numeric_and_geometry_types( - _system_primitive + _system_numeric, _system_geometric ) all_specs = collect_all_supplementary_types(feature_specs) registry = build_placement_registry( @@ -172,8 +175,8 @@ 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, ) ) 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 0e829d1f4..bf16ef816 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 @@ -44,7 +44,7 @@ "render_feature", "render_geometry_from_values", "render_newtype", - "render_primitives_from_specs", + "render_numeric_from_specs", "render_pydantic_type", ] @@ -521,7 +521,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 @@ -586,9 +586,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]] = [] 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/tests/codegen_test_support.py b/packages/overture-schema-codegen/tests/codegen_test_support.py index 2a18faf13..2adcb7193 100644 --- a/packages/overture-schema-codegen/tests/codegen_test_support.py +++ b/packages/overture-schema-codegen/tests/codegen_test_support.py @@ -33,14 +33,13 @@ 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.model_constraint import require_any_of -from overture.schema.system.primitive import ( +from overture.schema.system.geometric import ( Geometry, GeometryType, GeometryTypeConstraint, - float64, - int32, ) +from overture.schema.system.model_constraint import require_any_of +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 d66cf72a3..dc4646f13 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,10 +71,12 @@ 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") diff --git a/packages/overture-schema-codegen/tests/test_constraint_description.py b/packages/overture-schema-codegen/tests/test_constraint_description.py index b205f6f73..7929a1ff1 100644 --- a/packages/overture-schema-codegen/tests/test_constraint_description.py +++ b/packages/overture-schema-codegen/tests/test_constraint_description.py @@ -10,6 +10,7 @@ ) from overture.schema.codegen.extraction.specs import TypeIdentity from overture.schema.codegen.extraction.type_analyzer import ConstraintSource +from overture.schema.system.geometric import GeometryType, GeometryTypeConstraint from overture.schema.system.model_constraint import ( FieldEqCondition, ForbidIfConstraint, @@ -22,7 +23,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 1f94bc06d..a0cb89309 100644 --- a/packages/overture-schema-codegen/tests/test_example_loader.py +++ b/packages/overture-schema-codegen/tests/test_example_loader.py @@ -889,7 +889,7 @@ class Aliased(BaseModel): def test_slots_based_field_flattened(self) -> None: """Non-BaseModel types with __slots__ and properties are flattened.""" - from overture.schema.system.primitive import BBox # noqa: PLC0415 + from overture.schema.system.geometric import BBox # noqa: PLC0415 class WithBBox(BaseModel): id: str @@ -907,7 +907,7 @@ class WithBBox(BaseModel): def test_none_slots_based_field_is_leaf(self) -> None: """A slots-based field with None value is a leaf.""" - from overture.schema.system.primitive import BBox # noqa: PLC0415 + from overture.schema.system.geometric import BBox # noqa: PLC0415 class WithBBox(BaseModel): id: str @@ -919,7 +919,7 @@ class WithBBox(BaseModel): def test_single_slot_wrapper_is_leaf(self) -> None: """Single-slot types (wrappers like Geometry) are leaf values.""" - from overture.schema.system.primitive import Geometry # noqa: PLC0415 + from overture.schema.system.geometric import Geometry # noqa: PLC0415 from shapely.geometry import Point # noqa: PLC0415 class WithGeom(BaseModel): diff --git a/packages/overture-schema-codegen/tests/test_markdown_renderer.py b/packages/overture-schema-codegen/tests/test_markdown_renderer.py index 698f9d70a..7b2c6477a 100644 --- a/packages/overture-schema-codegen/tests/test_markdown_renderer.py +++ b/packages/overture-schema-codegen/tests/test_markdown_renderer.py @@ -47,7 +47,7 @@ render_enum, render_feature, render_newtype, - render_primitives_from_specs, + render_numeric_from_specs, render_pydantic_type, ) from overture.schema.codegen.markdown.reverse_references import UsedByEntry, UsedByKind @@ -57,7 +57,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 @@ -1122,50 +1122,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", @@ -1173,7 +1173,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 e54426f5f..7f57245c7 100644 --- a/packages/overture-schema-codegen/tests/test_markdown_type_format.py +++ b/packages/overture-schema-codegen/tests/test_markdown_type_format.py @@ -16,7 +16,7 @@ format_type, format_underlying_type, ) -from overture.schema.system.primitive import int32 +from overture.schema.system.numeric import int32 from pydantic import BaseModel, HttpUrl @@ -222,20 +222,16 @@ 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.""" ti = analyze_type(int32) field = _make_field(ti) 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(field, ctx) assert "[`int32`]" in result - assert "system/primitive/primitives.md" in result + assert "system/numeric.md" in result class TestListOfSemanticNewtype: diff --git a/packages/overture-schema-codegen/tests/test_model_extractor.py b/packages/overture-schema-codegen/tests/test_model_extractor.py index f2b2bd257..4c3a2ecb4 100644 --- a/packages/overture-schema-codegen/tests/test_model_extractor.py +++ b/packages/overture-schema-codegen/tests/test_model_extractor.py @@ -18,17 +18,17 @@ ) from overture.schema.codegen.extraction.specs import ModelSpec 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 ee604ba75..1d07db640 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_specs.py b/packages/overture-schema-codegen/tests/test_specs.py index 0780e2fda..30356b46d 100644 --- a/packages/overture-schema-codegen/tests/test_specs.py +++ b/packages/overture-schema-codegen/tests/test_specs.py @@ -283,7 +283,7 @@ def test_enum_spec_identity(self) -> None: assert ident.name == "Color" def test_newtype_spec_identity(self) -> None: - from overture.schema.system.primitive import int32 + from overture.schema.system.numeric import int32 spec = NewTypeSpec( name="int32", description=None, type_info=STR_TYPE, source_type=int32 diff --git a/packages/overture-schema-codegen/tests/test_type_analyzer.py b/packages/overture-schema-codegen/tests/test_type_analyzer.py index bbf8373fd..f1aeafca6 100644 --- a/packages/overture-schema-codegen/tests/test_type_analyzer.py +++ b/packages/overture-schema-codegen/tests/test_type_analyzer.py @@ -12,7 +12,7 @@ analyze_type, single_literal_value, ) -from overture.schema.system.primitive import float64, int32 +from overture.schema.system.numeric import float64, 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_placement.py b/packages/overture-schema-codegen/tests/test_type_placement.py index 63e26457c..500462883 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, @@ -26,7 +27,7 @@ from overture.schema.codegen.markdown.link_computation import LinkContext, relative_link from overture.schema.codegen.markdown.path_assignment import ( GEOMETRY_PAGE, - PRIMITIVES_PAGE, + NUMERIC_PAGE, build_placement_registry, ) from overture.schema.codegen.markdown.pipeline import ( @@ -35,7 +36,7 @@ from pydantic import BaseModel _NUMERIC_NAMES, _GEOMETRY_NAMES = partition_numeric_and_geometry_types( - _system_primitive + _system_numeric, _system_geometric ) _SCHEMA_ROOT = "overture.schema" @@ -75,8 +76,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: @@ -109,18 +110,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/geometry.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 GEOMETRY_PAGE == PurePosixPath("system/geometry.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 dbb77a281..479f98b2f 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 8f89d790f..e0a928ce8 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 801d35aa3..408abcec3 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, uint8 +from overture.schema.system.numeric import float64, uint8 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-system/README.md b/packages/overture-schema-system/README.md index 9733d105f..74eb6da22 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 the domain is 0--255. The numeric 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: ```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 26ebf5085..de9c1f565 100644 --- a/packages/overture-schema-system/src/overture/schema/system/__init__.py +++ b/packages/overture-schema-system/src/overture/schema/system/__init__.py @@ -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 descrie relationships between models based on unique IDs. (*i.e.*, foreign key relationships). - :mod:`string ` String types with built-in validation to conform to @@ -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 82715014f..fae33806b 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..95cc97255 --- /dev/null +++ b/packages/overture-schema-system/src/overture/schema/system/geometric/__init__.py @@ -0,0 +1,25 @@ +""" +Geometric types. + +This module provides geometric primitives 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. + +Geometric primitives 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 100% 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 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 99% 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..f60051014 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 @@ -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, 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/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 0d2685df9..fd7709556 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, From 0301bf7332c04288b3e821ff30c8cfb8faac9e41 Mon Sep 17 00:00:00 2001 From: Seth Fitzsimmons Date: Fri, 10 Jul 2026 10:03:53 -0700 Subject: [PATCH 2/4] [REFACTOR](schema) Drop leftover primitive wording from system docstrings Follow-up to the numeric/geometric split: the system package docstring and the new geometric module docstring still described these types as "primitive types" / "geometric primitives", the exact wording the split was meant to retire. Signed-off-by: Seth Fitzsimmons --- .../src/overture/schema/system/__init__.py | 4 ++-- .../src/overture/schema/system/geometric/__init__.py | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) 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 de9c1f565..616731051 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 ----------- 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 index 95cc97255..fd1ea6518 100644 --- a/packages/overture-schema-system/src/overture/schema/system/geometric/__init__.py +++ b/packages/overture-schema-system/src/overture/schema/system/geometric/__init__.py @@ -1,13 +1,13 @@ """ Geometric types. -This module provides geometric primitives that can be used as fields in Pydantic models but are +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. -Geometric primitives 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. +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 1dfbbdedea14937bcbb6b6b985f5486d6b20b1b5 Mon Sep 17 00:00:00 2001 From: Seth Fitzsimmons Date: Fri, 10 Jul 2026 10:15:19 -0700 Subject: [PATCH 3/4] [REFACTOR](schema) Finish removing primitive wording from system docstrings Commit 0301bf73 left "primitive" in several docstrings after the system.primitive split into numeric and geometric modules. Remove the remaining instances in __init__.py, geometric/geom.py, geometric/bbox.py, and string.py so the term no longer appears anywhere in the package. Signed-off-by: Seth Fitzsimmons --- .../src/overture/schema/system/__init__.py | 2 +- .../src/overture/schema/system/geometric/bbox.py | 10 +++++----- .../src/overture/schema/system/geometric/geom.py | 12 ++++++------ .../src/overture/schema/system/string.py | 6 +++--- 4 files changed, 15 insertions(+), 15 deletions(-) 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 616731051..24682f3c4 100644 --- a/packages/overture-schema-system/src/overture/schema/system/__init__.py +++ b/packages/overture-schema-system/src/overture/schema/system/__init__.py @@ -38,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). diff --git a/packages/overture-schema-system/src/overture/schema/system/geometric/bbox.py b/packages/overture-schema-system/src/overture/schema/system/geometric/bbox.py index c078290c5..5af086be9 100644 --- a/packages/overture-schema-system/src/overture/schema/system/geometric/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/geometric/geom.py b/packages/overture-schema-system/src/overture/schema/system/geometric/geom.py index f60051014..d7d2b0e8e 100644 --- a/packages/overture-schema-system/src/overture/schema/system/geometric/geom.py +++ b/packages/overture-schema-system/src/overture/schema/system/geometric/geom.py @@ -1,5 +1,5 @@ """ -Geometry primitive and geometry type constraint. +Geometry wrapper and geometry type constraint. Use `Geometry` as the type for fields containing geometry values. Use `GeometryTypeConstraint` if you need to constrain allowed types of geometries. @@ -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/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 From 2280da8f386b440a1923373ad7ff2c23d56e4c24 Mon Sep 17 00:00:00 2001 From: Seth Fitzsimmons Date: Fri, 10 Jul 2026 10:22:51 -0700 Subject: [PATCH 4/4] Align geom.py module docstring wording with its class docstring Signed-off-by: Seth Fitzsimmons --- .../src/overture/schema/system/geometric/geom.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/overture-schema-system/src/overture/schema/system/geometric/geom.py b/packages/overture-schema-system/src/overture/schema/system/geometric/geom.py index d7d2b0e8e..b543cbb6f 100644 --- a/packages/overture-schema-system/src/overture/schema/system/geometric/geom.py +++ b/packages/overture-schema-system/src/overture/schema/system/geometric/geom.py @@ -1,5 +1,5 @@ """ -Geometry wrapper 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.