Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 13 additions & 13 deletions PYDANTIC_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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):
Expand Down Expand Up @@ -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."""
Expand Down Expand Up @@ -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."""
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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."""
Expand Down Expand Up @@ -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"]]):
Expand Down Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions README.pydantic.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion packages/overture-schema-codegen/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion packages/overture-schema-codegen/docs/design.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
28 changes: 15 additions & 13 deletions packages/overture-schema-codegen/docs/walkthrough.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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.

Expand All @@ -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.
Expand Down Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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


Expand Down
Loading