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
20 changes: 18 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.PHONY: default uv-sync clean-pyspark generate-pyspark check test-all test test-only docformat docformat-only doctest doctest-only mypy mypy-only lint-only update-baselines
.PHONY: default uv-sync clean-pyspark generate-pyspark check check-namespace test-all test test-only docformat docformat-only doctest doctest-only mypy mypy-only lint-only update-baselines

TESTMON ?= --testmon

Expand All @@ -23,7 +23,23 @@ generate-pyspark: uv-sync clean-pyspark
@uv run ruff format --quiet $(PYSPARK_EXPRESSIONS) $(PYSPARK_GENERATED_TESTS)

check: uv-sync generate-pyspark
@$(MAKE) -j test-only docformat-only doctest-only lint-only mypy-only
@$(MAKE) -j test-only docformat-only doctest-only lint-only mypy-only check-namespace

# Guard the PEP 420 namespace roots. overture/ and overture/schema/ are
# implicit namespace packages -- no __init__.py -- so every workspace package
# contributes its own leaf under the shared namespace. An __init__.py at either
# root turns that package into a regular package that shadows every other
# distribution's contribution at import time. -path patterns (not shell globs)
# keep this shell-independent and match only the two roots, never the leaves.
check-namespace:
@found=$$(find packages -type f -path '*/src/overture/__init__.py' \
-o -type f -path '*/src/overture/schema/__init__.py'); \
if [ -n "$$found" ]; then \
echo "ERROR: __init__.py at PEP 420 namespace root(s) -- delete these:" >&2; \
echo "$$found" >&2; \
echo "overture/ and overture/schema/ must stay implicit namespace packages." >&2; \
exit 1; \
fi

# test-all is the unconditional full run -- testmon-independent, unlike the
# incremental test/test-only targets -- so data-only changes (golden JSON,
Expand Down
1 change: 1 addition & 0 deletions packages/overture-schema-cli/changelog.d/618.misc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Migrated the build backend from hatchling to uv_build and made `overture.schema` a PEP 420 namespace package.
8 changes: 4 additions & 4 deletions packages/overture-schema-cli/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ overture-schema-common = { workspace = true }
overture-schema-system = { workspace = true }

[build-system]
build-backend = "hatchling.build"
requires = ["hatchling"]
requires = ["uv_build>=0.11.32,<0.13"]
build-backend = "uv_build"

