Skip to main content

osdu-python-models

Typed Pydantic v2 models for OSDU data payloads — an opt-in companion to osdu-python-client, mirroring the C# osdu-csharp-schemas library.

Scope. Covers all work-product-component, master-data and dataset entity types in the pinned OSDU snapshot — 221 entity types across 595 schema versions (103 work-product-component + 90 master-data + 28 dataset), plus 132 shared abstract modules pulled in on demand. The generator is data-driven: the scope is the SCOPE_GROUPS list in tools/generate.py, and every type and version is discovered from the snapshot automatically, so a snapshot bump or adding a group needs no other code change. abstract schemas are not listed explicitly — only those reachable from a selected entity's $ref closure are generated.

Why

osdu-python-client leaves the record data block free-form (a dict), matching the canonical os-core-common Map<String, Object> — the right call, because OSDU data is schema-on-read and versioned by kind. But consumers building ingestion or validation logic for a specific kind + version still want types: autocomplete, runtime validation, and self-documenting payloads. This package provides exactly that, without touching the client.

from osdu_models.workproductcomponent.well_log.v1_5_0 import Data, Curve

# Typed authoring — autocomplete + validation
data = Data(
    WellboreID="namespace:master-data--Wellbore:abc:",
    TopMeasuredDepth=1234.5,
    Curves=[Curve(Mnemonic="GR")],
)

# Bridge into the client's free-form `data` — just model_dump(), no client changes
record = {"kind": "osdu:wks:work-product-component--WellLog:1.5.0",
          "acl": ..., "legal": ...,
          "data": data.model_dump(by_alias=True, exclude_none=True)}

Reading is the mirror image: Data.model_validate(record["data"]).

Install

pip install osdu-python-models

Requires Python 3.10–3.14.

or with uv:

uv add osdu-python-models

Models are shipped pre-generated in the published distributions — no codegen step needed to consume them. To build from source instead, see Build & test.

Each tagged version is also attached to its GitHub Release as .whl / .tar.gz assets.

Design

  • Types only the data block. The client owns the envelope (id/kind/acl/legal); this package owns data. The two compose via model_dump() / model_validate().
  • Side-by-side versions. Each published version is its own module (well_log/v1_4_0.py, v1_5_0.py) — no "latest wins", explicit per-kind.
  • Shared abstract modules. OSDU abstract/* building blocks are generated once under osdu_models/abstract/<type>/v<ver>.py; each entity model imports them rather than inlining a private copy. This removes the ~96 % class duplication of a per-entity bundling approach (595 models: ~68,000 → 2,176 class defs) and is what makes scaling to the full schema set viable. Same idea as the C# library's ExternalReferenceCode abstract sharing.
  • String-only constraints stripped off non-string nodes. A few OSDU schemas attach pattern/format to array/integer fields (e.g. AbstractColumnBasedTable.IntegerColumn); the generator drops them so Pydantic v2 doesn't reject otherwise-valid payloads.
  • extra='allow' everywhere. Unknown / forward-compatible fields round-trip untouched (the Pydantic equivalent of C#'s [JsonExtensionData]).
  • String format dropped → plain str. This library types data for lossless round-tripping, not semantic validation. Honouring format would make codegen emit validating/normalising types that defeat that or pull optional deps: date/date-time/time (OSDU payloads carry non-conformant variants a strict parser rejects), email (EmailStr, needs email-validator), uri (AnyUrl, normalises the value). Keeping plain str preserves the input. Same pragmatic choice the C# library makes.
  • Pinned snapshot. schemas/M27.1/ is a frozen copy of the OSDU data-definitions Generated/ schemas (DD v0.30.1, the M27.1 milestone publication; shared with the C# library). Bumping it is an explicit, reviewable change.

Layout

osdu-python-models/
├── schemas/M27.1/             # pinned data-definitions snapshot (abstract + entities)
├── tools/generate.py          # restructures the `data` sub-schemas, runs datamodel-codegen
├── src/osdu_models/            # generated Pydantic models (gitignored, regenerable)
│   ├── abstract/<type>/v<ver>.py          # shared abstract building blocks (generated once)
│   ├── workproductcomponent/<type>/v<ver>.py
│   ├── masterdata/<type>/v<ver>.py        # → class Data, importing the shared abstracts
│   └── dataset/<type>/v<ver>.py           # e.g. dataset/file_generic/v1_1_0.py
├── tests/test_roundtrip.py    # round-trip + typed-access tests vs real OSDU examples (all versions)
└── samples/author_welllog.py  # end-to-end authoring demo (no network)

Build & test

uv venv && uv pip install -e ".[dev]"
uv run python tools/generate.py     # generate models from the pinned snapshot
uv run ruff check tools tests samples  # lint hand-written sources (not generated)
uv run pytest                       # round-trip tests against OSDU example payloads
uv run python samples/author_welllog.py

How it works

OSDU record schemas put the payload under properties.data as an allOf of abstract building blocks (../abstract/*.json) plus inline fields. tools/generate.py uses datamodel-codegen directory mode, which turns cross-file $refs into Python imports:

  1. lifts each entity's data sub-schema (titled Data) and transitively collects the shared abstract/* files it references,
  2. lays both out in a temp tree mirroring the output package structure (every file at the same depth, <pkg>/<snake>/v<ver>.json), cleaning schema quirks and rewriting every $ref to a canonical root-relative path (../../<pkg>/ <snake>/v<ver>.json) so it resolves identically regardless of which file the resolver treats as the base — sidestepping a datamodel-codegen quirk that otherwise resolves a shared schema's nested $refs against the referencing entity's directory,
  3. runs datamodel-codegen once over that tree — emitting each abstract as a shared module and each entity as a Data model that imports them.

Generated code is gitignored — regenerable from the pinned snapshot, never hand-edited.

Contributing

Contributions are welcome — see CONTRIBUTING.md for development setup, the pull-request process, and commit conventions.

Security

To report a security vulnerability, follow the process in SECURITY.md. Do not open a public issue.

License

Licensed under the Apache License 2.0.

Metadata

Release files for osdu-python-models 0.8.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for osdu-python-models 0.8.0
File Size Uploaded
osdu_python_models-0.8.0.tar.gz 636.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for osdu-python-models 0.8.0
File Interpreter ABI Platform
osdu_python_models-0.8.0-py3-none-any.whl Python 3 none any Details

Total release size: 2.4 MB

Release files / osdu_python_models-0.8.0.tar.gz

Download URL osdu_python_models-0.8.0.tar.gz
Size 636.3 kB
Tags Source
SHA-256 checksum
How to use checksums
af8d911bd1328442391c1d37958e8634d59c2f964b2a53ebfa37cee4bd238e58
BLAKE2b-256 checksum
How to use checksums
7227d5b23e79c2e47c3d9680a362102d2b12a09fbca2a7f606ab63d62a29f5df
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 8, 2026.

Transparency log

Release files / osdu_python_models-0.8.0-py3-none-any.whl

Download URL osdu_python_models-0.8.0-py3-none-any.whl
Size 1.7 MB
Tags Python 3
SHA-256 checksum
How to use checksums
c987c92d09acbdc623572d524954dc3bd718fc9237a06ad6ebcf3ab2c5da758b
BLAKE2b-256 checksum
How to use checksums
8983ee83747ed84a6da2ace0b873e8a5cfee47707e6f9481a3c0077277cd34aa
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 8, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.8.0 This release

2 release files

0.7.1

2 release files

0.7.0

2 release files

0.6.0

2 release files

0.5.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page