Typed Pydantic models for OSDU data payloads — opt-in companion to osdu-python-client
Project description
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-dataanddatasetentity types in the pinned OSDU snapshot — 194 entity types across 551 schema versions (93 work-product-component + 73 master-data + 28 dataset), plus 128 sharedabstractmodules pulled in on demand. The generator is data-driven: the scope is theSCOPE_GROUPSlist intools/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.abstractschemas are not listed explicitly — only those reachable from a selected entity's$refclosure 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.gzassets.
Design
- Types only the
datablock. The client owns the envelope (id/kind/acl/legal); this package ownsdata. The two compose viamodel_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 underosdu_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 (551 models: ~65,000 → 2,071 class defs) and is what makes scaling to the full schema set viable. Same idea as the C# library'sExternalReferenceCodeabstract sharing. - String-only constraints stripped off non-string nodes. A few OSDU schemas
attach
pattern/formattoarray/integerfields (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
formatdropped → plainstr. This library typesdatafor lossless round-tripping, not semantic validation. Honouringformatwould 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, needsemail-validator),uri(AnyUrl, normalises the value). Keeping plainstrpreserves the input. Same pragmatic choice the C# library makes. - Pinned snapshot.
schemas/2026.05.22/is a frozen copy of the OSDUdata-definitionsGenerated/schemas (shared with the C# library). Bumping it is an explicit, reviewable change.
Layout
osdu-python-models/
├── schemas/2026.05.22/ # 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:
- lifts each entity's
datasub-schema (titledData) and transitively collects the sharedabstract/*files it references, - 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$refto 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 adatamodel-codegenquirk that otherwise resolves a shared schema's nested$refs against the referencing entity's directory, - runs
datamodel-codegenonce over that tree — emitting each abstract as a shared module and each entity as aDatamodel 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.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file osdu_python_models-0.6.0.tar.gz.
File metadata
- Download URL: osdu_python_models-0.6.0.tar.gz
- Upload date:
- Size: 595.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ef0d2be814c609019e741ab070cf10c86861327d635f7522c73f262a5f06c503
|
|
| MD5 |
a26a4a29c5460c09a4aa991e74104070
|
|
| BLAKE2b-256 |
79b3713c334a2ef864d8c79542afc02b16b42d7dcb0065bc146553de749074ef
|
Provenance
The following attestation bundles were made for osdu_python_models-0.6.0.tar.gz:
Publisher:
release.yml on equinor/osdu-python-models
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
osdu_python_models-0.6.0.tar.gz -
Subject digest:
ef0d2be814c609019e741ab070cf10c86861327d635f7522c73f262a5f06c503 - Sigstore transparency entry: 1938103443
- Sigstore integration time:
-
Permalink:
equinor/osdu-python-models@f310f69a4010d7a289b436a0b3409bd8f3d56f8a -
Branch / Tag:
refs/heads/main - Owner: https://github.com/equinor
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@f310f69a4010d7a289b436a0b3409bd8f3d56f8a -
Trigger Event:
push
-
Statement type:
File details
Details for the file osdu_python_models-0.6.0-py3-none-any.whl.
File metadata
- Download URL: osdu_python_models-0.6.0-py3-none-any.whl
- Upload date:
- Size: 1.6 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c53d662d86b07770e976d2c023342b1aaf12967395ab07e2e82d5d10824864f4
|
|
| MD5 |
eb1765befeb1256b3ae929160a7213fd
|
|
| BLAKE2b-256 |
9526981d4cf32c5077fbf41e6e90e787b79f8997b0cb5d21d95f66284a5fcb98
|
Provenance
The following attestation bundles were made for osdu_python_models-0.6.0-py3-none-any.whl:
Publisher:
release.yml on equinor/osdu-python-models
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
osdu_python_models-0.6.0-py3-none-any.whl -
Subject digest:
c53d662d86b07770e976d2c023342b1aaf12967395ab07e2e82d5d10824864f4 - Sigstore transparency entry: 1938103617
- Sigstore integration time:
-
Permalink:
equinor/osdu-python-models@f310f69a4010d7a289b436a0b3409bd8f3d56f8a -
Branch / Tag:
refs/heads/main - Owner: https://github.com/equinor
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@f310f69a4010d7a289b436a0b3409bd8f3d56f8a -
Trigger Event:
push
-
Statement type: