Create Pydantic models from RDFS ontologies.
Caution
This is a test-driven-development project, with handwritten test fixtures and an LLM-generated implementation.
- Module generation: Generate Python code as a single module containing all classes
- Package generation: Create file-based package structures with a module for each class
- JSON-LD aliasing: Use a
@contextdocument to customise class and property names - Inheritance support: RDFS
rdfs:subClassOfbecomes Python inheritance - Union types: Multiple property ranges become union types
- Namespace handling: Automatic disambiguation for classes with identical names across namespaces
- Doctrings: Single- and multi-line docstrings are generated from the IRI,
rdfs:labelandrdfs:commentvalues
Here's an example RDFS ontology using simple artist and artwork classes.
@prefix ex: <http://example.org/> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
ex:Agent a rdfs:Class ;
rdfs:label "Agent" ;
rdfs:comment "A person or organisation" .
ex:Artist a rdfs:Class ;
rdfs:subClassOf ex:Agent ;
rdfs:label "Artist" ;
rdfs:comment "A creator of artworks" .
ex:Artwork a rdfs:Class ;
rdfs:comment "An artistic creation" .
ex:Painting a rdfs:Class ;
rdfs:subClassOf ex:Artwork .
ex:Exhibition a rdfs:Class ;
rdfs:comment "A curated collection of artworks" .
ex:name a rdf:Property ;
rdfs:label "Name" ;
rdfs:comment "The name of the resource" ;
rdfs:domain ex:Agent ;
rdfs:range rdfs:Literal .
ex:created a rdf:Property ;
rdfs:domain ex:Artist ;
rdfs:range ex:Painting .
ex:artist a rdf:Property ;
rdfs:domain ex:Artwork ;
rdfs:range ex:Artist .
ex:artworks a rdf:Property ;
rdfs:domain ex:Exhibition ;
rdfs:range ex:Painting , ex:Artwork .Generate the Pydantic models from the ontology.
from rdflib import Graph
from rdfs_pydantic import create_module
g = Graph()
g.parse("path/to/ontology.ttl", format="turtle")
pydantic_code = create_module(g)
print(pydantic_code)Result:
from __future__ import annotations
from pydantic import BaseModel, Field
class Agent(BaseModel):
"""Agent <http://example.org/Agent>.
A person or organisation.
"""
name: list[str] = Field(default_factory=list)
"""Name <http://example.org/name>.
The name of the resource.
"""
class Artist(Agent):
"""Artist <http://example.org/Artist>.
A creator of artworks.
"""
created: list[Painting] = Field(default_factory=list)
"""<http://example.org/created>."""
class Artwork(BaseModel):
"""<http://example.org/Artwork>.
An artistic creation.
"""
artist: list[Artist] = Field(default_factory=list)
"""<http://example.org/artist>."""
class Exhibition(BaseModel):
"""<http://example.org/Exhibition>.
A curated collection of artworks.
"""
artworks: list[Painting | Artwork] = Field(default_factory=list)
"""<http://example.org/artworks>."""
class Painting(Artwork):
"""<http://example.org/Painting>."""
...Generate all models as a single Python string, suitable for dynamic evaluation or single-file output:
from rdflib import Graph
from rdfs_pydantic import create_module
g = Graph()
g.parse("ontology.ttl", format="turtle")
code = create_module(g)
print(code)Create a structured package directory with separate files per class:
from rdflib import Graph
from rdfs_pydantic import create_package
g = Graph()
g.parse("ontology.ttl", format="turtle")
create_package(g, output_dir="my_ontology_package")Provide a JSON-LD @context to rename classes and properties:
from rdflib import Graph
from rdfs_pydantic import create_module
data = """
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
<http://example.org/E1> a rdfs:Class .
"""
g = Graph()
g.bind('ex', 'http://example.org/')
g.parse(data=data, format="turtle")
context = {
"@context": {
"Entity": {"@id": "http://example.org/E1"}
}
}
code = create_module(g, context=context)Generates code as:
from __future__ import annotations
from pydantic import BaseModel
class Entity(BaseModel):
"""<http://example.org/E1>."""
...# Generate module to stdout
uv run rdfs_pydantic module --ontology ontology.ttl
# Generate package structure
uv run rdfs_pydantic package --ontology ontology.ttl --output-dir ./outputuv run pytest