Skip to content

Commit 4daa0e8

Browse files
mojodnavcschapp
authored andcommitted
refactor: rename primitive → numeric in extraction layer
Extraction-layer spec describes numeric types exclusively (bounds, float_bits). Frees 'primitive' for the broader system-level taxonomy. Renames: - PrimitiveSpec → NumericSpec - primitive_extraction.py → numeric_extraction.py - extract_primitives → extract_numerics - partition_primitive_and_geometry_names → partition_numeric_and_geometry_types partition_numeric_and_geometry_types moved from numeric_extraction to pipeline — it discovers both numeric and geometry types, so it didn't belong in a module scoped to numeric extraction. Renderer function names and output constants unchanged — those describe rendered output, not the extraction concept. Signed-off-by: Seth Fitzsimmons <sethfitz@amazon.com>
1 parent a8cfb2f commit 4daa0e8

File tree

13 files changed

+96
-93
lines changed

13 files changed

+96
-93
lines changed

packages/overture-schema-codegen/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ the same pipeline.
5555
function -- a single iterative loop that peels NewType, Annotated, Union, and container
5656
wrappers, accumulating constraints tagged with the NewType that contributed them.
5757
Domain-specific extractors (`model_extraction`, `union_extraction`, `enum_extraction`,
58-
`newtype_extraction`, `primitive_extraction`) call `analyze_type()` for field types and
58+
`newtype_extraction`, `numeric_extraction`) call `analyze_type()` for field types and
5959
produce spec dataclasses.
6060

6161
**Output Layout** determines what artifacts to generate and where they go. Supplementary

packages/overture-schema-codegen/docs/design.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ Extraction is split by entity kind:
144144
- `extraction/enum_extraction.py`: Enum class -> `EnumSpec`
145145
- `extraction/newtype_extraction.py`: NewType -> `NewTypeSpec`
146146
- `extraction/union_extraction.py`: Discriminated union alias -> `UnionSpec`
147-
- `extraction/primitive_extraction.py`: Numeric primitives -> `PrimitiveSpec`
147+
- `extraction/numeric_extraction.py`: Numeric types -> `NumericSpec`
148148

149149
Each calls `analyze_type()` for field types. Tree expansion (`expand_model_tree()`)
150150
walks MODEL-kind fields to populate nested model references, with a shared cache and

packages/overture-schema-codegen/docs/walkthrough.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -230,11 +230,11 @@ dispatch, and example loading all operate on `FeatureSpec` without knowing which
230230
concrete type they hold.
231231

232232
**EnumSpec** and **EnumMemberSpec** serve enums. **NewTypeSpec** serves NewTypes.
233-
**PrimitiveSpec** serves numeric primitives with an `Interval` for bounds and optional
233+
**NumericSpec** serves numeric primitives with an `Interval` for bounds and optional
234234
`float_bits`.
235235

236236
**SupplementarySpec** is the union type alias `EnumSpec | NewTypeSpec | ModelSpec` --
237-
the set of non-feature types that need their own output pages. `PrimitiveSpec` and
237+
the set of non-feature types that need their own output pages. `NumericSpec` and
238238
geometry types are excluded because they render on aggregate pages rather than
239239
individual ones.
240240

@@ -363,10 +363,10 @@ member for single-value `Literal` fields on the discriminator.
363363

364364
### Primitive extraction
365365

366-
`partition_primitive_and_geometry_names` reads a module's `__all__` exports. NewType
366+
`partition_numeric_and_geometry_types` reads a module's `__all__` exports. NewType
367367
exports are numeric primitives; non-constraint class exports are geometry types.
368368

369-
`extract_primitives` builds `PrimitiveSpec` objects. For each primitive name it resolves
369+
`extract_numerics` builds `NumericSpec` objects. For each primitive name it resolves
370370
the object from the module, calls `extract_newtype` for the type analysis, then extracts
371371
numeric bounds from constraints. `extract_numeric_bounds` scans constraint objects for
372372
`ge`/`gt`/`le`/`lt` attributes and packs them into an `Interval`.
@@ -713,7 +713,7 @@ two NewType layers and an `Annotated` layer, producing a `TypeInfo` with
713713
`FieldSpec.model` references. The shared cache ensures sub-models referenced by multiple
714714
features (like `Sources`) extract once. Union-kind fields skip inline expansion.
715715

