Skip to content

Commit fe0e69e

Browse files
sethfitzvcschapp
authored andcommitted
docs(system,core): write package READMEs
System README: document Feature, primitive types, string types, field constraints, model constraints, references, and the Also Included section (Optionality, DocumentedEnum, Metadata, JSON Schema). Core README: document OvertureFeature, scoping (with scope table), names, sources, cartography, and supplementary modules (types, units, discovery). Pydantic guide: correct import paths and package descriptions for the core/system split. Fill in DocumentedEnum section that was stubbed as TODO. Signed-off-by: Seth Fitzsimmons <sethfitz@amazon.com>
1 parent ce6584f commit fe0e69e

4 files changed

Lines changed: 211 additions & 148 deletions

File tree

PYDANTIC_GUIDE.md

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,8 @@ from overture.schema.system.string import (
5454
NoWhitespaceString,
5555
StrippedString,
5656
)
57-
from overture.schema.core.types import (
58-
ConfidenceScore,
59-
LanguageTag,
60-
)
57+
from overture.schema.core.types import ConfidenceScore
58+
from overture.schema.system.string import LanguageTag
6159

6260
# Numeric primitives (use these instead of int/float)
6361
from overture.schema.system.primitive import (
@@ -182,7 +180,7 @@ from typing import Literal
182180
from overture.schema.core import OvertureFeature
183181
from overture.schema.core.models import Stacked
184182
from overture.schema.core.names import Named
185-
from overture.schema.system.primitives import float64
183+
from overture.schema.system.primitive import float64
186184

187185
class Building(OvertureFeature[Literal["buildings"], Literal["building"]], Named, Stacked):
188186
# Gets fields from Feature: id, theme, type, geometry, etc.
@@ -506,18 +504,34 @@ class Building(OvertureFeature):
506504

507505
Add documentation to describe what the enum and its values mean. In Python, you do this with **docstrings** - text enclosed in triple quotes `"""` that describes what something does:
508506

509-
TODO: DocumentedEnum
507+
Use `DocumentedEnum` from `overture.schema.system.doc` when enum members need their own descriptions for code generation and documentation tooling. Each member takes a `(value, description)` tuple:
510508

511509
```python
512-
class VehicleType(str, Enum):
510+
from overture.schema.system.doc import DocumentedEnum
511+
512+
class VehicleType(str, DocumentedEnum):
513513
"""Types of vehicles for transportation."""
514514

515-
CAR = "car" # Standard passenger vehicle
516-
TRUCK = "truck" # Commercial freight vehicle
517-
BICYCLE = "bicycle" # Human-powered two-wheeler
518-
MOTORCYCLE = "motorcycle" # Motorized two-wheeler
515+
CAR = ("car", "Standard passenger vehicle")
516+
TRUCK = ("truck", "Commercial freight vehicle")
517+
BICYCLE = ("bicycle", "Human-powered two-wheeler")
518+
MOTORCYCLE = ("motorcycle", "Motorized two-wheeler")
519519
```
520520

521+
Members without descriptions use the plain value form -- documentation is optional per-member:
522+
523+
```python
524+
class ConnectionState(str, DocumentedEnum):
525+
CONNECTED = "connected"
526+
DISCONNECTED = "disconnected"
527+
QUIESCING = (
528+
"quiescing",
529+
"Gracefully shutting down, rejecting new requests but completing existing ones",
530+
)
531+
```
532+
533+
Use `DocumentedEnum` over plain `str, Enum` when the enum members' semantics aren't obvious from their names and downstream tools (code generators, documentation renderers) need access to member-level descriptions. Use plain `str, Enum` for self-explanatory values.
534+
521535
#### Why str, Enum?
522536

523537
Inheriting from `str, Enum` makes enum values work as both enums and strings, which is useful for JSON serialization and compatibility.
@@ -560,7 +574,7 @@ class DivisionArea(OvertureFeature[Literal["divisions"], Literal["division_area"
560574
] = None
561575
```
562576

563-
**Available relationship types (see [Relationship](packages/overture-schema-core/src/overture/schema/core/ref.py)):**
577+
**Available relationship types (see [Relationship](packages/overture-schema-system/src/overture/schema/system/ref/ref.py)):**
564578

565579
- **`BELONGS_TO`**: The referencing feature belongs to the referenced feature (division area belongs to division)
566580
- **`CONNECTS_TO`**: The referencing feature connects to the referenced feature (segment connects to connector)
@@ -627,7 +641,7 @@ class Building(OvertureFeature[Literal["buildings"], Literal["building"]]):
627641

628642
#### Best Practices
629643

630-
**1. Always Use Reference Annotations**
644+
##### Always Use Reference Annotations
631645

632646
Include `Reference` annotations for semantic clarity and documentation:
633647

@@ -643,7 +657,7 @@ division_id: Annotated[
643657
division_id: Id
644658
```
645659

646-
**2. Choose the Right Pattern**
660+
##### Choose the Right Pattern
647661

648662
- **Simple relationships** → Direct references (foreign keys)
649663
- **Relationships with metadata** → Separate association features
@@ -938,7 +952,7 @@ Organize code by scope and avoid circular imports:
938952

939953
**Cross-theme shared**: `overture-schema-core` package
940954

941-
- Used by multiple themes (e.g., `LanguageTag`, `CountryCode`, `OvertureFeature`)
955+
- Used by multiple themes (e.g., `OvertureFeature`, `Names`, `Sources`, `Scope`)
942956

943957
**Theme-level shared**: Theme package root (e.g., `overture-schema-transportation-theme/src/overture/schema/transportation/`)
944958

@@ -1110,7 +1124,7 @@ JSON Schema containers become **mixin classes** in Pydantic that you inherit fro
11101124
```python models.py
11111125
from typing import Annotated
11121126
from pydantic import BaseModel, Field
1113-
from overture.schema.model_constraints import no_extra
1127+
from overture.schema.system.model_constraint import no_extra_fields
11141128
from overture.schema.system.primitive import int8, float64
11151129
11161130
@no_extra_fields

README.pydantic.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,11 @@ This workspace contains the following packages:
8888

8989
- **`overture-schema`** - Main entrypoint package that aggregates all types for
9090
convenient usage
91-
- **`overture-schema-core`** - Base classes, geometry models, and common structures
92-
shared across all themes
93-
- **`overture-schema-system`** - Foundational system of primitive types and constraints
91+
- **`overture-schema-core`** - Overture-specific models shared across themes: base
92+
feature class, scoping framework, names, sources, and cartographic hints
93+
- **`overture-schema-system`** - Portable primitive types, constraints, and a
94+
GeoJSON-aware base model for building Pydantic schemas that serialize to
95+
JSON, Parquet, and Spark
9496

9597
### Theme Packages
9698

Lines changed: 59 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -1,166 +1,97 @@
11
# Overture Schema Core
22

3-
Core Pydantic models and base classes for Overture Maps schemas, providing foundational types, geometry handling, and a comprehensive scoping system for conditional rule application.
3+
Shared models and conventions for building Overture Maps feature types. Defines the base feature class all themes extend, a scoping framework for expressing conditional values (this speed limit applies *here*, *then*, to *these vehicles*), and common structures for names, sources, and cartographic hints.
44

55
## Installation
66

77
```bash
88
pip install overture-schema-core
99
```
1010

11-
## Key Components
11+
## OvertureFeature
1212

13-
- **Base Classes**: Extensible base models for Overture Maps features
14-
- **Geometry Types**: WKB geometry type hints and utilities
15-
- **Common Structures**: Shared models used across all themes
16-
- **Primitive Data Types**: Validated primitive types with multi-target serialization support
17-
- **Scoping System**: Flexible conditional rule application framework
18-
19-
## Enhanced Primitive Types
20-
21-
The enhanced primitive types system provides validated primitive types with automatic
22-
constraint checking and multi-target serialization support. This enables consistent type
23-
definitions that can generate appropriate representations for different targets (Spark,
24-
Parquet, etc.).
25-
26-
### Available Types
27-
28-
Built-in Python primitive types (`str`, `int`, `float`, `bool`, `list`, etc.) are
29-
automatically mapped.
30-
31-
We also provide the following additional types:
32-
33-
#### Integer Types
34-
35-
- **`uint8`**: 8-bit unsigned integer (0-255)
36-
- **`uint16`**: 16-bit unsigned integer (0-65535)
37-
- **`uint32`**: 32-bit unsigned integer (0-4294967295)
38-
- **`int8`**: 8-bit signed integer (-128 to 127)
39-
- **`int32`**: 32-bit signed integer (-2³¹ to 2³¹-1)
40-
- **`int64`**: 64-bit signed integer (-2⁶³ to 2⁶³-1)
41-
42-
#### Floating Point Types
43-
44-
- **`float32`**: 32-bit floating point number
45-
- **`float64`**: 64-bit floating point number
46-
47-
### Basic Usage
13+
Every Overture feature type inherits from `OvertureFeature`, which extends `system.Feature` with the fields present on all Overture data: `id`, `theme`, `type`, `version`, `geometry`, and `sources`.
4814

4915
```python
50-
from pydantic import BaseModel, Field
51-
from overture.schema.core.primitives import (
52-
uint8, uint32, float32
53-
)
54-
55-
class Building(BaseModel):
56-
"""Building feature with specific primitive data types."""
57-
58-
height: float32 | None = Field(
59-
None,
60-
description="Height of building in meters"
61-
)
62-
63-
num_floors: uint8 | None = Field(
64-
None,
65-
description="Number of floors in building"
66-
)
67-
68-
area: uint32 | None = Field(
69-
None,
70-
description="Floor area in square meters"
71-
)
16+
from typing import Literal
17+
from overture.schema.core import OvertureFeature
18+
19+
class Park(OvertureFeature[Literal["places"], Literal["park"]]):
20+
area_hectares: float | None = None
7221
```
7322

74-
### Automatic Validation
23+
## Scoping
7524

76-
Enhanced primitive types automatically validate constraints:
25+
Many Overture values only apply under specific conditions -- a speed limit that holds during rush hour, along a sub-segment, in the forward direction. The `@scoped` decorator adds conditional fields to any Pydantic model:
7726

7827
```python
79-
# Valid values
80-
building = Building(height=45.5, num_floors=12, area=2500)
28+
from pydantic import BaseModel
29+
from overture.schema.core.scoping import Scope, scoped
30+
from overture.schema.system.primitive import float32
8131

82-
# Invalid values raise ValidationError
83-
Building(num_floors=256) # Error: 256 > UInt8 maximum (255)
84-
Building(num_floors=-1) # Error: -1 < UInt8 minimum (0)
32+
@scoped(Scope.GEOMETRIC_RANGE, Scope.TEMPORAL)
33+
class SpeedLimit(BaseModel):
34+
max_speed: float32
8535
```
8636

87-
### Type Safety
37+
This produces a model with `between` (geometric range) and `when.during` (temporal) fields, both optional. The full set of scopes and the fields they inject:
8838

89-
The enhanced primitive types provide strong type safety guarantees at both static and
90-
runtime levels:
39+
| Scope | Field |
40+
|----------------------------|-------------------|
41+
| `Scope.GEOMETRIC_POSITION` | `at` |
42+
| `Scope.GEOMETRIC_RANGE` | `between` |
43+
| `Scope.HEADING` | `when.heading` |
44+
| `Scope.TEMPORAL` | `when.during` |
45+
| `Scope.TRAVEL_MODE` | `when.mode` |
46+
| `Scope.PURPOSE_OF_USE` | `when.using` |
47+
| `Scope.RECOGNIZED_STATUS` | `when.recognized` |
48+
| `Scope.SIDE` | `side` |
49+
| `Scope.VEHICLE` | `when.vehicle` |
9150

92-
**Static Type Checking**: mypy can distinguish between different primitive types,
93-
*preventing common errors:
51+
Scopes are optional by default. Make them mandatory via `required`:
9452

9553
```python
96-
from overture.schema.core.primitives import uint8, uint32
54+
@scoped(Scope.TEMPORAL, required=(Scope.GEOMETRIC_POSITION, Scope.HEADING))
55+
class TrafficSignal(BaseModel):
56+
signal_type: str
57+
```
9758

98-
def process_floor_count(floors: uint8) -> str:
99-
return f"Building has {floors} floors"
59+
## Names
10060

101-
def process_area(area: uint32) -> str:
102-
return f"Area: {area} sq meters"
61+
Multilingual naming with support for common names, name rules (official, alternate, short variants), and scoping by geometric range, side, or political perspective. Mix `Named` into a feature type to give it a `names` field:
10362

104-
# Type checker prevents mixing incompatible types
105-
floors: uint8 = 12
106-
area: uint32 = 2500
63+
```python
64+
from typing import Literal
65+
from overture.schema.core import OvertureFeature
66+
from overture.schema.core.names import Named
10767

108-
process_floor_count(area) # mypy error: Expected UInt8, got UInt32
109-
process_area(floors) # mypy error: Expected UInt32, got UInt8
68+
class Lake(OvertureFeature[Literal["base"], Literal["water"]], Named):
69+
pass # inherits names: Names | None from Named
11070
```
11171

72+
Name rules support geometric range and side scoping for cases like a street whose name changes partway along or differs on each side. `NameRule` variants: `common`, `official`, `alternate`, `short`.
11273

113-
### Examples
74+
## Sources
11475

115-
#### Temporal Speed Limit
116-
117-
```yaml
118-
speed_limits:
119-
- between: [0, 1]
120-
max_speed: {value: 30, unit: km/h}
121-
when:
122-
during: "Mo-Fr 07:00-09:00,17:00-19:00" # Rush hours only
123-
```
76+
Source attribution tracking. Each `SourceItem` identifies which dataset a feature or property came from, with optional license, record ID, update time, and confidence score. Source items support geometric range scoping for per-segment attribution.
12477

125-
#### Vehicle-Specific Access Restriction
126-
127-
```yaml
128-
access_restrictions:
129-
- between: [0.2, 0.8]
130-
access_type: denied
131-
when:
132-
vehicle:
133-
- dimension: weight
134-
comparison: greater_than
135-
value: 7.5
136-
unit: t
137-
```
138-
139-
#### Multi-Dimensional Scoping
140-
141-
```yaml
142-
access_restrictions:
143-
- between: [0, 1]
144-
access_type: denied
145-
when:
146-
mode: [bus]
147-
during: "Mo-Fr 15:00-18:00"
148-
heading: forward
149-
using: [to_deliver]
78+
```python
79+
from overture.schema.core.sources import SourceItem
80+
81+
sources = [
82+
SourceItem(property="", dataset="OpenStreetMap"),
83+
SourceItem(property="/geometry", dataset="Microsoft ML Buildings"),
84+
# first 30% of the segment's geometry came from a different source
85+
SourceItem(property="/geometry", dataset="County GIS", between=[0, 0.3]),
86+
]
15087
```
15188

152-
### Design Principles
153-
154-
1. **Composability**: Mix-in design allows combining only needed scoping dimensions
155-
2. **Reusability**: Base scope classes work across all rule types and themes
156-
3. **Extensibility**: Easy to add new scoping dimensions or modify existing ones
157-
4. **Type Safety**: Full Pydantic validation for all scoping conditions
158-
5. **Linear Reference Integration**: Seamless integration with geometric positioning
89+
## Cartography
15990

160-
### Rule Complexity Patterns
91+
Rendering hints for map-making: `prominence` (1--100 significance scale), `min_zoom`/`max_zoom` (tile zoom bounds), and `sort_key` (draw order). Mix `CartographicallyHinted` into a model to add a `cartography` field.
16192

162-
- **Simple Rules** (flags, dimensions): Geometric scoping only
163-
- **Complex Rules** (speed limits, access): Geometric + conditional scoping
164-
- **Transition Rules**: Full scoping including directional constraints
93+
## Also Included
16594

166-
This scoping system provides the foundation for precise, flexible rule specification across all Overture Maps transportation features.
95+
- **Types** -- domain-specific aliases built on system primitives: `ConfidenceScore` (0.0--1.0), `Level` (z-order), `FeatureVersion`.
96+
- **Units** -- measurement enumerations: `SpeedUnit`, `LengthUnit`, `WeightUnit`.
97+
- **Discovery** -- entry-point-based model registry. Theme packages register models via `overture.models` entry points; `discover_models()` resolves them at runtime.

0 commit comments

Comments
 (0)