[dependency-groups]
dev = [
Expand All @@ -38,8 +38,8 @@ dev = [
"mypy>=1.17.0",
]

[tool.hatch.build.targets.wheel]
packages = ["src/overture"]
[tool.uv.build-backend]
module-name = "overture.schema.cli"

[project.scripts]
overture-schema = "overture.schema.cli:cli"
1 change: 0 additions & 1 deletion packages/overture-schema-cli/src/overture/__init__.py

This file was deleted.

This file was deleted.

1 change: 1 addition & 0 deletions packages/overture-schema-cli/tests/test_cli_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import pytest
from click.testing import CliRunner
from conftest import build_feature

from overture.schema.cli.commands import cli


Expand Down
3 changes: 2 additions & 1 deletion packages/overture-schema-cli/tests/test_cli_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import yaml
from click.exceptions import UsageError
from conftest import build_feature
from pydantic import BaseModel, ValidationError

from overture.schema.cli.commands import (
_best_fit_model,
_revalidate_undiscriminatable_items,
Expand All @@ -19,7 +21,6 @@
from overture.schema.cli.type_analysis import get_item_index
from overture.schema.cli.types import ValidationErrorDict
from overture.schema.system.discovery import TagSelector
from pydantic import BaseModel, ValidationError


class TestLoadInput:
Expand Down
5 changes: 3 additions & 2 deletions packages/overture-schema-cli/tests/test_data_display.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@
from io import StringIO

from conftest import build_feature
from rich.console import Console
from rich.panel import Panel

from overture.schema.cli.data_display import (
create_feature_display,
extract_feature_data,
format_field_value,
select_context_fields,
)
from rich.console import Console
from rich.panel import Panel


class TestExtractFeatureData:
Expand Down
5 changes: 3 additions & 2 deletions packages/overture-schema-cli/tests/test_error_formatting.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@

import pytest
from click.testing import CliRunner
from pydantic import BaseModel, Field, TypeAdapter, ValidationError
from rich.console import Console

from overture.schema.cli.commands import cli
from overture.schema.cli.error_formatting import (
format_path,
Expand All @@ -14,8 +17,6 @@
)
from overture.schema.cli.type_analysis import introspect_union
from overture.schema.cli.types import ErrorLocation, ValidationErrorDict
from pydantic import BaseModel, Field, TypeAdapter, ValidationError
from rich.console import Console


class TestErrorGrouping:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import pytest
from click.testing import CliRunner
from conftest import build_feature

from overture.schema.cli.commands import cli


Expand Down
1 change: 1 addition & 0 deletions packages/overture-schema-cli/tests/test_resolve_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from unittest.mock import patch

import pytest

from overture.schema.cli.commands import resolve_types
from overture.schema.system.discovery import ModelKey, TagSelector

Expand Down
3 changes: 2 additions & 1 deletion packages/overture-schema-cli/tests/test_type_analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@
from typing import Annotated, Literal

import pytest
from pydantic import BaseModel, Discriminator, Field

from overture.schema.cli.type_analysis import (
StructuralTuple,
create_structural_tuple,
extract_discriminator_path,
get_or_create_structural_tuple,
introspect_union,
)
from pydantic import BaseModel, Discriminator, Field


class TestStructuralTuples:
Expand Down
1 change: 1 addition & 0 deletions packages/overture-schema-codegen/changelog.d/618.misc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Migrated the build backend to uv_build and stopped emitting `__init__.py` in the generated PySpark trees, making them PEP 420 namespace packages.
8 changes: 4 additions & 4 deletions packages/overture-schema-codegen/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[build-system]
build-backend = "hatchling.build"
requires = ["hatchling"]
requires = ["uv_build>=0.11.32,<0.13"]
build-backend = "uv_build"

[project]
dependencies = [
Expand Down Expand Up @@ -42,5 +42,5 @@ test = [
"overture-schema-theme-transportation",
]

[tool.hatch.build.targets.wheel]
packages = ["src/overture"]
[tool.uv.build-backend]
module-name = "overture.schema.codegen"
1 change: 0 additions & 1 deletion packages/overture-schema-codegen/src/overture/__init__.py

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from __future__ import annotations

from collections.abc import Iterable, Sequence
from collections.abc import Sequence
from dataclasses import dataclass
from pathlib import PurePosixPath

Expand Down Expand Up @@ -48,12 +48,10 @@ class GeneratedModule:
class PipelineOutput:
"""PySpark modules emitted by the pipeline, split by output tree.

The source and test trees are written to separate directories and
mirror the same relative layout, so a path is meaningful only
relative to its tree. Splitting at the boundary keeps each tree
self-contained -- in practice the overlap today is just
`__init__.py`, but any path duplicated between trees would be
ambiguous in a single flat list.
Source and test modules write to separate directories
(`--output-dir` and `--test-output-dir`), so they travel as two
lists rather than one. Both trees mirror the same relative layout,
so a path is meaningful only relative to its own tree.
"""

source: list[GeneratedModule]
Expand All @@ -62,21 +60,6 @@ class PipelineOutput:

_OUTPUT_PACKAGE = "overture.schema.pyspark.expressions.generated"

# Dots in `from ...x import y` from a generated test module to reach
# `tests/`: one to leave the file's package, one to leave `generated/`.
# Each additional directory component under `generated/` adds another.
_DOTS_FROM_TEST_TO_TESTS_ROOT = 2


def _support_prefix(directory: PurePosixPath) -> str:
"""Relative-import prefix used by generated test modules to reach `_support`.

Each leading dot climbs one package level; the first two dots step
out of `tests/generated/` to `tests/`, and an extra dot is appended
for every component of *directory* under `generated/`.
"""
return "." * (len(directory.parts) + _DOTS_FROM_TEST_TO_TESTS_ROOT)


def _require_entry_point(spec: ModelSpec) -> str:
"""Return *spec*'s entry point or raise if it's missing."""
Expand Down Expand Up @@ -117,21 +100,6 @@ def _extract_geometry_types(
return tuple(sorted(seen, key=lambda g: g.name))


def _init_modules(paths: Iterable[PurePosixPath]) -> list[GeneratedModule]:
"""Emit empty `__init__.py` for every directory of `paths`.

Includes the output root so the top-level package exists after a
full `rm -rf` of the generated tree.
"""
paths = list(paths)
if not paths:
return []
dirs: set[PurePosixPath] = set()
for path in paths:
dirs.update(path.parents)
return [GeneratedModule(content="", path=d / "__init__.py") for d in sorted(dirs)]


def generate_pyspark_module(spec: ModelSpec) -> GeneratedModule:
"""Generate a PySpark validation module from a model spec.

Expand Down Expand Up @@ -162,16 +130,14 @@ def generate_pyspark_modules(
Returns
-------
PipelineOutput
Source-tree model modules and test-tree modules. Each tree
includes the `__init__.py` files needed for its package layout.
Source-tree model modules and test-tree modules. The generated
tree is PEP 420, so no `__init__.py` files are emitted.
"""
items = [(spec, build_checks(spec)) for spec in model_specs]
source = [_render_module(spec, checks) for spec, checks in items]
test: list[GeneratedModule] = []
for spec, checks in items:
test.extend(_render_test_modules(spec, checks))
source.extend(_init_modules(m.path for m in source))
test.extend(_init_modules(m.path for m in test))
return PipelineOutput(source=source, test=test)


Expand Down Expand Up @@ -232,7 +198,6 @@ def _render_test_modules(
field_checks, model_checks = checks
directory, model_name = _directory_and_model_name(spec)
expression_import = ".".join([_OUTPUT_PACKAGE, *directory.parts, model_name])
support_prefix = _support_prefix(directory)

modules: list[GeneratedModule] = []
for arm, (base_row_sparse, base_row_populated) in _select_arm_rows(spec).items():
Expand All @@ -248,7 +213,6 @@ def _render_test_modules(
arm=arm,
spec=spec,
expression_import=expression_import,
support_prefix=support_prefix,
),
path=directory / f"test_{model_name}{suffix}.py",
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,17 @@ from {{ expression_import }} import (
)
from pyspark.sql import SparkSession

from {{ support_prefix }}_support.harness import (
from _support.harness import (
ValidationResults,
run_validation_pipeline,
)
{% if mutation_imports %}
from {{ support_prefix }}_support.mutations import {{ mutation_imports | join(", ") }}
from _support.mutations import {{ mutation_imports | join(", ") }}
{% endif %}
{% if needs_set_at_path %}
from {{ support_prefix }}_support.helpers import set_at_path
from _support.helpers import set_at_path
{% endif %}
from {{ support_prefix }}_support.scenarios import Scenario
from _support.scenarios import Scenario

BASE_ROW_SPARSE: dict = {{ base_row_sparse }}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,6 @@ def render_test_module(
model_checks: list[ModelCheck],
*,
expression_import: str,
support_prefix: str,
base_row_sparse: dict[str, Any] | None = None,
base_row_populated: dict[str, Any] | None = None,
arm: str | None = None,
Expand Down Expand Up @@ -187,7 +186,6 @@ def render_test_module(
base_row_populated=populated_repr,
scenarios=all_scenarios,
expression_import=expression_import,
support_prefix=support_prefix,
)


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

import pytest
from annotated_types import MinLen
from pydantic import BaseModel, EmailStr, Field, HttpUrl, RootModel

from overture.schema.codegen.extraction.field import LiteralScalar, Primitive
from overture.schema.codegen.extraction.field_walk import terminal_of
from overture.schema.codegen.extraction.model_extraction import extract_model
Expand Down Expand Up @@ -55,7 +57,6 @@
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, RootModel

STR_TYPE = Primitive(base_type="str")

Expand Down
7 changes: 4 additions & 3 deletions packages/overture-schema-codegen/tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
"""Shared pytest fixtures for overture-schema-codegen tests."""

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
from pydantic import BaseModel

import overture.schema.system.geometric as _system_geometric
import overture.schema.system.numeric as _system_numeric
from overture.schema.codegen.extraction.model_extraction import extract_model
from overture.schema.codegen.extraction.numeric_extraction import extract_numerics
from overture.schema.codegen.extraction.specs import RecordSpec
Expand All @@ -17,7 +19,6 @@
)
from overture.schema.system.discovery import discover_models
from overture.schema.system.geometric import GeometryType
from pydantic import BaseModel


def pytest_addoption(parser: pytest.Parser) -> None:
Expand Down
1 change: 1 addition & 0 deletions packages/overture-schema-codegen/tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import pytest
from click.testing import CliRunner

from overture.schema.codegen.cli import cli
from overture.schema.codegen.extraction.specs import RecordSpec

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import re

from annotated_types import Ge, Gt, Interval, Le, Lt, MultipleOf

from overture.schema.codegen.extraction.field_constraints import (
constraint_display_text,
describe_field_constraint,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from enum import Enum

from codegen_test_support import find_member

from overture.schema.codegen.extraction.enum_extraction import extract_enum
from overture.schema.codegen.extraction.specs import EnumMemberSpec, EnumSpec
from overture.schema.system.doc import DocumentedEnum
Expand Down
Loading
Loading