716-
**Layout.** `partition_primitive_and_geometry_names` reads the system module's exports.
716+
**Layout.** `partition_numeric_and_geometry_types` reads the system module's exports.
717717
`collect_all_supplementary_types` walks Segment's expanded fields and discovers
718718
referenced enums (like `Subtype`), semantic NewTypes (like `Id`, `Sources`), and
719719
sub-models. The walk follows `FieldSpec.model` references down the tree, and for

packages/overture-schema-codegen/src/overture/schema/codegen/extraction/field_constraints.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
# annotated_types constraint attribute (Ge, Gt, Le, Lt, Interval) to its
2929
# mathematical symbol for prose rendering.
3030
#
31-
# primitive_extraction.py has its own _BOUND_ATTRS for numeric extraction. The
31+
# numeric_extraction.py has its own _BOUND_ATTRS for numeric extraction. The
3232
# duplication is deliberate: these modules use the same attribute names for
3333
# unrelated purposes (display formatting vs. numeric bound extraction), and
3434
# coupling them for four string literals adds a dependency without value.

packages/overture-schema-codegen/src/overture/schema/codegen/extraction/primitive_extraction.py renamed to packages/overture-schema-codegen/src/overture/schema/codegen/extraction/numeric_extraction.py

Lines changed: 12 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,22 @@
1-
"""Primitive extraction and partitioning."""
1+
"""Numeric type extraction."""
22

33
from annotated_types import Interval
44

55
from .docstring import first_docstring_line
66
from .newtype_extraction import extract_newtype
7-
from .specs import PrimitiveSpec, TypeIdentity
8-
from .type_analyzer import TypeInfo, is_newtype
7+
from .specs import NumericSpec, TypeIdentity
8+
from .type_analyzer import TypeInfo
99

1010
__all__ = [
1111
"extract_numeric_bounds",
12-
"extract_primitives",
13-
"partition_primitive_and_geometry_names",
12+
"extract_numerics",
1413
]
1514

1615

1716
# Bound attribute names on annotated_types constraint objects (Ge, Gt, Le,
1817
# Lt, Interval) used for numeric bound extraction.
1918
#
20-
# field_constraint_description.py has its own _BOUND_OPS for display formatting.
19+
# field_constraints.py has its own _BOUND_OPS for display formatting.
2120
# The duplication is deliberate: these modules use the same attribute names
2221
# for unrelated purposes (numeric extraction vs. prose rendering), and
2322
# coupling them for four string literals adds a dependency without value.
@@ -41,18 +40,18 @@ def extract_numeric_bounds(type_info: TypeInfo) -> Interval:
4140
return Interval(**found)
4241

4342

44-
def extract_primitives(
45-
primitive_ids: list[TypeIdentity],
46-
) -> list[PrimitiveSpec]:
47-
"""Extract specifications for numeric primitive types."""
48-
specs: list[PrimitiveSpec] = []
49-
for tid in primitive_ids:
43+
def extract_numerics(
44+
numeric_ids: list[TypeIdentity],
45+
) -> list[NumericSpec]:
46+
"""Extract specifications for numeric types."""
47+
specs: list[NumericSpec] = []
48+
for tid in numeric_ids:
5049
newtype_spec = extract_newtype(tid.obj)
5150
bounds = extract_numeric_bounds(newtype_spec.type_info)
5251
description = first_docstring_line(getattr(tid.obj, "__doc__", None))
5352
float_bits = _extract_float_bits(tid.name)
5453
specs.append(
55-
PrimitiveSpec(
54+
NumericSpec(
5655
name=tid.name,
5756
description=description,
5857
bounds=bounds,
@@ -71,25 +70,3 @@ def extract_primitives(
7170
def _extract_float_bits(name: str) -> int | None:
7271
"""Extract bit width from a float type name like 'float32'."""
7372
return _FLOAT_BITS.get(name)
74-
75-
76-
def partition_primitive_and_geometry_names(
77-
primitive_module: object,
78-
) -> tuple[list[TypeIdentity], list[TypeIdentity]]:
79-
"""Discover primitive and geometry types from a module's exports.
80-
81-
NewType exports are numeric primitives.
82-
Non-constraint class/enum exports are geometry types.
83-
"""
84-
module_all: list[str] = getattr(primitive_module, "__all__", [])
85-
primitives: list[TypeIdentity] = []
86-
geometries: list[TypeIdentity] = []
87-
88-
for name in module_all:
89-
obj = getattr(primitive_module, name)
90-
if is_newtype(obj):
91-
primitives.append(TypeIdentity(obj, name))
92-
elif isinstance(obj, type) and not name.endswith("Constraint"):
93-
geometries.append(TypeIdentity(obj, name))
94-
95-
return primitives, geometries

packages/overture-schema-codegen/src/overture/schema/codegen/extraction/specs.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
"FieldSpec",
2222
"ModelSpec",
2323
"NewTypeSpec",
24-
"PrimitiveSpec",
24+
"NumericSpec",
2525
"PydanticTypeSpec",
2626
"SupplementarySpec",
2727
"TypeIdentity",
@@ -189,8 +189,8 @@ class NewTypeSpec(_SourceTypeIdentityMixin):
189189

190190

191191
@dataclass
192-
class PrimitiveSpec:
193-
"""Extracted specification for a numeric primitive type."""
192+
class NumericSpec:
193+
"""Extracted specification for a numeric type."""
194194

195195
name: str
196196
description: str | None
@@ -219,7 +219,7 @@ def docs_url(self) -> str:
219219
SupplementarySpec = EnumSpec | NewTypeSpec | ModelSpec | PydanticTypeSpec
220220
"""Non-feature types referenced by feature models.
221221
222-
Excludes PrimitiveSpec and geometry types, which are extracted
222+
Excludes NumericSpec and geometry types, which are extracted
223223
separately via dedicated functions.
224224
"""
225225

packages/overture-schema-codegen/src/overture/schema/codegen/markdown/path_assignment.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
def build_placement_registry(
3232
feature_specs: Sequence[FeatureSpec],
3333
all_specs: dict[TypeIdentity, SupplementarySpec],
34-
primitive_names: list[TypeIdentity],
34+
numeric_names: list[TypeIdentity],
3535
geometry_names: list[TypeIdentity],
3636
schema_root: str,
3737
) -> dict[TypeIdentity, PurePosixPath]:
@@ -41,7 +41,7 @@ def build_placement_registry(
4141
the source Python module path relative to schema_root.
4242
"""
4343
registry: dict[TypeIdentity, PurePosixPath] = _aggregate_page_entries(
44-
primitive_names, geometry_names
44+
numeric_names, geometry_names
4545
)
4646

4747
feature_dirs: set[PurePosixPath] = set()
@@ -81,12 +81,12 @@ def resolve_output_path(
8181

8282

8383
def _aggregate_page_entries(
84-
primitive_names: list[TypeIdentity],
84+
numeric_names: list[TypeIdentity],
8585
geometry_names: list[TypeIdentity],
8686
) -> dict[TypeIdentity, PurePosixPath]:
8787
"""Pre-populate registry entries for types documented on aggregate pages."""
8888
entries: dict[TypeIdentity, PurePosixPath] = dict.fromkeys(
89-
primitive_names, PRIMITIVES_PAGE
89+
numeric_names, PRIMITIVES_PAGE
9090
)
9191
entries.update(dict.fromkeys(geometry_names, GEOMETRY_PAGE))
9292
return entries

packages/overture-schema-codegen/src/overture/schema/codegen/markdown/pipeline.py

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,7 @@
1515

1616
from ..extraction.examples import ExampleRecord, load_examples
1717
from ..extraction.model_extraction import expand_model_tree
18-
from ..extraction.primitive_extraction import (
19-
extract_primitives,
20-
partition_primitive_and_geometry_names,
21-
)
18+
from ..extraction.numeric_extraction import extract_numerics
2219
from ..extraction.specs import (
2320
EnumSpec,
2421
FeatureSpec,
@@ -29,6 +26,7 @@
2926
TypeIdentity,
3027
UnionSpec,
3128
)
29+
from ..extraction.type_analyzer import is_newtype
3230
from ..layout.type_collection import collect_all_supplementary_types
3331
from .link_computation import LinkContext
3432
from .path_assignment import (
@@ -47,7 +45,11 @@
4745
)
4846
from .reverse_references import UsedByEntry, compute_reverse_references
4947

50-
__all__ = ["RenderedPage", "generate_markdown_pages"]
48+
__all__ = [
49+
"RenderedPage",
50+
"generate_markdown_pages",
51+
"partition_numeric_and_geometry_types",
52+
]
5153

5254

5355
@dataclass(frozen=True, slots=True)
@@ -109,6 +111,28 @@ def _render_supplement(
109111
return RenderedPage(content=content, path=output_path)
110112

111113

114+
def partition_numeric_and_geometry_types(
115+
types_module: object,
116+
) -> tuple[list[TypeIdentity], list[TypeIdentity]]:
117+
"""Discover numeric and geometry types from a module's exports.
118+
119+
NewType exports are numeric types.
120+
Non-constraint class/enum exports are geometry types.
121+
"""
122+
module_all: list[str] = getattr(types_module, "__all__", [])
123+
numerics: list[TypeIdentity] = []
124+
geometries: list[TypeIdentity] = []
125+
126+
for name in module_all:
127+
obj = getattr(types_module, name)
128+
if is_newtype(obj):
129+
numerics.append(TypeIdentity(obj, name))
130+
elif isinstance(obj, type) and not name.endswith("Constraint"):
131+
geometries.append(TypeIdentity(obj, name))
132+
133+
return numerics, geometries
134+
135+
112136
def generate_markdown_pages(
113137
feature_specs: Sequence[FeatureSpec],
114138
schema_root: str,
@@ -123,12 +147,12 @@ def generate_markdown_pages(
123147
for spec in feature_specs:
124148
expand_model_tree(spec, cache)
125149

126-
primitive_names, geometry_names = partition_primitive_and_geometry_names(
150+
numeric_names, geometry_names = partition_numeric_and_geometry_types(
127151
_system_primitive
128152
)
129153
all_specs = collect_all_supplementary_types(feature_specs)
130154
registry = build_placement_registry(
131-
feature_specs, all_specs, primitive_names, geometry_names, schema_root
155+
feature_specs, all_specs, numeric_names, geometry_names, schema_root
132156
)
133157

134158
reverse_refs = compute_reverse_references(feature_specs, all_specs)
@@ -148,7 +172,7 @@ def generate_markdown_pages(
148172

149173
pages.append(
150174
RenderedPage(
151-
content=render_primitives_from_specs(extract_primitives(primitive_names)),
175+
content=render_primitives_from_specs(extract_numerics(numeric_names)),
152176
path=PRIMITIVES_PAGE,
153177
)
154178
)

packages/overture-schema-codegen/src/overture/schema/codegen/markdown/renderer.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
FieldSpec,
2424
ModelSpec,
2525
NewTypeSpec,
26-
PrimitiveSpec,
26+
NumericSpec,
2727
PydanticTypeSpec,
2828
TypeIdentity,
2929
UnionSpec,
@@ -587,8 +587,8 @@ def _bit_width_key(name: str) -> tuple[str, int]:
587587
return (prefix, int(digits) if digits else 0)
588588

589589

590-
def render_primitives_from_specs(specs: list[PrimitiveSpec]) -> str:
591-
"""Render the primitives.md page from pre-extracted PrimitiveSpecs."""
590+
def render_primitives_from_specs(specs: list[NumericSpec]) -> str:
591+
"""Render the primitives.md page from pre-extracted NumericSpecs."""
592592
template = _get_jinja_env().get_template("primitives.md.jinja2")
593593

594594
signed_ints: list[dict[str, str | None]] = []

packages/overture-schema-codegen/tests/conftest.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@
55
from click.testing import CliRunner
66
from codegen_test_support import find_model_class
77
from overture.schema.codegen.extraction.model_extraction import extract_model
8-
from overture.schema.codegen.extraction.primitive_extraction import (
9-
extract_primitives,
10-
partition_primitive_and_geometry_names,
11-
)
8+
from overture.schema.codegen.extraction.numeric_extraction import extract_numerics
129
from overture.schema.codegen.extraction.specs import ModelSpec
10+
from overture.schema.codegen.markdown.pipeline import (
11+
partition_numeric_and_geometry_types,
12+
)
1313
from overture.schema.codegen.markdown.renderer import (
1414
render_geometry_from_values,
1515
render_primitives_from_specs,
@@ -72,8 +72,8 @@ def division_class(all_discovered_models: dict) -> type[BaseModel]:
7272
@pytest.fixture(scope="module")
7373
def primitives_markdown() -> str:
7474
"""Render the primitives.md page from the system primitive module."""
75-
primitive_names, _ = partition_primitive_and_geometry_names(_system_primitive)
76-
return render_primitives_from_specs(extract_primitives(primitive_names))
75+
numeric_names, _ = partition_numeric_and_geometry_types(_system_primitive)
76+
return render_primitives_from_specs(extract_numerics(numeric_names))
7777

7878

7979
@pytest.fixture(scope="module")

0 commit comments

Comments
 (0)