Skip to content
Open
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
8 changes: 6 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ With `make`:

```bash
make docs # serve with live reload at http://localhost:8000
make docs-test # strict build fails on any warning
make docs-test # strict build, fails on any warning
```

Without `make`:
Expand All @@ -78,4 +78,8 @@ Releases are published automatically by CI when a version tag is pushed.
git push origin v0.17.0
```

CI will build the package (`uv build`), publish it to PyPI, and deploy the docs to GitHub Pages. The version is derived from the git tag via `hatch-vcs` — no manual version bumping needed.
CI will build the package (`uv build`), publish it to PyPI, and deploy the docs to GitHub Pages. The version is derived from the git tag via `hatch-vcs`, so no manual version bumping is needed.

## AI Guidelines

We believe that AI, and in particular LLMs, can be helpful conventional tools to accelerate development and improve quality when used responsibly. AI or any other tool is never the author of code; a human developer always is. Therefore, it is mandatory to carefully review all generated content for correctness, quality, and the absence of legal and ethical issues. For consistency, please avoid patterns that are hard to maintain manually, such as duplicated content or special characters like em dashes or UTF icons.
35 changes: 20 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
# oold-python

<!-- markdownlint-disable MD033 -->
<p align="center">
<img alt="OO-LD logo" src="https://raw.githubusercontent.com/OO-LD/schema/main/OO-LD_logo.jpg" width="220" />
</p>
<!-- markdownlint-enable MD033 -->

[![DOI](https://zenodo.org/badge/691355012.svg)](https://zenodo.org/doi/10.5281/zenodo.8374237)
[![PyPI-Server](https://img.shields.io/pypi/v/oold.svg)](https://pypi.org/project/oold/)
[![Build status](https://img.shields.io/github/actions/workflow/status/OO-LD/oold-python/main.yml?branch=main)](https://github.com/OO-LD/oold-python/actions/workflows/main.yml?query=branch%3Amain)
[![codecov](https://codecov.io/gh/OO-LD/oold-python/branch/main/graph/badge.svg)](https://codecov.io/gh/OO-LD/oold-python)
[![License](https://img.shields.io/github/license/OO-LD/oold-python)](https://github.com/OO-LD/oold-python/blob/main/LICENSE)


# oold-python

Linked data class python package for object oriented linked data ([OO-LD](https://github.com/OO-LD/schema)) based on [pydantic](https://github.com/pydantic/pydantic). This package aims to implement this functionality independent from the [osw-python](https://github.com/OpenSemanticLab/osw-python) package - work in progress.

## Installation
Expand All @@ -28,6 +29,7 @@ pip install oold
```

## Objectives

- lossless transpilation between [OO-LD](https://github.com/OO-LD/schema) schemas and extended pydantic data classes
- interpret string IRIs with `oold-range` annotation as typed class property
- dynamically resolve such IRIs from one or multiple backends (simple in-memory dict, RDF-Graph, SPARQL-Endpoint, Document Store, etc.)
Expand All @@ -36,20 +38,20 @@ pip install oold

## Related Work

| Library | Notes |
|---|---|
| [RDFLib](https://github.com/RDFLib/rdflib) | RDF management; no schema validation or type safety. Used as a backend by oold-python. |
| [SuRF](https://github.com/cosminbasca/surfrdf) | ORM-like RDF; dynamically generated classes, no static type checking. |
| [Owlready2](https://github.com/pwin/owlready2) | OWL-aligned classes with native reasoning; no remote SPARQL support. |
| [twa](https://github.com/TheWorldAvatar/baselib/tree/main/python_wrapper) | Pydantic-based OGM; tightly couples RDF properties and type annotations. |
| [COLD](https://github.com/DigiBatt/cold/) | Generates static classes from OWL; no object-to-graph mapping. |
| Library | Notes |
| ------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- |
| [RDFLib](https://github.com/RDFLib/rdflib) | RDF management; no schema validation or type safety. Used as a backend by oold-python. |
| [SuRF](https://github.com/cosminbasca/surfrdf) | ORM-like RDF; dynamically generated classes, no static type checking. |
| [Owlready2](https://github.com/pwin/owlready2) | OWL-aligned classes with native reasoning; no remote SPARQL support. |
| [twa](https://github.com/TheWorldAvatar/baselib/tree/main/python_wrapper) | Pydantic-based OGM; tightly couples RDF properties and type annotations. |
| [COLD](https://github.com/DigiBatt/cold/) | Generates static classes from OWL; no object-to-graph mapping. |

See also: Bai et al. [https://doi.org/10.1039/D5DD00069F](https://doi.org/10.1039/D5DD00069F)


## Features

### Code Generation

Generate Python data models from OO-LD Schemas (based on [datamodel-code-generator](https://github.com/koxudaxi/datamodel-code-generator)):

```python
Expand Down Expand Up @@ -121,6 +123,7 @@ Thanks to the resolver mechanism, these IRIs turn into fully-fledged objects as
More details see [example code](./tests/test_oold.py)

### RDF-Export

Easily convert your objects to RDF (JSON-LD) and integrate with SPARQL queries:

```python
Expand Down Expand Up @@ -188,6 +191,7 @@ ctrl.to_json() # {"name": "arm-1", "joint_count": 6, "connection_url": "tcp://.
```

Key features:

- **Auto-detects the pure data model** from MRO - no manual configuration needed
- **Serialization strips controller fields** - `to_json()` / `to_jsonld()` only include data model fields
- **Type registry exclusion** - controllers don't replace their data model in the `_types` lookup, so backend resolution always returns the pure model class
Expand All @@ -205,6 +209,7 @@ target = TargetClass(source, extra_field="value")
```

Parameters:

- `none_to_default` - drop None/empty list attributes so the target uses its defaults
- `remove_extra` - drop fields not defined on the target class
- `silent` - suppress warnings about dropped fields (default: True)
Expand All @@ -213,11 +218,11 @@ Parameters:

Built-in backends for entity persistence and resolution:

| Backend | Storage | Query support |
|---------|---------|---------------|
| Backend | Storage | Query support |
| --------------------------- | ------------------------------------------------ | --------------- |
| **SimpleDictDocumentStore** | In-memory dict, optional JSON file (`file_path`) | Filter by field |
| **SqliteDocumentStore** | SQLite database (default `format=JSON`) | - |
| **LocalSparqlBackend** | In-memory RDF graph (rdflib) | SPARQL |
| **SqliteDocumentStore** | SQLite database (default `format=JSON`) | - |
| **LocalSparqlBackend** | In-memory RDF graph (rdflib) | SPARQL |

```python
from oold.backend.document_store import SimpleDictDocumentStore
Expand Down
6 changes: 6 additions & 0 deletions docs/contributing.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,9 @@ git push origin v0.17.0
```

CI will build the package (`uv build`), publish it to PyPI, and deploy the docs to GitHub Pages. The version is derived from the git tag via `hatch-vcs` - no manual version bumping needed.

---

## AI Guidelines

We believe that AI, and in particular LLMs, can be helpful conventional tools to accelerate development and improve quality when used responsibly. AI or any other tool is never the author of code; a human developer always is. Therefore, it is mandatory to carefully review all generated content for correctness, quality, and the absence of legal and ethical issues. For consistency, please avoid patterns that are hard to maintain manually, such as duplicated content or special characters like em dashes or UTF icons.
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ subclass-of-final-class = "ignore"

[tool.pytest.ini_options]
testpaths = ["tests"]
addopts = "--cov --cov-config=pyproject.toml --cov-report=term-missing"

[tool.deptry]
# The anywidget notebook only runs in the browser (pyodide) and imports
Expand Down
Loading