OldMan: Python OLDM¶

OldMan is a Python Object Linked Data Mapper (OLDM). It relies on the popular RDFlib Python library. See the foreword for further characteristics.
User’s Guide¶
Foreword¶
OldMan is a Python Object Linked Data Mapper (OLDM).
An OLDM let you create, retrieve and update RDF representations of Web Resources by manipulating them as Python objects.
OldMan, in its core, is based on two W3C standards:
- RDF (the Resource Description Framework) as data model;
- JSON-LD context for mapping objects and RDF graphs.
It is designed to support multiple protocols for interacting with data stores hosting these resources. Currently, only SPARQL is officially supported.
OldMan relies on the RDFlib Python library.
Why a new term?¶
Some similar projects employ the term Object RDF Mapper for denoting the mapping between objects and RDF graphs. This terminology uses the same initials than the well-known notion of Object Relational Mapper (ORM) that consider table rows instead of RDF graphs.
The Object Linked Data Mapper (OLDM) term avoids this confusion. It also emphasizes that the manipulated resources can be on the Web, not just in a local database. It should lead users to interact with data stores on which they not always have full control (e.g. a tiers Web API).
Mission¶
OldMan has one main objective: help you to declare your models using RDF triples and JSON-LD contexts instead of programming Python model classes yourself.
However, OldMan does not force you to express all your domain logic in a declarative style. OldMan makes easy for you to add dynamically plain-old Python methods to resource objects.
By adopting a declarative style:
- You can provide both RDF and JSON data to your clients.
- Your schema (including validation constraints) can be published and reused by hypermedia-driven Web clients.
- Your declared domain logic becomes independent of Python and its frameworks.
It also acknowledges that IRIs or compact URIs (CURIEs) -like strings are not always pleasant to use: arbitrary short names and objects are usually more user-friendly. However, you can still manipulate IRIs when it is relevant for you to do so. Everything remains mapped to IRIs.
Current core features¶
Resource-centric validation based on RDF vocabularies:
- Hydra: hydra:required , hydra:readonly and hydra:writeonly;
- Literal validation for common XSD types;
- Literal validation for arbitrary property (e.g. foaf:mbox);
- JSON-LD collections (set, list and language maps);
Inheritance (attributes and Python methods);
An attribute can require its value to be a collection (a set, a list or a language map);
Arbitrary attribute names (e.g. plural names for collections);
Separation between the client and data store models;
Extensibility to various sorts of data stores (not just SPARQL endpoints);
IRI generation for new resources (if not done by the remote data store);
Optional resource cache relying on the popular dogpile.cache library.
Status¶
OldMan is a young project still in an early stage. Feel free to contribute and to subscribe to our mailing list oldman AT librelist.com.
Only Python 2.7 is currently supported, but support for Python 3.x is of course something we would like to consider.
Installation¶
Python 2.7 is required, so if in your distribution you have both Python 2.7 and Python 3.x, please make sure you are using the right version (usually, the command python links to Python 3.x).
Virtualenv¶
We recommend you to isolate the installation of OldMan and its dependencies by using Virtualenv.
If virtualenv is not already installed on your computer, you can install it with easy_install or pip:
$ sudo easy_install-2.7 install virtualenv
or:
$ sudo pip2 install virtualenv
Now create a directory where to install your virtualenv. For instance:
$ mkdir -p ~/envs/oldman-2.7
Move in, init and activae your virtualenv:
$ cd ~/envs/oldman-2.7
$ virtualenv2 .
$ source bin/activate
Install OldMan and its dependencies¶
$ mkdir src
$ cd src
$ git clone https://github.com/oldm/OldMan.git oldman
$ cd oldman
Install first the concrete requirements:
$ pip install -r requirements.txt
And then install oldman and its abstract (not yet fulfilled) dependencies:
$ python setup.py install
To test your installation, we encourage you to install the nose testing library:
$ pip install nose
You can run the tests:
$ nosetests tests/
Hope everything is ok!
Continue to the quickstart example.
Quickstart¶
Model creation¶
1. Get the declared domain knowledge¶
First, let’s import some functions and classes:
from rdflib import Graph
from oldman import create_mediator, parse_graph_safely, SparqlStore
and create the RDF graph schema_graph that will contain our schema:
schema_graph = Graph()
The role of the schema graph is to contain most of the domain logic necessary to build our models. In this example, we load it from a RDF file:
schema_url = "https://raw.githubusercontent.com/oldm/OldMan/master/examples/quickstart_schema.ttl"
parse_graph_safely(schema_graph, schema_url, format="turtle")
Another main piece of the domain logic is found in the JSON-LD context. Here, we just need its IRI:
ctx_iri = "https://raw.githubusercontent.com/oldm/OldMan/master/examples/quickstart_context.jsonld"
We now have most of the domain knowledge we need to instantiate the store and its models.
2. Instantiate the store¶
Here, we consider an in-memory triplestore (read-write SPARQL endpoint) as a store (SparqlStore
):
# In-memory triplestore
data_graph = Graph()
store = SparqlStore(data_graph, schema_graph=schema_graph)
We extract the prefix information from the schema graph:
store.extract_prefixes(schema_graph)
3. Create the store model¶
We create a LocalPerson StoreModel
for the store.
Like for any model, we need:
- The IRI or a JSON-LD term of the RDFS class of the model. Here “LocalPerson” is an alias for http://example.org/myvoc#LocalPerson defined in the context file ;
- The JSON-LD context.
Moreover, since this model is associated to a store with limited capabilities (SparqlStore
), it also has
to generate IRIs for new resources. Here we provide the following additional information:
A prefix for creating the IRI of new resources (optional) ;
An IRI fragment (optional);
To declare that we want to generate incremental IRIs with short numbers for new
Resource
objects (optional).store.create_model("LocalPerson", ctx_iri, iri_prefix="http://localhost/persons/", iri_fragment="me", incremental_iri=True)
4. Load the mediator and the client model¶
Store models are not directly manipulated; the user is expected to use their relative client models instead. Oldman distinguishes client and store models so that they can have (if necessary) a slightly different but compatible domain logic. However here, for the sake of simplicity, client models are directly derived (i.e. imported) from the store models.
First we instantiate a Mediator
object that will be in charge of the mediation
between the client and store models:
mediator = create_mediator(store)
Then we import the client model from the store model:
mediator.import_store_models()
lp_model = mediator.get_client_model("LocalPerson")
That’s it, now our client model is ready to be used for creating new resources.
Resource editing¶
Now that the domain logic has been declared, we can create ClientResource
objects
for two persons, Alice and Bob.
Oldman requires the creation of a new ClientResource
to be done
inside a ClientSession
for performance reasons.
session1 = mediator.create_session()
alice = lp_model.new(session1, name="Alice", emails={"alice@example.org"},
short_bio_en="I am ...")
bob = lp_model.new(session1, name="Bob", blog="http://blog.example.com/",
short_bio_fr=u"J'ai grandi en ... .")
We now have to ClientResource
in memory but Alice and Bob are not yet
in the store.
Actually, Bob is not ready yet to be persisted because some information is still missing: its email addresses.
This information is required by our domain logic. Let’s satisfy this constraint and flush the session:
>>> bob.is_valid()
False
>>> bob.emails = {"bob@localhost", "bob@example.org"}
>>> bob.is_valid()
True
>>> session1.flush()
Let’s now declare that they are friends and save this change:
alice.friends = {bob}
bob.friends = {alice}
session1.flush()
That’s it. Have you seen many IRIs? Only one, for the blog. Let’s look at them:
>>> alice.id
"http://localhost/persons/1#me"
>>> bob.id
"http://localhost/persons/2#me"
>>> bob.types
[u'http://example.org/myvoc#LocalPerson', u'http://xmlns.com/foaf/0.1/Person']
and at some other attributes:
>>> alice.name
"Alice"
>>> bob.emails
set(['bob@example.org', 'bob@localhost'])
>>> bob.short_bio_en
None
>>> bob.short_bio_fr
u"J'ai grandi en ... ."
We can also assign an IRI when creating a ClientResource
object:
>>> john_iri = "http://example.org/john#me"
>>> john = lp_model.new(session1, iri=john_iri, name="John", emails={"john@example.org"})
>>> session1.flush()
>>> john.id.iri
"http://example.org/john#me"
Resource retrieval¶
By default, resources are not cached. We can retrieve Alice and Bob from the data graph as follows:
>>> alice_iri = alice.id.iri
>>> session2 = mediator.create_session()
>>> # First person found named Bob
>>> bob = lp_model.first(session2, name="Bob")
>>> alice = lp_model.get(session2, iri=alice_iri)
>>> # Or retrieve her as the unique friend of Bob
>>> alice = list(bob.friends)[0]
>>> alice.name
"Alice"
Finds all the persons:
>>> set(lp_model.all(session2))
set([ClientResource(<http://example.org/john#me>), ClientResource(<http://localhost/persons/2#me>), ClientResource(<http://localhost/persons/1#me>)])
>>> # Equivalent to
>>> set(lp_model.filter(session2))
set([ClientResource(<http://localhost/persons/1#me>), ClientResource(<http://localhost/persons/2#me>), ClientResource(<http://example.org/john#me>)])
Serialization¶
JSON:
>>> print alice.to_json()
{
"emails": [
"alice@example.org"
],
"friends": [
"http://localhost/persons/2#me"
],
"id": "http://localhost/persons/1#me",
"name": "Alice",
"short_bio_en": "I am ...",
"types": [
"http://example.org/myvoc#LocalPerson",
"http://xmlns.com/foaf/0.1/Person"
]
}
JSON-LD:
>>> print john.to_jsonld()
{
"@context": "https://raw.githubusercontent.com/oldm/OldMan/master/examples/quickstart_context.jsonld",
"emails": [
"john@example.org"
],
"id": "http://example.org/john#me",
"name": "John",
"types": [
"http://example.org/myvoc#LocalPerson",
"http://xmlns.com/foaf/0.1/Person"
]
}
Turtle:
>>> print bob.to_rdf("turtle")
@prefix bio: <http://purl.org/vocab/bio/0.1/> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix myvoc: <http://example.org/myvoc#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xml: <http://www.w3.org/XML/1998/namespace> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
<http://localhost/persons/2#me> a myvoc:LocalPerson,
foaf:Person ;
bio:olb "J'ai grandi en ... ."@fr ;
foaf:knows <http://localhost/persons/1#me> ;
foaf:mbox "bob@example.org"^^xsd:string,
"bob@localhost"^^xsd:string ;
foaf:name "Bob"^^xsd:string ;
foaf:weblog <http://blog.example.com/> .
Validation¶
Validation is also there:
>>> # Email is required
>>> lp_model.new(session1, name="Jack")
>>> session1.flush()
oldman.core.exception.OMRequiredPropertyError: emails
>>> # Invalid email
>>> bob.emails = {'you_wont_email_me'}
oldman.core.exception.OMAttributeTypeCheckError: you_wont_email_me is not a valid email (bad format)
>>> # Not a set
>>> bob.emails = "bob@example.com"
oldman.core.exception.OMAttributeTypeCheckError: A container (<type 'set'>) was expected instead of <type 'str'>
>>> # Invalid name
>>> bob.name = 5
oldman.core.exception.OMAttributeTypeCheckError: 5 is not a (<type 'str'>, <type 'unicode'>)
>>> session1.close()
>>> session2.close()
Domain logic¶
Here is the declared domain logic that we used:
JSON-LD context https://raw.githubusercontent.com/oldm/OldMan/master/examples/quickstart_context.jsonld:
{
"@context": {
"xsd": "http://www.w3.org/2001/XMLSchema#",
"foaf": "http://xmlns.com/foaf/0.1/",
"bio": "http://purl.org/vocab/bio/0.1/",
"myvoc": "http://example.org/myvoc#",
"Person": "foaf:Person",
"LocalPerson": "myvoc:LocalPerson",
"id": "@id",
"types": "@type",
"friends": {
"@id": "foaf:knows",
"@type": "@id",
"@container": "@set"
},
"short_bio_fr": {
"@id": "bio:olb",
"@language": "fr"
},
"name": {
"@id": "foaf:name",
"@type": "xsd:string"
},
"emails": {
"@id": "foaf:mbox",
"@type": "xsd:string",
"@container": "@set"
},
"blog": {
"@id": "foaf:weblog",
"@type": "@id"
},
"short_bio_en": {
"@id": "bio:olb",
"@language": "en"
}
}
}
Schema (uses the Hydra vocabulary) https://raw.githubusercontent.com/oldm/OldMan/master/examples/quickstart_schema.ttl:
@prefix bio: <http://purl.org/vocab/bio/0.1/> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix hydra: <http://www.w3.org/ns/hydra/core#> .
@prefix myvoc: <http://example.org/myvoc#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
# Properties that may be given to a foaf:Person (no requirement)
foaf:Person a hydra:Class ;
hydra:supportedProperty [ hydra:property foaf:mbox ],
[ hydra:property foaf:weblog ],
[ hydra:property foaf:name ],
[ hydra:property bio:olb ],
[ hydra:property foaf:knows ].
# Local version of a Person with requirements
myvoc:LocalPerson a hydra:Class ;
rdfs:subClassOf foaf:Person ;
hydra:supportedProperty [ hydra:property foaf:mbox ;
hydra:required true ],
[ hydra:property foaf:name ;
hydra:required true ].
Core concepts¶
THIS PAGE IS OUT-DATED. TODO: rewrite it.
Resource¶
A Resource
object represents a Web resource
identified by a regular IRI (internationalized URI) or
or a skolem IRI (if it should treated
as a blank node).
In OldMan, Web resources are described in conformance to the
Resource Description Framework (RDF).
A Resource
object may have some attributes that provide the predicate
(also called property) and the object terms of RDF triples describing the resource.
The resource itself is the subject of the triple (expect if the property is reversed).
Its attributes have arbitrary short names as defined in the JSON-LD context.
A Resource
object access to its attributes through the
Model
objects to which it relates (through its types
).
Thus, if it has no type or its types that are not related to a Model
object,
a Resource
object has no “RDF” attribute.
In OldMan, the relation between Resource
and Model
objects
is many-to-many.
It differs from traditional ORMs where the relation is one-to-many (the resource is usually
an instance of the model and the latter is a Python class in these frameworks).
However, we expect that most Resource
objects will relate to one
Model
object, but this is not a requirement.
It is common for a resource in RDF to be instance of multiple RDFS classes so OldMan had to be ok with this practise.
Some inherited Python methods may also be provided by the Model
objects.
Features¶
Edit its properties:
>>> # We assume that a model has been created for the RDFS class schema:Person. >>> alice = Resource(resource_manager, types=["http://schema.org/Person"]) >>> alice.name = "Alice" >>> print alice.name Alice >>> print alice.id 'http://localhost/person/3#me' >>> alice.add_type("http://schema.org/Researcher") >>> print alice.types [u'http://schema.org/Person', u'http://schema.org/Researcher']
Persist its new values in the triplestore:
alice.save()
Call inherited methods:
alice.do_that()
Serialize to JSON, JSON-LD or any other RDF format:
>>> alice.to_jsonld() { "@context": "https://example.com/context.jsonld", "id": "http://localhost/person/3#me", "name": "Alice", "types": [ "http://schema.org/Person", "http://schema.org/Researcher" ] } >>> alice.to_rdf(format="turtle") @prefix schema: <http://schema.org/> . @prefix xsd: <http://www.w3.org/2001/XMLSchema#> . <http://localhost/persons/3#me> a schema:Person, schema:Researcher ; foaf:name "Alice"^^xsd:string .
UserMediator¶
TODO: update
A UserMediator
object is the central object of OldMan.
It creates Model
objects (create_model()
)
and retrieves Resource
objects (get()
,
filter()
and sparql_filter()
).
It accepts Python method declarations if they happen before the creation of Model
objects
(declare_method()
).
It also provide helper functions to create new Resource
objects
(create()
and new()
)
but it is usually simpler to use those of a Model
object.
For creating the UserMediator
object, the schema graph
and the data store (DataStore
) must be given.
Basically, the schema graph describes which properties should be expected for a given RDFS class, which are required and what are the constraints.
Model¶
In OldMan, models are not Python classes but Model
objects.
However, on the RDF side, they correspond to RDFS classes (their
class_iri
attributes).
Their main role is to provide attributes and methods to Resource
objects, as explained
above.
Model
objects are created by the UserMediator
object.
A model provide some helpers above the UserMediator
object (
get()
, filter()
, new()
and
create()
) that include the class_iri
to the types
parameter of these methods.
DataStore¶
A DataStore
implements the CRUD operations on Web Resources exposed by the
UserMediator
and Model
objects.
The vision of OldMan is to include a large choice of data stores. But currently, only SPARQL endpoints are supported.
Non-CRUD operations may also be introduced in the future (in discussion).
Any data store accepts a dogpile.cache.region.CacheRegion
object to enable its
ResourceCache
object.
By default the latter is disabled so it does not cache the Resource
objects loaded
from and stored in the data store.
SPARQLDataStore¶
A SPARQLDataStore
object relies on one or two RDF graphs (rdflib.graph.Graph
):
the data and default graphs.
The data graph is where regular resources are saved and loaded.
The default graph (rdflib.graph.ConjunctiveGraph
or rdflib.graph.Dataset
) may be
given as an optional second graph.
Its only constraint is to include the content of the data graph in its default graph.
Examples¶
DBpedia querying (read-only)¶
This example presents a use case where an OLDM produces a significant overhead that is important to understand.
We want to query the DBpedia which contains RDF statements extracted from the info-boxes of Wikipedia. DBpedia provides a public SPARQL endpoint powered by Virtuoso.
Inspired by a gist of O. Berger, we will display:
- The 10 first French films found on DBpedia and the names of their actors;
- The films in which Michel Piccoli had a role.
Direct SPARQL queries (without OldMan)¶
First, let’s create a Graph to access the DBpedia SPARQL endpoint
from rdflib import Graph
from rdflib.plugins.stores.sparqlstore import SPARQLStore
data_graph = Graph(SPARQLStore("http://dbpedia.org/sparql", context_aware=False))
Query 1¶
import time
q3_start_time = time.time()
results = data_graph.query("""
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX dcterms: <http://purl.org/dc/terms/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX dbpo: <http://dbpedia.org/ontology/>
SELECT ?film ?title_fr ?title_en ?actor ?actor_name_fr ?actor_name_en
WHERE {
{
SELECT ?film
WHERE {
?film a dbpo:Film ;
dcterms:subject <http://dbpedia.org/resource/Category:French_films> .
}
LIMIT 10
}
OPTIONAL {
?film rdfs:label ?title_en .
FILTER langMatches( lang(?title_en), "EN" ) .
}
OPTIONAL {
?film rdfs:label ?title_fr .
FILTER langMatches( lang(?title_fr), "FR" ) .
}
OPTIONAL {
?film dbpo:with ?actor .
OPTIONAL {
?actor foaf:name ?actor_name_en .
FILTER langMatches( lang(?actor_name_en), "EN" ) .
}
OPTIONAL {
?actor foaf:name ?actor_name_fr .
FILTER langMatches( lang(?actor_name_fr), "FR" ) .
}
}
}
""")
Now we extract the film titles and the names of the actors:
film_titles = {}
film_actors = {}
for film_iri, title_fr, title_en, actor_iri, actor_name_fr, actor_name_en in results:
if film_iri not in film_titles:
for t in [title_fr, title_en, film_iri]:
if t is not None:
film_titles[film_iri] = unicode(t)
break
for name in [actor_name_fr, actor_name_en, actor_iri]:
if name is not None:
if film_iri not in film_actors:
film_actors[film_iri] = [name]
elif name not in film_actors[film_iri]:
film_actors[film_iri].append(unicode(name))
break
and display them:
>>> for film_iri in film_titles:
... title = film_titles[film_iri]
... if film_iri not in film_actors:
... print "%s %s (no actor declared)" % (title, film_iri)
... else:
... actor_names = ", ".join(film_actors[film_iri])
... print "%s with %s" % (title, actor_names)
And Now... Ladies and Gentlemen with Patricia Kaas, Jeremy Irons, Thierry Lhermitte
Un long dimanche de fiançailles (film) with Dominique Pinon, Marion Cotillard, Ticky Holgado, Audrey Tautou, Jodie Foster, Chantal Neuwirth, Gaspard Ulliel, André Dussollier, Andre Dussolier
Charlotte et Véronique http://dbpedia.org/resource/All_the_Boys_Are_Called_Patrick (no actor declared)
Toutes ces belles promesses with Jeanne Balibar, Bulle Ogier, Valerie Crunchant, http://dbpedia.org/resource/Renaud_B%C3%A9card
Édith et Marcel with Évelyne Bouix, Evelyne Bouix, http://dbpedia.org/resource/Marcel_Cerdan_Jr
Une robe d'été http://dbpedia.org/resource/A_Summer_Dress (no actor declared)
9 semaines 1/2 with Kim Basinger, Mickey Rourke
Tout sur ma mère with Penélope Cruz, Penélope Cruz Sánchez, Cecilia Roth, Antonia San Juan, Candela Pena, Marisa Paredes
Artemisia (film) with Miki Manojlović, Predrag Miki Manojlovic, Michel Serrault, Valentina Cervi
Two Days in Paris with Julie Delpy, Adam Goldberg, Daniel Bruhl
>>> print "Done in %.3f seconds" % (time.time() - q3_start_time)
Done in 0.252 seconds
Some names are missing in the DBpedia and are replaced by the URI. The film URI is also displayed when the actors are unknown so that you can check with your browser that this information is missing.
Query 2¶
q4_start_time = time.time()
results = data_graph.query("""
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX dcterms: <http://purl.org/dc/terms/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX dbpo: <http://dbpedia.org/ontology/>
SELECT ?film ?title_fr ?title_en
WHERE {
?film a dbpo:Film ;
dbpo:with <http://dbpedia.org/resource/Michel_Piccoli> .
OPTIONAL {
?film rdfs:label ?title_en .
FILTER langMatches( lang(?title_en), "EN" ) .
}
OPTIONAL {
?film rdfs:label ?title_fr .
FILTER langMatches( lang(?title_fr), "FR" ) .
}
}
""")
>>> for film_iri, title_fr, title_en in results:
... if film_iri not in film_titles:
... for t in [title_fr, title_en, film_iri]:
... if t is not None:
... print t
... break
La Diagonale du fou
Le Journal d'une femme de chambre (film, 1964)
La Grande Bouffe
Max et les Ferrailleurs
La Voie lactée (film, 1969)
Les Demoiselles de Rochefort
Le Saut dans le vide
Belle toujours
Boxes
Des enfants gâtés
Une étrange affaire
Belle de Jour (film)
Benjamin ou les Mémoires d'un puceau
Le Mépris (film)
Dillinger est mort
Généalogies d'un crime
Je rentre à la maison
La Belle Noiseuse
La Chamade (film)
Le Prix du danger (film)
Mauvais Sang (film)
Milou en mai
Passion (film, 1982)
La Prophétie des grenouilles
La Poussière du temps
Le Fantôme de la liberté
Compartiment tueurs
Les Choses de la vie
Themroc
Une chambre en ville
Vincent, François, Paul... et les autres
Habemus papam (film)
Les Noces rouges
Les Cent et Une Nuits de Simon Cinéma
La Décade prodigieuse
Der Preis fürs Überleben
Party (1996 film)
The Distant Land
Passion in the Desert
>>> print "Done in %.3f seconds" % (time.time() - q4_start_time)
Done in 0.180 seconds
With OldMan¶
Let’s first create two Model
objects: film_model and person_model from these
context
and schema:
from oldman import create_mediator, SparqlStore
from dogpile.cache import make_region
schema_url = "https://raw.githubusercontent.com/oldm/OldMan/master/examples/dbpedia_film_schema.ttl"
schema_graph = Graph().parse(schema_url, format="turtle")
context_url = "https://raw.githubusercontent.com/oldm/OldMan/master/examples/dbpedia_film_context.jsonld"
# Same data graph that before
data_graph = Graph(SPARQLStore("http://dbpedia.org/sparql", context_aware=False))
cache_region = make_region().configure('dogpile.cache.memory_pickle')
# store: SPARQL-aware triple store, with two models
store = SparqlStore(data_graph, schema_graph=schema_graph, cache_region=cache_region)
store.create_model("http://dbpedia.org/ontology/Film", context_url)
# JSON-LD terms can be used instead of IRIs
store.create_model("Person", context_url)
# Mediator for users
mediator = create_mediator(store)
# Re-uses the models of the data store
mediator.use_all_store_models()
film_model = mediator.get_client_model("http://dbpedia.org/ontology/Film")
actor_model = mediator.get_client_model("Person")
Please note that we set up a resource cache and reused the data_graph.
We also declare two extraction functions:
def extract_title(film):
if len(film.titles) > 0:
key = "fr" if "fr" in film.titles else film.titles.keys()[0]
return "%s (%s version)" % (film.titles[key], key)
return film.id
def extract_name(person):
if person.names is not None and len(person.names) > 0:
for key in ["fr", "en"]:
if key in person.names:
return person.names[key]
return person.names.values()[0]
return person.id
Query 1 (lazy)¶
By default, OldMan behaves lazily:
>>> q1_start_time = time.time()
>>> for film in film_model.filter(subjects=["http://dbpedia.org/resource/Category:French_films"],
... limit=10):
... title = extract_title(film)
... if film.actors is None:
... print " %s %s (no actor declared)" % (title, film.id)
... else:
... actor_names = ", ".join([extract_name(a) for a in film.actors])
... print "%s with %s" % (title, actor_names)
Édith et Marcel (fr version) with http://dbpedia.org/resource/Marcel_Cerdan_Jr, Evelyne Bouix
Two Days in Paris (fr version) with Julie Delpy, Adam Goldberg, Daniel Bruhl
9 semaines 1/2 (fr version) with Kim Basinger, Mickey Rourke
Une robe d'été (fr version) http://dbpedia.org/resource/A_Summer_Dress (no actor declared)
Un long dimanche de fiançailles (film) (fr version) with Jodie Foster, Chantal Neuwirth, Marion Cotillard, Ticky Holgado, André Dussollier, Dominique Pinon, Audrey Tautou, Gaspard Ulliel
Tout sur ma mère (fr version) with Cecilia Roth, Antonia San Juan, Marisa Paredes, Candela Pena, Penélope Cruz Sánchez
Charlotte et Véronique (fr version) http://dbpedia.org/resource/All_the_Boys_Are_Called_Patrick (no actor declared)
Toutes ces belles promesses (fr version) with Valerie Crunchant, Jeanne Balibar, Bulle Ogier, http://dbpedia.org/resource/Renaud_B%C3%A9card
And Now... Ladies and Gentlemen (fr version) with Thierry Lhermitte, Jeremy Irons, Patricia Kaas
Artemisia (film) (fr version) with Michel Serrault, Miki Manojlović, Valentina Cervi
>>> print "Done in %.3f seconds" % (time.time() - q1_start_time)
Done in 17.123 seconds
17s? Why is it so slow? There are two reasons:
- OldMan loads a
Resource
object for each film or actor that is displayed. Loading aResource
object implies to retrieve all the triples in which the resource is the subject. In DBpedia, entries like films and actors have often many triples. Some of them have long textual literal values (localized paragraphs from Wikipedia). For instance, see http://dbpedia.org/resource/Penelope_Cruz. This approach retrieves much more information than we need for our specific query. - By default OldMan is lazy so it retrieves each a
Resource
object at the last time, one by one in sequence. The execution of this long sequence of queries takes a long time, partly because of the network latency that is multiplied by the number of queries.
Query 1 (eager)¶
While this first phenomenon is something you should expect when using an OLDM, the second reason can avoided by adopting an eager strategy:
>>> q1_start_time = time.time()
>>> for film in film_model.filter(subjects=["http://dbpedia.org/resource/Category:French_films"],
... limit=10, eager=True,
... pre_cache_properties=["http://dbpedia.org/ontology/starring"]):
... # Code and results not shown
>>> print "Done in %.3f seconds" % (time.time() - q1_start_time)
Done in 2.518 seconds
The eager strategy makes one heavy SPARQL request that returns all the triples about the films but also about the actors (thanks to the pre-cached property dbpo:starring). The network latency is then almost minimal.
If we re-query it again lazily, thanks to the cache it makes just one lightweight SPARQL query:
>>> q1_start_time = time.time()
>>> for film in film_model.filter(subjects=["http://dbpedia.org/resource/Category:French_films"],
... limit=10):
... # Code and results not shown
>>> print "Done in %.3f seconds" % (time.time() - q1_start_time)
Done in 0.182 seconds
But if we re-query it eagerly, the heavy query will be sent again. The cache is then of little interest:
>>> # Code and results not shown
>>> print "Done in %.3f seconds" % (time.time() - q1_start_time)
Done in 2.169 seconds
Query 2 (lazy)¶
>>> q2_start_time = time.time()
>>> for film in film_model.filter(actors=["http://dbpedia.org/resource/Michel_Piccoli"]):
... print extract_title(film)
... # Results not shown
>>> print "Done in %.3f seconds" % (time.time() - q2_start_time)
Done in 16.419 seconds
Query 2 (eager)¶
>>> q2_start_time = time.time()
>>> for film in film_model.filter(actors=["http://dbpedia.org/resource/Michel_Piccoli"],
eager=True):
... # Code and results not shown
>>> print "Done in %.3f seconds" % (time.time() - q2_start_time)
Done in 1.503 seconds
API reference¶
Main classes manipulated by end-users: Mediator
,
ClientModel
and ClientResource
.
PermanentIDGenerator
classes can be found in the oldman.storage.id_generation
module.
Store
classes can be found in the package oldman.storage.store
.
oldman package¶
Subpackages¶
oldman.client package¶
Subpackages¶
-
class
oldman.client.mediation.mediator.
Mediator
[source]¶ Bases:
object
TODO: describe
-
declare_method
(method, name, class_iri)[source]¶ Attaches a method to the
Resource
objects that are instances of a given RDFS class.Like in Object-Oriented Programming, this method can be overwritten by attaching a homonymous method to a class that has a higher inheritance priority (such as a sub-class).
To benefit from this method (or an overwritten one),
Resource
objects must be associated to aModel
that corresponds to the RDFS class or to one of its subclasses.Parameters: - method – Python function that takes as first argument a
Resource
object. - name – Name assigned to this method.
- class_iri – Targeted RDFS class. If not overwritten, all the instances
(
Resource
objects) should inherit this method.
- method – Python function that takes as first argument a
-
-
class
oldman.client.mediation.store_proxy.
DefaultStoreProxy
(store_selector, conversion_manager)[source]¶ Bases:
oldman.client.mediation.store_proxy.StoreProxy
-
filter
(resource_finder, resource_factory, types=None, hashless_iri=None, limit=None, eager=True, pre_cache_properties=None, **kwargs)[source]¶ TODO: explain
:return list of ClientResource ?
-
first
(client_tracker, resource_factory, types=None, hashless_iri=None, pre_cache_properties=None, eager_with_reversed_attributes=True, **kwargs)[source]¶
-
flush
(resource_factory, client_resources_to_update, client_resources_to_delete, is_end_user)[source]¶ TODO: explain
:return list of the new ClientResource ?
-
-
class
oldman.client.mediation.store_proxy.
StoreProxy
[source]¶ Bases:
object
TODO: find a better name
-
filter
(resource_tracker, resource_factory, types=None, hashless_iri=None, limit=None, eager=False, pre_cache_properties=None, **kwargs)[source]¶ TODO: explain
:return list of ClientResource ?
-
first
(resource_finder, resource_factory, types=None, hashless_iri=None, pre_cache_properties=None, eager_with_reversed_attributes=True, **kwargs)[source]¶
-
flush
(resource_factory, client_resources_to_update, client_resources_to_delete, is_end_user)[source]¶ TODO: explain
:return list of the updated ClientResource ?
-
-
class
oldman.client.model.manager.
ClientModelManager
(oper_extractor, declare_default_operation_functions=True, **kwargs)[source]¶ Bases:
oldman.core.model.manager.ModelManager
Client ModelManager.
In charge of the conversion between and store and client models.
-
class
oldman.client.model.model.
ClientModel
(name, class_iri, ancestry_iris, context, om_attributes, operations=None, local_context=None, accept_new_blank_nodes=False)[source]¶ Bases:
oldman.core.model.model.Model
TODO: describe.
TODO: further study this specific case.
Contains methods for end-users (–> layer above the user mediator).
-
all
(session, limit=None, eager=False)[source]¶ Finds every
Resource
object that is instance of its RDFS class.Parameters: - limit – Upper bound on the number of solutions returned (SPARQL LIMIT). Positive integer. Defaults to None.
- eager – If True loads all the Resource objects within one single SPARQL query. Defaults to False (lazy).
Returns: A generator of
Resource
objects.
-
filter
(session, hashless_iri=None, limit=None, eager=True, pre_cache_properties=None, **kwargs)[source]¶ Finds the
Resource
objects matching the given criteria.The class_iri attribute is added to the types.
See
oldman.resource.finder.ResourceFinder.filter()
for further details.
-
first
(session, hashless_iri=None, eager_with_reversed_attributes=True, pre_cache_properties=None, **kwargs)[source]¶ Finds the
Resource
objects matching the given criteria.The class_iri attribute is added to the types.
See
oldman.resource.finder.ResourceFinder.filter()
for further details.
-
get
(session, iri, eager_with_reversed_attributes=None)[source]¶ Gets the first
Resource
object matching the given criteria.The class_iri attribute is added to the types. Also looks if reversed attributes should be considered eagerly.
See
oldman.store.datastore.DataStore.get()
for further details.
-
methods
¶ dict of Python functions that takes as first argument a
Resource
object. Keys are the method names.
-
TODO: explain
-
class
oldman.client.parsing.operation.
HydraOperationExtractor
[source]¶ Bases:
oldman.client.parsing.operation.OperationExtractor
TODO: describe
-
class
oldman.client.rest.controller.
HTTPController
(user_mediator, config={})[source]¶ Bases:
object
HTTP.
TODO: check declared methods (only GET and HEAD are implicit).
-
DEFAULT_CONFIG
= {'allow_put_new_resource': True, 'allow_put_new_type_existing_resource': False, 'allow_put_remove_type_existing_resource': False}¶
-
get
(hashless_iri, accept_header='*/*', **kwargs)[source]¶ TODO: describe.
No support declaration required.
-
-
class
oldman.client.rest.crud.
HashLessCRUDer
(user_mediator)[source]¶ Bases:
object
A
HashlessCRUDer
object helps you to manipulate yourResource
objects in a RESTful-like manner.Please note that REST/HTTP only manipulates hash-less IRIs. A hash IRI is the combination of a hash-less IRI (fragment-less IRI) and a fragment. Multiple hashed IRIs may have the same hash-less IRI and only differ by their fragment values. This is a concern for each type of HTTP operation.
This class is generic and does not support the Collection pattern (there is no append method).
Parameters: manager – ResourceManager
object.Possible improvements:
- Add a PATCH method.
-
delete
(hashless_iri)[source]¶ Deletes every
Resource
object having this hash-less IRI.Parameters: hashless_iri – Hash-less IRI.
-
get
(hashless_iri, content_type='text/turtle')[source]¶ Gets the main
Resource
object having its hash-less IRI.When multiple
Resource
objects have this hash-less IRI, one of them has to be selected. If one has no fragment value, it is selected. Otherwise, this selection is currently arbitrary.TODO: stop selecting the resources and returns the graph containing these resources.
Raises an
ObjectNotFoundError
exception if no resource is found.Parameters: - hashless_iri – hash-less of the resource.
- content_type – Content type of its representation.
Returns: The representation of selected
Resource
object and its content type
-
update
(hashless_iri, document_content, content_type, allow_new_type=False, allow_type_removal=False)[source]¶ Updates every
Resource
object having this hash-less IRI.Raises an
OMDifferentBaseIRIError
exception if tries to create of modify non-blankResource
objects that have a different hash-less IRI. This restriction is motivated by security concerns.Accepts JSON, JSON-LD and RDF formats supported by RDFlib.
Parameters: - hashless_iri – Document IRI.
- document_content – Payload.
- content_type – Content type of the payload.
- allow_new_type – If True, new types can be added. Defaults to False. See
oldman.resource.Resource.full_update()
for explanations about the security concerns. - allow_type_removal – If True, new types can be removed. Same security concerns than above. Defaults to False.
Submodules¶
oldman.client.resource module¶
-
class
oldman.client.resource.
ClientResource
(model_manager, session, iri=None, hashless_iri=None, collection_iri=None, iri_fragment=None, is_new=True, **kwargs)[source]¶ Bases:
oldman.core.resource.resource.Resource
ClientResource: resource manipulated by the end-user.
Has access to the session.
TODO: complete the description.
Parameters: - iri – IRI of the resource. If not given, this IRI is generated by the main model. Defaults to None.
- hashless_iri – Hash-less IRI that is given to the main model for generating a new IRI if no id is given. The IRI generator may ignore it. Defaults to None. Must be None if collection_iri is given.
- collection_iri – IRI of the controller to which this resource belongs. This information is used to generate a new IRI if no id is given. The IRI generator may ignore it. Defaults to None. Must be None if hashless_iri is given.
- iri_fragment – TODO: describe.
Is not serializable.
-
classmethod
load_from_graph
(mediator, model_manager, id, subgraph, is_new=True, collection_iri=None)[source]¶ Loads a new
ClientResource
object from a sub-graph.TODO: update the comments.
Parameters: - mediator –
Mediator
object. - id – IRI of the resource.
- subgraph –
rdflib.Graph
object containing triples about the resource. - is_new – When is True and id given, checks that the IRI is not already existing in the union_graph. Defaults to True.
Returns: The
Resource
object created.- mediator –
-
receive_local_deletion_notification
()[source]¶ TODO: explain and find a better name.
“Pre”-deletion.
-
session
¶
oldman.client.resource_factory module¶
oldman.client.session module¶
-
class
oldman.client.session.
ClientSession
[source]¶ Bases:
oldman.core.session.session.Session
-
filter
(types=None, hashless_iri=None, limit=None, eager=True, pre_cache_properties=None, **kwargs)[source]¶ See
oldman.store.store.Store.filter()
.
-
first
(types=None, hashless_iri=None, eager_with_reversed_attributes=True, pre_cache_properties=None, **kwargs)[source]¶
-
new
(iri=None, types=None, hashless_iri=None, collection_iri=None, **kwargs)[source]¶ Creates a new
Resource
object without saving it in the data_store.The kwargs dict can contains regular attribute key-values that will be assigned to
OMAttribute
objects.TODO: update this doc
Parameters: - iri – IRI of the new resource. Defaults to None. If not given, the IRI is generated by the IRI generator of the main model.
- types – IRIs of RDFS classes the resource is instance of. Defaults to None.
Note that these IRIs are used to find the models of the resource
(see
find_models_and_types()
for more details). - hashless_iri – hash-less IRI that MAY be considered when generating an IRI for the new resource. Defaults to None. Ignored if id is given. Must be None if collection_iri is given.
- collection_iri – IRI of the controller to which this resource belongs. This information is used to generate a new IRI if no id is given. The IRI generator may ignore it. Defaults to None. Must be None if hashless_iri is given.
Returns: A new
Resource
object.
-
-
class
oldman.client.session.
DefaultClientSession
(model_manager, store_proxy)[source]¶ Bases:
oldman.client.session.ClientSession
TODO: find a better name
-
delete
(client_resource)[source]¶ TODO: describe.
Wait for the next flush() to remove the resource from the store.
-
filter
(types=None, hashless_iri=None, limit=None, eager=False, pre_cache_properties=None, **kwargs)[source]¶
-
first
(types=None, hashless_iri=None, eager_with_reversed_attributes=True, pre_cache_properties=None, **kwargs)[source]¶
-
Module contents¶
oldman.core package¶
Subpackages¶
-
class
oldman.core.model.ancestry.
ClassAncestry
(child_class_iri, schema_graph)[source]¶ Bases:
object
Ancestry of a given RDFS class.
Parameters: - child_class_iri – IRI of the child RDFS class.
- schema_graph –
rdflib.Graph
object contains all the schema triples.
-
bottom_up
¶ Ancestry list starting from the child.
-
child
¶ Child of the ancestry.
-
parents
(class_iri)[source]¶ Finds the parents of a given class in the ancestry.
Parameters: class_iri – IRI of the RDFS class. Returns: List of class IRIs
-
top_down
¶ Reverse of the bottom_up attribute.
-
class
oldman.core.model.attribute.
Entry
(saved_value=None)[source]¶ Bases:
object
Mutable.
TODO: describe
-
current_value
¶
-
-
class
oldman.core.model.attribute.
OMAttribute
(metadata, value_format)[source]¶ Bases:
object
An
OMAttribute
object corresponds to a JSON-LD term that refers to a RDF property.TODO: update the documentation. No direct access to the resource_manager anymore (indirect through the resource).
Technically, the name of the
OMAttribute
object is a JSON-LD term, namely “a short-hand string that expands to an IRI or a blank node identifier” (cf. the JSON-LD standard) which corresponds here to a RDF property (seeOMProperty
).In JSON-LD, the same RDF property may correspond to multiple JSON-LD terms that have different metadata. For instance, a foaf:Person resource may have two attributes for its bio in English and in French. These attributes have two different languages but use the same property bio:olb. Look at the quickstart example to see it in practice.
An
OMAttribute
object manages the values of everyResource
object that depends on a givenModel
object.Each value may be :
- None;
- The Python equivalent for a RDF literal (double, string, date, etc.);
- An IRI;
- A collection (set, list and dict) of these types.
Parameters: - metadata –
OMAttributeMetadata
object. - value_format –
ValueFormat
object that validates the format of values and converts RDF values into regular Python objects.
-
check_validity
(resource, is_end_user=True)[source]¶ Raises an
OMEditError
exception if the attribute value assigned to a resource is invalid.Parameters: - resource –
Resource
object. - is_end_user – False when an authorized user (not a regular end-user) wants to force some rights. Defaults to True.
- resource –
-
check_value
(value)[source]¶ Checks a new when assigned.
Raises an
oldman.exception.OMAttributeTypeCheckError
exception if the value is invalid.Parameters: value – collection or atomic value.
-
container
¶ JSON-LD container (“@set”, “@list”, “@language” or “@index”). May be None.
-
diff
(resource)[source]¶ Gets out the former value that has been replaced.
TODO: update this comment
Parameters: resource – Resource
object.Returns: The former and new attribute values.
-
get
(resource)[source]¶ Gets the attribute value of a resource.
Parameters: resource – Resource
object.Returns: Atomic value or a generator.
-
get_lightly
(resource)[source]¶ Gets the attribute value of a resource in a lightweight manner.
By default, behaves exactly like
get()
. See the latter function for further details.
-
has_value
(resource)[source]¶ Tests if the resource attribute has a non-None value.
Parameters: resource – Resource
object.Returns: False if the value is None.
-
is_read_only
¶ True if the property cannot be modified by regular end-users.
-
is_required
¶ True if its property is required.
-
is_valid
(resource, is_end_user=True)[source]¶ Tests if the attribute value assigned to a resource is valid.
See
check_validity()
for further details.Returns: False if the value assigned to the resource is invalid and True otherwise.
-
is_write_only
¶ True if the property cannot be accessed by regular end-users.
-
jsonld_type
¶ JSON-LD type (datatype IRI or JSON-LD keyword). May be None.
-
language
¶ Its language if localized.
-
name
¶ Its name as an attribute.
-
om_property
¶ OMProperty
to which it belongs.
-
other_attributes
¶ Other
OMAttribute
objects of the same property.
-
receive_storage_ack
(resource)[source]¶ Clears the former value that has been replaced.
TODO: update this description.
Parameters: resource – Resource
object.
-
reversed
¶ True if the object and subject in RDF triples should be reversed.
-
set
(resource, value)[source]¶ Sets the attribute value of a resource.
Parameters: - resource –
Resource
object. - value – Its value for this attribute.
- resource –
-
to_nt
(resource)[source]¶ Converts its current attribute value to N-Triples (NT) triples.
Relies on
value_to_nt()
.Parameters: resource – Resource
object.Returns: N-Triples serialization of its attribute value.
-
update_from_graph
(resource, sub_graph, initial=False)[source]¶ Updates a resource attribute value by extracting the relevant information from a RDF graph.
Parameters: - resource –
Resource
object. - sub_graph –
rdflib.Graph
object containing the value to extract. - initial – True when the value is directly from the datastore. Defaults to False.
- resource –
-
value_format
¶ ValueFormat
object that validates the format of values and converts RDF values into regular Python objects.
-
class
oldman.core.model.attribute.
OMAttributeMetadata
(name, property, language, jsonld_type, container, reversed)¶ Bases:
tuple
-
container
¶ Alias for field number 4
-
jsonld_type
¶ Alias for field number 3
-
language
¶ Alias for field number 2
-
name
¶ Alias for field number 0
-
property
¶ Alias for field number 1
-
reversed
¶ Alias for field number 5
-
-
class
oldman.core.model.attribute.
ObjectOMAttribute
(metadata, value_format)[source]¶ Bases:
oldman.core.model.attribute.OMAttribute
An
ObjectOMAttribute
object is anOMAttribute
object that depends on an owl:ObjectProperty.
-
class
oldman.core.model.manager.
ModelManager
(schema_graph=None, attr_extractor=None)[source]¶ Bases:
object
TODO: update this documentation
The model_manager creates and registers
Model
objects.Internally, it owns a
ModelRegistry
object.Parameters: - schema_graph –
rdflib.Graph
object containing all the schema triples. - data_store –
DataStore
object. - attr_extractor –
OMAttributeExtractor
object that will extractOMAttribute
for generating newModel
objects. Defaults to a new instance ofOMAttributeExtractor
.
-
find_models_and_types
(type_set)[source]¶ See
oldman.model.registry.ModelRegistry.find_models_and_types()
.
-
include_reversed_attributes
¶ Is True if at least one of its models use some reversed attributes.
-
models
¶ TODO: describe.
-
non_default_models
¶ TODO: describe.
-
schema_graph
¶
- schema_graph –
-
class
oldman.core.model.model.
Model
(name, class_iri, ancestry_iris, context, om_attributes, accept_new_blank_nodes, local_context=None)[source]¶ Bases:
object
A
Model
object represents a RDFS class on the Python side.TODO: update this documentation
It gathers
OMAttribute
objects and Python methods which are made available toResource
objects that are instances of its RDFS class.It also creates and retrieves
Resource
objects that are instances of its RDFS class. It manages anIriGenerator
object.Model creation
Model
objects are normally created by aResourceManager
object. Please use theoldman.resource.manager.ResourceManager.create_model()
method for creating newModel
objects.Parameters: - name – Model name. Usually corresponds to a JSON-LD term or to a class IRI.
- class_iri – IRI of the RDFS class represented by this
Model
object. - ancestry_iris – ancestry of the attribute class_iri. Each instance of class_iri is also instance of these classes.
- context – An IRI, a list or a dict that describes the JSON-LD context. See http://www.w3.org/TR/json-ld/#the-context for more details.
- om_attributes – dict of
OMAttribute
objects. Keys are their names. - accept_new_blank_nodes – TODO: describe.
- methods – dict of Python functions that takes as first argument a
Resource
object. Keys are the method names. Defaults to {}. TODO: remove?? - local_context – TODO: describe.
-
accept_new_blank_nodes
¶ TODO: describe. Useful for knowing if a bnode ID of a resource is temporary or maybe not.
-
access_attribute
(name)[source]¶ Gets an
OMAttribute
object.Used by the
Resource
class but an end-user should not need to call it.Parameters: name – Name of the attribute. Returns: The corresponding OMAttribute
object.
-
ancestry_iris
¶ IRIs of the ancestry of the attribute class_iri.
-
class_iri
¶ IRI of the class IRI the model refers to.
-
context
¶ An IRI, a list or a dict that describes the JSON-LD context. See http://www.w3.org/TR/json-ld/#the-context for more details.
Official context that will be included in the representation.
-
has_reversed_attributes
¶ Is True if one of its attributes is reversed.
-
is_subclass_of
(model)[source]¶ Returns True if its RDFS class is a sub-class (rdfs:subClassOf) of the RDFS class of another model.
Parameters: model – Model
object to compare with.Returns: True if is a sub-class of the other model, False otherwise.
-
local_context
¶ Context available locally (but not to external consumer). TODO: describe further
-
methods
¶ Models does not support methods by default.
-
name
¶ Name attribute.
-
om_attributes
¶ dict of
OMAttribute
objects. Keys are their names.
-
class
oldman.core.model.property.
OMProperty
(property_iri, supporter_class_iri, is_required=False, read_only=False, write_only=False, reversed=False, cardinality=None, property_type=None, domains=None, ranges=None, link_class_iri=None)[source]¶ Bases:
object
An
OMProperty
object represents the support of a RDF property by a RDFS class.TODO: check this documentation after the removal of the resource_manager.
It gathers some
OMAttribute
objects (usually one).An
OMProperty
object is in charge of generating itsOMAttribute
objects according to the metadata that has been extracted from the schema and JSON-LD context.A property can be reversed: the
Resource
object to which theOMAttribute
objects will be (indirectly) attached is then the object of this property, not its subject (?o ?p ?s).Consequently, two
OMProperty
objects can refer to the same RDF property when one is reversed while the second is not.Parameters: - property_iri – IRI of the RDF property.
- supporter_class_iri – IRI of the RDFS class that supports the property.
- is_required – If True instances of the supporter class must assign a value to this property for being valid. Defaults to False.
- read_only – If True, the value of the property cannot be modified by a regular end-user. Defaults to False.
- write_only – If True, the value of the property cannot be read by a regular end-user. Defaults to False.
- reversed – If True, the property is reversed. Defaults to False.
- cardinality – Defaults to None. Not yet supported.
- property_type – String. In OWL, a property is either a DatatypeProperty or an ObjectProperty. Defaults to None (unknown).
- domains – Set of class IRIs that are declared as the RDFS domain of the property. Defaults to set().
- ranges – Set of class IRIs that are declared as the RDFS range of the property. Defaults to set().
- link_class_iri – TODO: describe.
-
add_attribute_metadata
(name, jsonld_type=None, language=None, container=None, reversed=False)[source]¶ Adds metadata about a future
OMAttribute
object.Parameters: - name – JSON-LD term representing the attribute.
- jsonld_type – JSON-LD type (datatype IRI or JSON-LD keyword). Defaults to None.
- language – Defaults to None.
- container – JSON-LD container (“@set”, “@list”, “@language” or “@index”). Defaults to None.
- reversed – True if the object and subject in RDF triples should be reversed. Defaults to False.
-
add_domain
(domain)[source]¶ Declares a RDFS class as part of the domain of the property.
Parameters: domain – IRI of RDFS class.
-
add_range
(p_range)[source]¶ Declares a RDFS class as part of the range of the property.
Parameters: p_range – IRI of RDFS class.
-
default_datatype
¶ IRI that is the default datatype of the property.
May be None (if not defined or if the property is an owl:ObjectProperty)
-
domains
¶ Set of class IRIs that are declared as the RDFS domain of the property.
-
generate_attributes
(attr_format_selector)[source]¶ Generates its
OMAttribute
objects.Can be called only once. When called a second time, raises an
OMAlreadyGeneratedAttributeError
exception.Parameters: attr_format_selector – ValueFormatSelector
object.
-
iri
¶ IRI of RDF property.
-
is_read_only
¶ True if the property cannot be modified by regular end-users.
-
is_required
¶ True if the property is required.
-
is_write_only
¶ True if the property cannot be accessed by regular end-users.
-
link_class_iri
¶ TODO: describe
-
om_attributes
¶ Set of
OMAttribute
objects that depends on this property.
-
ranges
¶ Set of class IRIs that are declared as the RDFS range of the property.
-
reversed
¶ True if the property is reversed (?o ?p ?s).
-
supporter_class_iri
¶ IRI of the RDFS class that supports the property.
-
type
¶ The property can be a owl:DatatypeProperty (“datatype”) or an owl:ObjectProperty (“object”). Sometimes its type is unknown (None).
-
class
oldman.core.model.registry.
ModelRegistry
[source]¶ Bases:
object
A
ModelRegistry
object registers theModel
objects.Its main function is to find and order models from a set of class IRIs (this ordering is crucial when creating new
Resource
objects). Seefind_models_and_types()
for more details.-
default_model
¶
-
find_models_and_types
(type_set)[source]¶ Finds the leaf models from a set of class IRIs and orders them. Also returns an ordered list of the RDFS class IRIs that come from type_set or were deduced from it.
Leaf model ordering is important because it determines:
- the IRI generator to use (the one of the first model);
- method inheritance priorities between leaf models.
Resulting orderings are cached.
Parameters: type_set – Set of RDFS class IRIs. Returns: An ordered list of leaf Model
objects and an ordered list of RDFS class IRIs.
-
get_model
(class_name_or_iri)[source]¶ Gets a
Model
object.Parameters: class_name_or_iri – Name or IRI of a RDFS class Returns: A Model
object or None if not found
-
model_names
¶ Names of the registered models.
-
models
¶
-
non_default_models
¶ Non-default models.
-
-
class
oldman.core.parsing.schema.attribute.
OMAttributeExtractor
(property_extractors=None, attr_md_extractors=None, use_hydra=True, use_jsonld_context=True)[source]¶ Bases:
object
Extracts
OMAttribute
objects from the schema and the JSON-LD context.Extensible in two ways:
- New
OMPropertyExtractor
objects (new RDF vocabularies); - New
OMAttributeMdExtractor
objects (e.g. JSON-LD context); - New
ValueFormat
objects. See itsvalue_format_registry
attribute.
Parameters: - property_extractors – Defaults to [].
- attr_md_extractors – Defaults to [].
- use_hydra – Defaults to True.
- use_jsonld_context – Defaults to True.
-
extract
(class_iri, type_iris, context_js, schema_graph)[source]¶ Extracts metadata and generates
OMProperty
andOMAttribute
objects.Parameters: - class_iri – IRI of RDFS class of the future
Model
object. - type_iris – Ancestry of the RDFS class.
- context_js – the JSON-LD context.
- schema_graph –
rdflib.graph.Graph
object.
Returns: dict of
OMAttribute
objects.- class_iri – IRI of RDFS class of the future
-
value_format_registry
¶ ValueFormatRegistry
object.
- New
-
class
oldman.core.parsing.schema.attribute.
ValueFormatRegistry
(special_properties=None, include_default_datatypes=True, include_well_known_properties=True)[source]¶ Bases:
object
Finds the
ValueFormat
object that corresponds to aOMAttributeMetadata
object.New
ValueFormat
objects can be added, for supporting:- Specific properties (eg. foaf:mbox and
EmailValueFormat
); - Other datatypes, as defined in the JSON-LD context or the RDFS domain or range (eg. xsd:string).
Parameters: - special_properties – Defaults to {}.
- include_default_datatypes – Defaults to True.
- include_well_known_properties – Defaults to True.
-
add_datatype
(datatype_iri, value_format)[source]¶ Registers a
ValueFormat
object for a given datatype.Parameters: - datatype_iri – IRI of the datatype.
- value_format –
ValueFormat
object.
- Specific properties (eg. foaf:mbox and
-
class
oldman.core.parsing.schema.context.
JsonLdContextAttributeMdExtractor
[source]¶ Bases:
oldman.core.parsing.schema.context.OMAttributeMdExtractor
OMAttributeMdExtractor
objects that extract attribute names and datatypes from the JSON-LD context.
-
class
oldman.core.parsing.schema.property.
HydraPropertyExtractor
[source]¶ Bases:
oldman.core.parsing.schema.property.OMPropertyExtractor
OMPropertyExtractor
objects that support the Hydra vocabulary.- Currently, this class supports:
-
class
oldman.core.parsing.schema.property.
OMPropertyExtractor
[source]¶ Bases:
object
An
OMPropertyExtractor
object generates and updatesOMProperty
objects from the schema RDF graph.This class is generic and must derived for supporting various RDF vocabularies.
-
update
(om_properties, class_iri, type_iris, schema_graph)[source]¶ Generates new
OMProperty
objects or updates them from the schema graph.Parameters: - om_properties – dict of
OMProperty
objects indexed by their IRIs and their reverse status. - class_iri – IRI of RDFS class of the future
Model
object. - type_iris – Ancestry of the RDFS class.
- schema_graph –
rdflib.graph.Graph
object.
Returns: Updated dict
OMProperty
objects.- om_properties – dict of
-
-
class
oldman.core.resource.reference.
ResourceReference
(subject_resource, attribute, object_resource_or_iri)[source]¶ Bases:
object
TODO: explain
“Subject” and “object” adjectives can be ROUGHLY understood like “subject predicate object”.
By roughly, we mean that we ignore the effect of “inverse property” (an attribute roughly corresponds to a predicate even in practice it can refer to an inverse predicate; we don’t make the distinction here).
-
attribute
¶
-
is_bound_to_object_resource
¶
-
object_iri
¶
-
subject_resource
¶
-
-
class
oldman.core.resource.resource.
Resource
(id, model_manager, session, types=None, is_new=True, former_types=None, **kwargs)[source]¶ Bases:
object
A
Resource
object is a subject-centric representation of a Web resource. A set ofResource
objects is equivalent to a RDF graph.In RDF, a resource is identified by an IRI (globally) or a blank node (locally). Because blank node support is complex and limited (
rdflib.plugins.stores.sparqlstore.SPARQLStore
stores do not support them), everyResource
object has an IRI.This IRI is either given or generated by a
IriGenerator
object. Some generators generate recognizable skolem IRIs that are treated as blank nodes when the resource is serialized into JSON, JSON-LD or another RDF format (for external consumption).A resource is usually instance of some RDFS classes. These classes are grouped in its attribute types.
Model
objects are found from these classes, by calling the methodoldman.resource.manager.ResourceManager.find_models_and_types()
. Models give access to Python methods and toOMAttribute
objects. Their ordering determines inheritance priorities. The main model is the first one of this list.Values of
OMAttribute
objects are accessible and modifiable like ordinary Python attribute values. However, these values are checked so someOMAccessError
orOMEditError
errors may be raised.This abstract class accepts two concrete classes:
StoreResource
andClientResource
. The former is serializable and can be saved directly by the datastore while the latter has to be converted into aStoreResource
so as to be saved.Example:
>>> alice = StoreResource(model_manager, data_store, types=["http://schema.org/Person"], name=u"Alice") >>> alice.id u'http://localhost/persons/1' >>> alice.name u'Alice' >>> alice.save() >>> alice.name = "Alice A." >>> print alice.to_jsonld() { "@context": "http://localhost/person.jsonld", "id": "http://localhost/persons/1", "types": [ "http://schema.org/Person" ], "name": "Alice A." } >>> alice.name = 5 oldman.exception.OMAttributeTypeCheckError: 5 is not a (<type 'str'>, <type 'unicode'>)
Resource creation
Resource
objects are normally created by aModel
or aResourceManager
object. Please use the methodsoldman.model.model.Model.create()
,oldman.model.Model.new()
,oldman.resource.manager.ResourceManager.create()
oroldman.resource.manager.ResourceManager.new()
for creating newResource
objects.Parameters: - id – TODO:describe.
- model_manager –
ModelManager
object. Gives access to its models. - types – IRI list or set of the RDFS classes the resource is instance of. Defaults to set().
- is_new – When is True and id given, checks that the IRI is not already existing in the data_store. Defaults to True.
- former_types – IRI list or set of the RDFS classes the resource was instance of. Defaults to set().
- kwargs – values indexed by their attribute names.
TODO: update this comment!!!!!
-
add_type
(additional_type)[source]¶ Declares that the resource is instance of another RDFS class.
Note that it may introduce a new model to the list and change its ordering.
Parameters: additional_type – IRI or JSON-LD term identifying a RDFS class.
-
attributes
¶ Returns: An ordered list of list of OMAttribute
objects.
-
check_validity
(is_end_user=True)[source]¶ Checks its validity.
Raises an
oldman.exception.OMEditError
exception if invalid.
-
context
¶ An IRI, a list or a dict that describes the JSON-LD context.
Derived from
oldman.model.Model.context
attributes.
-
former_non_model_types
¶ RDFS classes that were not associated to a Model.
-
former_types
¶ Not for end-users
-
get_lightly
(attribute_name)[source]¶ If the attribute corresponds to an owl:ObjectProperty, returns a IRI or None. Otherwise (if is a datatype), returns the value.
Not for end-users!
Gets a related Resource through its session.
If cannot get the resource, return its IRI.
-
id
¶ IRI that identifies the resource.
-
in_same_document
(other_resource)[source]¶ Tests if two resources have the same hash-less IRI.
Returns: True if these resources are in the same document.
-
is_blank_node
()[source]¶ Tests if id.iri is a skolem IRI and should thus be considered as a blank node.
See
is_blank_node()
for further details.Returns: True if id.iri is a locally skolemized IRI.
-
is_instance_of
(model)[source]¶ Tests if the resource is instance of the RDFS class of the model.
Parameters: model – Model
object.Returns: True if the resource is instance of the RDFS class.
-
is_new
¶ True if the resource has never been saved.
-
is_valid
()[source]¶ Tests if the resource is valid.
Returns: False if the resource is invalid, True otherwise.
-
local_context
¶ Context that is locally accessible but that may not be advertised in the JSON-LD serialization.
-
model_manager
¶ ModelManager
object. Gives access to theModel
objects.
-
models
¶ TODO: describe
-
non_model_types
¶ RDFS classes that are not associated to a Model.
-
notify_reference
(reference, object_resource=None, object_iri=None)[source]¶ Not for end-users!
TODO: describe
-
receive_storage_ack
(id)[source]¶ Receives the permanent ID assigned by the store. Useful when the permanent ID is given by an external server.
Replaces the temporary ID of the resource.
-
to_dict
(remove_none_values=True, include_different_contexts=False, ignored_iris=None)[source]¶ Serializes the resource into a JSON-like dict.
Parameters: - remove_none_values – If True, None values are not inserted into the dict. Defaults to True.
- include_different_contexts – If True local contexts are given to sub-resources. Defaults to False.
- ignored_iris – List of IRI of resources that should not be included in the dict. Defaults to set().
Returns: A dict describing the resource.
-
to_json
(remove_none_values=True, ignored_iris=None)[source]¶ Serializes the resource into pure JSON (not JSON-LD).
Parameters: - remove_none_values – If True, None values are not inserted into the dict. Defaults to True.
- ignored_iris – List of IRI of resources that should not be included in the dict. Defaults to set().
Returns: A JSON-encoded string.
-
to_jsonld
(remove_none_values=True, include_different_contexts=False, ignored_iris=None)[source]¶ Serializes the resource into JSON-LD.
Parameters: - remove_none_values – If True, None values are not inserted into the dict. Defaults to True.
- include_different_contexts – If True local contexts are given to sub-resources. Defaults to False.
- ignored_iris – List of IRI of resources that should not be included in the dict. Defaults to set().
Returns: A JSON-LD encoded string.
-
to_rdf
(rdf_format='turtle')[source]¶ Serializes the resource into RDF.
Parameters: rdf_format – content-type or keyword supported by RDFlib. Defaults to “turtle”. Returns: A string in the chosen RDF format.
-
types
¶ IRI list of the RDFS classes the resource is instance of.
-
update
(full_dict, allow_new_type=False, allow_type_removal=False)[source]¶ Updates the resource from a flat dict.
By flat, we mean that sub-resources are only represented by their IRIs: there is no nested sub-object structure.
This dict is supposed to be exhaustive, so absent value is removed. Some sub-resources may thus be deleted like if there were a cascade deletion.
Parameters: - full_dict – Flat dict containing the attribute values to update.
- allow_new_type –
If True, new types can be added. Please keep in mind that type change can:
- Modify the behavior of the resource by changing its model list.
- Interfere with the SPARQL requests using instance tests.
If enabled, this may represent a major security concern. Defaults to False.
- allow_type_removal – If True, new types can be removed. Same security concerns than above. Defaults to False.
Returns: The
Resource
object itself.
-
update_from_graph
(subgraph, initial=False, allow_new_type=False, allow_type_removal=False)[source]¶ Similar to
full_update()
but with a RDF graph instead of a Python dict.Parameters: - subgraph –
rdflib.Graph
object containing the full description of the resource. - initial – True when the subgraph comes from the data_graph and is thus used
to load
Resource
object from the triple store. Defaults to False. - allow_new_type – If True, new types can be added. Defaults to False. See
full_update()
for explanations about the security concerns. - allow_type_removal – If True, new types can be removed. Same security concerns than above. Defaults to False.
Returns: The
Resource
object itself.- subgraph –
-
class
oldman.core.session.tracker.
BasicResourceTracker
[source]¶ Bases:
oldman.core.session.tracker.ResourceTracker
-
modified_resources
¶ TODO: re-implement it
-
receive_reference
(reference, object_resource=None, object_iri=None)[source]¶ TODO: better implement it
-
resources_to_delete
¶
-
-
oldman.core.utils.crud.
create_blank_nodes
(session, graph, bnode_subjects, hashless_iri=None, collection_iri=None)[source]¶ TODO: comment
-
oldman.core.utils.sparql.
build_query_part
(verb_and_vars, subject_term, lines)[source]¶ Builds a SPARQL query.
Parameters: - verb_and_vars – SPARQL verb and variables.
- subject_term – Common subject term.
- lines – Lines to insert into the WHERE block.
Returns: A SPARQL query.
-
oldman.core.utils.sparql.
build_update_query_part
(verb, subject, lines)[source]¶ Builds a SPARQL Update query.
Parameters: - verb – SPARQL verb.
- subject – Common subject term.
- lines – Lines to insert into the WHERE block.
Returns: A SPARQL Update query.
-
oldman.core.utils.sparql.
parse_graph_safely
(graph, *args, **kwargs)[source]¶ Skolemizes the input source if the graph uses a
rdflib.plugins.stores.sparqlstore.SPARQLUpdateStore
object.Parameters: - graph –
rdflib.graph.Graph
object. - args – Argument list to transmit to
rdflib.graph.Graph.parse()
. - kwargs – Argument dict to transmit to
rdflib.graph.Graph.parse()
.
Returns: The updated
rdflib.graph.Graph
object.- graph –
-
class
oldman.core.validation.value_format.
AnyValueFormat
[source]¶ Bases:
oldman.core.validation.value_format.ValueFormat
Accepts any value.
-
class
oldman.core.validation.value_format.
EmailValueFormat
[source]¶ Bases:
oldman.core.validation.value_format.TypedValueFormat
Checks that the value is an email address.
-
class
oldman.core.validation.value_format.
HexBinaryFormat
[source]¶ Bases:
oldman.core.validation.value_format.TypedValueFormat
Checks that the value is a hexadecimal string.
-
class
oldman.core.validation.value_format.
IRIValueFormat
[source]¶ Bases:
oldman.core.validation.value_format.ValueFormat
Checks that the value is an IRI.
-
class
oldman.core.validation.value_format.
NegativeTypedValueFormat
(types)[source]¶ Bases:
oldman.core.validation.value_format.TypedValueFormat
Checks that the value is a negative number.
-
class
oldman.core.validation.value_format.
NonNegativeTypedValueFormat
(types)[source]¶ Bases:
oldman.core.validation.value_format.TypedValueFormat
Checks that the value is a non-negative number.
-
class
oldman.core.validation.value_format.
NonPositiveTypedValueFormat
(types)[source]¶ Bases:
oldman.core.validation.value_format.TypedValueFormat
Checks that the value is a non-positive number.
-
class
oldman.core.validation.value_format.
PositiveTypedValueFormat
(types)[source]¶ Bases:
oldman.core.validation.value_format.TypedValueFormat
Checks that the value is a positive number.
-
class
oldman.core.validation.value_format.
TypedValueFormat
(types)[source]¶ Bases:
oldman.core.validation.value_format.ValueFormat
Checks that the value is of a given type.
Parameters: types – Supported Python types.
-
class
oldman.core.validation.value_format.
ValueFormat
[source]¶ Bases:
object
A
ValueFormat
object checks the values and converts rdflib.term.Identifier objects into Python objects.
-
exception
oldman.core.validation.value_format.
ValueFormatError
[source]¶ Bases:
exceptions.Exception
Invalid format detected.
Submodules¶
oldman.core.common module¶
oldman.core.exception module¶
-
exception
oldman.core.exception.
AlreadyAllocatedModelError
[source]¶ Bases:
oldman.core.exception.ModelGenerationError
The class IRI or the short name of a new model is already allocated.
-
exception
oldman.core.exception.
ModelGenerationError
[source]¶ Bases:
oldman.core.exception.OMError
Error when generating a new model.
-
exception
oldman.core.exception.
OMAccessError
[source]¶ Bases:
oldman.core.exception.OMUserError
Error when accessing objects.
-
exception
oldman.core.exception.
OMAlreadyDeclaredDatatypeError
[source]¶ Bases:
oldman.core.exception.OMAttributeDefError
At least two different datatypes for the same attribute.
You may check the possible datatype inherited from the property (rdfs:range) and the one specified in the JSON-LD context.
-
exception
oldman.core.exception.
OMAlreadyGeneratedAttributeError
[source]¶ Bases:
oldman.core.exception.OMInternalError
Attribute generation occurs only once per SupportedProperty.
You should not try to add metadata or regenerate after that.
-
exception
oldman.core.exception.
OMAttributeAccessError
[source]¶ Bases:
oldman.core.exception.OMAccessError
When such an attribute cannot be identified (is not supported or no model has been found).
-
exception
oldman.core.exception.
OMAttributeDefError
[source]¶ Bases:
oldman.core.exception.OMSchemaError
Inconsistency in the definition of a model class attribute.
-
exception
oldman.core.exception.
OMAttributeTypeCheckError
[source]¶ Bases:
oldman.core.exception.OMEditError
The value assigned to the attribute has wrong type.
-
exception
oldman.core.exception.
OMBadRequestException
[source]¶ Bases:
oldman.core.exception.OMControllerException
TODO: describe
Error: 400
-
exception
oldman.core.exception.
OMClassInstanceError
[source]¶ Bases:
oldman.core.exception.OMAccessError
The object is not an instance of the expected RDFS class.
-
exception
oldman.core.exception.
OMControllerException
[source]¶ Bases:
exceptions.Exception
TODO: describe
-
exception
oldman.core.exception.
OMDifferentHashlessIRIError
[source]¶ Bases:
oldman.core.exception.OMIriError
,oldman.core.exception.OMEditError
When creating or updating an object with a different hashless IRI is forbidden.
Blank nodes are not concerned.
-
exception
oldman.core.exception.
OMEditError
[source]¶ Bases:
oldman.core.exception.OMUserError
Runtime errors, occuring when editing or creating an object.
-
exception
oldman.core.exception.
OMError
[source]¶ Bases:
exceptions.Exception
Root of exceptions generated by the oldman package expected HTTP ones.
-
exception
oldman.core.exception.
OMExpiredMethodDeclarationTimeSlotError
[source]¶ Bases:
oldman.core.exception.ModelGenerationError
All methods must be declared before creating a first model.
-
exception
oldman.core.exception.
OMForbiddenOperationException
[source]¶ Bases:
oldman.core.exception.OMControllerException
No chance TODO: improve
-
exception
oldman.core.exception.
OMForbiddenSkolemizedIRIError
[source]¶ Bases:
oldman.core.exception.OMEditError
When updating a skolemized IRI from the local domain is forbidden.
-
exception
oldman.core.exception.
OMHashIriError
[source]¶ Bases:
oldman.core.exception.OMAccessError
A hash IRI has been given instead of a hash-less IRI.
-
exception
oldman.core.exception.
OMInternalError
[source]¶ Bases:
oldman.core.exception.OMError
Do not expect it.
-
exception
oldman.core.exception.
OMIriError
[source]¶ Bases:
oldman.core.exception.OMRuntimeError
Root class for problems with an IRI (generation, validation).
-
exception
oldman.core.exception.
OMMethodNotAllowedException
[source]¶ Bases:
oldman.core.exception.OMControllerException
405
-
exception
oldman.core.exception.
OMNotAcceptableException
[source]¶ Bases:
oldman.core.exception.OMControllerException
406 Not Acceptable
TODO: indicate the content-type
-
exception
oldman.core.exception.
OMObjectNotFoundError
[source]¶ Bases:
oldman.core.exception.OMAccessError
When the object is not found.
-
exception
oldman.core.exception.
OMPropertyDefError
[source]¶ Bases:
oldman.core.exception.OMSchemaError
Inconsistency in the definition of a supported property.
-
exception
oldman.core.exception.
OMPropertyDefTypeError
[source]¶ Bases:
oldman.core.exception.OMPropertyDefError
A RDF property cannot be both an ObjectProperty and a DatatypeProperty.
-
exception
oldman.core.exception.
OMReadOnlyAttributeError
[source]¶ Bases:
oldman.core.exception.OMEditError
End-users are not allowed to edit this attribute.
-
exception
oldman.core.exception.
OMRequiredAuthenticationException
[source]¶ Bases:
oldman.core.exception.OMControllerException
Try again TODO: improve
-
exception
oldman.core.exception.
OMRequiredHashlessIRIError
[source]¶ Bases:
oldman.core.exception.OMEditError
No hash-less IRI has been given.
-
exception
oldman.core.exception.
OMRequiredPropertyError
[source]¶ Bases:
oldman.core.exception.OMEditError
A required property has no value.
-
exception
oldman.core.exception.
OMReservedAttributeNameError
[source]¶ Bases:
oldman.core.exception.OMAttributeDefError
Some attribute names are reserved and should not be included in the JSON-LD context.
-
exception
oldman.core.exception.
OMResourceNotFoundException
[source]¶ Bases:
oldman.core.exception.OMControllerException
TODO: describe
-
exception
oldman.core.exception.
OMRuntimeError
[source]¶ Bases:
oldman.core.exception.OMError
Error at runtime after the initialization.
-
exception
oldman.core.exception.
OMSPARQLError
[source]¶ Bases:
oldman.core.exception.OMAccessError
Invalid SPARQL query given.
-
exception
oldman.core.exception.
OMSPARQLParseError
[source]¶ Bases:
oldman.core.exception.OMInternalError
Invalid SPARQL request.
-
exception
oldman.core.exception.
OMSchemaError
[source]¶ Bases:
oldman.core.exception.ModelGenerationError
Error in the schema graph and/or the JSON-LD context.
-
exception
oldman.core.exception.
OMStoreError
[source]¶ Bases:
oldman.core.exception.OMRuntimeError
Error detected in the stored data.
-
exception
oldman.core.exception.
OMTemporaryIriError
[source]¶ Bases:
oldman.core.exception.OMEditError
When saving a Resource that has an attribute that points to a temporary IRI.
Bases:
oldman.core.exception.OMEditError
When updating a resource with new types without explicit authorization.
-
exception
oldman.core.exception.
OMUndeclaredClassNameError
[source]¶ Bases:
oldman.core.exception.ModelGenerationError
The name of the model class should be defined in the JSON-LD context.
-
exception
oldman.core.exception.
OMUniquenessError
[source]¶ Bases:
oldman.core.exception.OMEditError
Attribute uniqueness violation.
Example: IRI illegal reusing.
-
exception
oldman.core.exception.
OMUnsupportedUserIRIError
[source]¶ Bases:
oldman.core.exception.OMIriError
,oldman.core.exception.OMEditError
The IRI provided by the user is not supported.
-
exception
oldman.core.exception.
OMUserError
[source]¶ Bases:
oldman.core.exception.OMRuntimeError
Error when accessing or editing objects.
-
exception
oldman.core.exception.
OMWrongResourceError
[source]¶ Bases:
oldman.core.exception.OMEditError
Not updating the right object.
-
exception
oldman.core.exception.
UnsupportedDataStorageFeatureException
[source]¶ Bases:
oldman.core.exception.OMStoreError
Feature not supported by the data store.
oldman.core.id module¶
-
class
oldman.core.id.
OMId
(iri, is_permanent)[source]¶ TODO: explain why an ID object and not a simple IRI. An ID can be temporary.
Immutable data structure.
-
fragment
¶ TODO: explain
-
hashless_iri
¶ TODO: explain
-
iri
¶
-
is_blank_node
¶ TODO: explain
-
is_permanent
¶
-
-
class
oldman.core.id.
PermanentId
(iri)[source]¶ Bases:
oldman.core.id.OMId
TODO: explain
-
class
oldman.core.id.
TemporaryId
(suggested_hashless_iri=None, suggested_iri_fragment=None, collection_iri=None, can_remain_bnode=True)[source]¶ Bases:
oldman.core.id.OMId
TODO: describe
-
can_remain_bnode
¶ Returns True if is currently a blank node and may remain it before being stored.
-
collection_iri
¶
-
suggested_fragment
¶ TODO: explain
-
suggested_hashless_iri
¶ TODO: explain
-
oldman.core.vocabulary module¶
RDF vocabulary used by OldMan. Some of it is specific to OldMan.
TODO: replace these URNs by URLs.
Parent model prioritization
In RDF, a class is often the child of multiple classes. When the code inherited from these classes (common practise in Object-Oriented Programming) is conflicting, arbitration is necessary.
In this library, we provide a RDF vocabulary to declare priorities for each parent of a given child class. A priority statement is declared as follows:
?cls <urn:oldman:model:ordering:hasPriority> [
<urn:oldman:model:ordering:class> ?parent1 ;
<urn:oldman:model:ordering:priority> 2
].
By default, when no priority is declared for a pair (child, parent), its priority value is set to 0.
-
oldman.core.vocabulary.
NEXT_NUMBER_IRI
= 'urn:oldman:nextNumber'¶ Used to increment IRIs.
Module contents¶
oldman.storage package¶
Subpackages¶
-
class
oldman.storage.hydra.schema_adapter.
HydraSchemaAdapter
[source]¶ Bases:
object
Updates some Hydra patterns in the schema graph:
- hydra:Link: create a hydra:Class, subclass of the link range that support the same operations
-
class
oldman.storage.model.conversion.converter.
DirectMappingModelConverter
(client_to_store_mappings)[source]¶ Bases:
oldman.storage.model.conversion.converter.ModelConverter
-
class
oldman.storage.model.conversion.converter.
EquivalentModelConverter
(client_model, store_model)[source]¶ Bases:
oldman.storage.model.conversion.converter.DirectMappingModelConverter
TODO: describe
-
class
oldman.storage.model.conversion.entry.
ClientToStoreEntryExchanger
(conversion_manager, store, client_resource, store_resource, xstore_session)[source]¶ Bases:
oldman.storage.model.conversion.entry.EntryExchanger
-
target_subject_resource
¶
-
target_tracker
¶
-
-
class
oldman.storage.model.conversion.entry.
EntryExchanger
(client_resource, store_resource)[source]¶ Bases:
object
TODO: explain
-
target_subject_resource
¶
-
target_tracker
¶
-
-
class
oldman.storage.model.conversion.entry.
StoreToClientEntryExchanger
(conversion_manager, client_resource, store_resource, client_session, client_factory)[source]¶ Bases:
oldman.storage.model.conversion.entry.EntryExchanger
-
target_subject_resource
¶
-
target_tracker
¶
-
-
class
oldman.storage.model.conversion.manager.
ModelConversionManager
[source]¶ Bases:
object
TODO: describe and find a better name.
-
convert_store_to_client_resource
(store_resource, client_factory, client_tracker, update_local_client_resource=False)[source]¶ Parameters: - store_resource –
- client_factory –
- client_tracker –
- update_local_client_resource – FOR OTHER updates than the IRI!
Returns:
-
-
class
oldman.storage.model.manager.
StoreModelManager
(schema_graph=None, attr_extractor=None)[source]¶ Bases:
oldman.core.model.manager.ModelManager
-
create_model
(class_name_or_iri, context_iri_or_payload, store, iri_prefix=None, iri_fragment=None, iri_generator=None, untyped=False, incremental_iri=False, is_default=False, context_file_path=None)[source]¶ Creates a
StoreModel
object.TODO: remove data_store from the constructor!
To create it, they are three elements to consider:
- Its class IRI which can be retrieved from class_name_or_iri;
- Its JSON-LD context for mapping
OMAttribute
values to RDF triples; - The
IriGenerator
object that generates IRIs from newResource
objects.
The
IriGenerator
object is either:- directly given: iri_generator;
- created from the parameters iri_prefix, iri_fragment and incremental_iri.
Parameters: - class_name_or_iri – IRI or JSON-LD term of a RDFS class.
- context_iri_or_payload – dict, list or IRI that represents the JSON-LD context .
- iri_generator –
IriGenerator
object. If given, other iri_* parameters are ignored. - iri_prefix – Prefix of generated IRIs. Defaults to None.
If is None and no iri_generator is given, a
BlankNodeIriGenerator
is created. - iri_fragment – IRI fragment that is added at the end of generated IRIs. For instance, “me” adds “#me” at the end of the new IRI. Defaults to None. Has no effect if iri_prefix is not given.
- incremental_iri – If True an
IncrementalIriGenerator
is created instead of aRandomPrefixedIriGenerator
. Defaults to False. Has no effect if iri_prefix is not given. - context_file_path – TODO: describe.
-
-
class
oldman.storage.model.model.
StoreModel
(name, class_iri, ancestry_iris, context, om_attributes, id_generator, local_context=None)[source]¶ Bases:
oldman.core.model.model.Model
Parameters: - name – Model name. Usually corresponds to a JSON-LD term or to a class IRI.
- class_iri – IRI of the RDFS class represented by this
Model
object. - ancestry_iris – ancestry of the attribute class_iri. Each instance of class_iri is also instance of these classes.
- context – An IRI, a list or a dict that describes the JSON-LD context. See http://www.w3.org/TR/json-ld/#the-context for more details.
- om_attributes – dict of
OMAttribute
objects. Keys are their names. - id_generator –
IriGenerator
object that generates IRIs from newResource
objects. - methods – dict of Python functions that takes as first argument a
Resource
object. Keys are the method names. Defaults to {}. TODO: see if is still needed. - local_context – TODO: describe.
-
class
oldman.storage.store.cache.
ResourceCache
(cache_region)[source]¶ Bases:
object
A
ResourceCache
object cachesResource
objects.It interfaces a
dogpile.cache.region.CacheRegion
front-end object. If not None, cache_region must be already configured, i.e. mapped to a back-end (like Memcache or Redis). See the official list of back-ends supported by dogpile.cache.When cache_region is None, no effective caching is done. However, methods
get_resource()
,set_resource()
andremove_resource()
can still safely be called. They just have no effect.Parameters: cache_region – dogpile.cache.region.CacheRegion
object. This object must already be configured. Defaults to None (no cache).-
cache_region
¶ dogpile.cache.region.CacheRegion
object. May be None.
-
change_cache_region
(cache_region)[source]¶ Replaces the cache_region attribute.
Parameters: cache_region – dogpile.cache.region.CacheRegion
object. May be None.
-
get_resource
(iri, store_session)[source]¶ Gets a
Resource
object from the cache.Parameters: iri – IRI of the resource. Returns: Resource
object or None if not found.
-
invalidate_cache
()[source]¶ See
dogpile.cache.region.CacheRegion.invalidate()
.Cache invalidation
Please note that this method is not supported by some
dogpile.cache.api.CacheBackend
objects. In such a case, this method has no effect so entries must be removed explicitly from their keys.
-
remove_resource
(resource)[source]¶ Removes a
Resource
object from the cache.Indempotent (no problem if the
Resource
object is not the cache). Does nothing if cache_region is None.Parameters: resource – Resource
object to remove from the cache.
-
-
class
oldman.storage.store.http.
HttpStore
(schema_graph=None, cache_region=None, http_session=None)[source]¶ Bases:
oldman.storage.store.store.Store
Read only. No search feature.
-
class
oldman.storage.store.sparql.
SparqlStore
(data_graph, schema_graph=None, model_manager=None, union_graph=None, cache_region=None)[source]¶ Bases:
oldman.storage.store.store.Store
A
SPARQLStore
is aStore
object relying on a SPARQL 1.1 endpoint (Query and Update).Parameters: - data_graph –
rdflib.graph.Graph
object where all the non-schema resources are stored by default. - union_graph – Union of all the named graphs of a
rdflib.ConjunctiveGraph
or ardflib.Dataset
. Super-set of data_graph and may also include schema_graph. Defaults to data_graph. Read-only. - cache_region –
dogpile.cache.region.CacheRegion
object. This object must already be configured. Defaults to None (no cache). SeeResourceCache
for further details.
TODO: complete
-
check_and_repair_counter
(class_iri)[source]¶ Checks the counter of a given RDFS class and repairs (inits) it if needed.
Parameters: class_iri – RDFS class IRI.
-
extract_prefixes
(other_graph)[source]¶ Adds the RDF prefix (namespace) information from an other graph to the namespace of the data_graph. :param other_graph: rdflib.graph.Graph that some prefix information.
- data_graph –
-
class
oldman.storage.store.store.
Store
(model_manager, cache_region=None, accept_iri_generation_configuration=True, support_sparql=False)[source]¶ Bases:
object
A
Store
object manages CRUD operations onStoreResource
objects.In the future, non-CRUD operations may also be supported.
Manages the cache (
ResourceCache
object) ofStoreResource
object.Parameters: - model_manager – TODO: describe!!!
- cache_region –
dogpile.cache.region.CacheRegion
object. This object must already be configured. Defaults to None (no cache). SeeResourceCache
for further details. - accept_iri_generation_configuration – If False, the IRI generator cannot be configured by the user: it is imposed by the data store. Default to False.
-
check_and_repair_counter
(class_iri)[source]¶ Checks the counter of a given RDFS class and repairs (inits) it if needed.
Parameters: class_iri – RDFS class IRI.
-
create_model
(class_name_or_iri, context_iri_or_payload, iri_generator=None, iri_prefix=None, iri_fragment=None, incremental_iri=False, context_file_path=None)[source]¶ TODO: comment. Convenience function
-
exists
(resource_iri)[source]¶ Tests if the IRI of the resource is present in the data_store.
May raise an
UnsupportedDataStorageFeatureException
exception.Parameters: resource_iri – IRI of the Resource
object.Returns: True if exists.
-
filter
(store_session, types=None, hashless_iri=None, limit=None, eager=True, pre_cache_properties=None, **kwargs)[source]¶ Finds the
Resource
objects matching the given criteria.The kwargs dict can contains:
- regular attribute key-values ;
- the special attribute iri. If given,
get()
is called.
TODO: UPDATE THE COMMENT!
Parameters: - types – IRIs of the RDFS classes filtered resources must be instance of. Defaults to None.
- hashless_iri – Hash-less IRI of filtered resources. Defaults to None.
- limit – Upper bound on the number of solutions returned (e.g. SPARQL LIMIT). Positive integer. Defaults to None.
- eager – If True loads all the Resource objects within the minimum number of queries (e.g. one single SPARQL query). Defaults to True.
- pre_cache_properties – List of RDF ObjectProperties to pre-cache eagerly.
Their values (
Resource
objects) are loaded and added to the cache. Defaults to []. If given, eager must be True. Disabled if there is no cache.
Returns: A generator (if lazy) or a list (if eager) of
Resource
objects.
-
first
(store_session, types=None, hashless_iri=None, eager_with_reversed_attributes=True, pre_cache_properties=None, **kwargs)[source]¶ Gets the first
Resource
object matching the given criteria.The kwargs dict can contains regular attribute key-values.
TODO: UPDATE THE COMMENT!
Parameters: - types – IRIs of the RDFS classes filtered resources must be instance of. Defaults to None.
- hashless_iri – Hash-less IRI of filtered resources. Defaults to None.
- eager_with_reversed_attributes – Allow to Look eagerly for reversed RDF properties.
May cause some overhead for some
Resource
objects that do not have reversed attributes. Defaults to True. - pre_cache_properties – List of RDF ObjectProperties to pre-cache eagerly.
Their values (
Resource
objects) are loaded and added to the cache. Defaults to []. If given, eager must be True. Disabled if there is no cache.
Returns: A
Resource
object or None if no resource has been found.
-
flush
(resources_to_update, resources_to_delete, is_end_user)[source]¶ TODO: explain :param new_resources: :param resources_to_update: :param resources_to_delete: :return:
-
generate_instance_number
(class_iri)[source]¶ Generates a new incremented number for a given RDFS class IRI.
May raise an
UnsupportedDataStorageFeatureException
exception.Parameters: class_iri – RDFS class IRI. Returns: Incremented number.
-
get
(store_session, iri, types=None, eager_with_reversed_attributes=True)[source]¶ Gets the
Resource
object having the given IRI.The kwargs dict can contains regular attribute key-values.
When types are given, they are then checked. An
OMClassInstanceError
is raised if the resource is not instance of these classes.Parameters: - iri – IRI of the resource. Defaults to None.
- types – IRIs of the RDFS classes filtered resources must be instance of. Defaults to None.
Returns: A
StoreResource
object or None if no resource has been found.
-
classmethod
get_store
(name)[source]¶ Gets a
DataStore
object by its name.Parameters: name – store name. Returns: A ModelManager
object.
-
model_manager
¶ The
ModelManager
object.TODO: update
Necessary for creating new
StoreResource
objects and accessing toModel
objects.
-
name
¶ Randomly generated name. Useful for serializing resources.
-
reset_instance_counter
(class_iri)[source]¶ Reset the counter related to a given RDFS class.
For test purposes only.
Parameters: class_iri – RDFS class IRI.
-
resource_cache
¶ ResourceCache
object.
-
sparql_filter
(store_session, query)[source]¶ Finds the
Resource
objects matching a given query.Raises an
UnsupportedDataStorageFeatureException
exception if the SPARQL protocol is not supported by the concrete data_store.Parameters: query – SPARQL SELECT query where the first variable assigned corresponds to the IRIs of the resources that will be returned. Returns: A generator of Resource
objects.
Submodules¶
oldman.storage.id_generation module¶
-
class
oldman.storage.id_generation.
BlankNodePermanentIDGenerator
(hostname=u'localhost')[source]¶ Bases:
oldman.storage.id_generation.PrefixedUUIDPermanentIDGenerator
Generates skolem IRIs that denote blank nodes.
Parameters: hostname – Defaults to “localhost”.
-
class
oldman.storage.id_generation.
IncrementalIriGenerator
(prefix, store, class_iri, fragment=None)[source]¶ Bases:
oldman.storage.id_generation.PermanentIDGenerator
Generates IRIs with short numbers.
Beautiful but slow in concurrent settings. The number generation implies a critical section and a sequence of two SPARQL requests, which represents a significant bottleneck.
Parameters: - prefix – IRI prefix.
- store – TODO: describe.
- graph –
rdflib.Graph
object where to store the counter. - class_iri – IRI of the RDFS class of which new
Resource
objects are instance of. Usually corresponds to the class IRI of theModel
object that owns this generator. - fragment – IRI fragment to append to the hash-less IRI. Defaults to None.
-
class
oldman.storage.id_generation.
PermanentIDGenerator
(is_generating_blank_nodes)[source]¶ Bases:
object
An
PermanentIDGenerator
object generates theResource
objects.-
is_generating_blank_nodes
¶ TODO: remove
-
-
class
oldman.storage.id_generation.
PrefixedUUIDPermanentIDGenerator
(prefix, fragment=None, is_generating_blank_nodes=False)[source]¶ Bases:
oldman.storage.id_generation.PermanentIDGenerator
Uses a prefix, a fragment and a unique UUID1 number to generate IRIs.
Recommended generator because UUID1 is robust and fast (no DB access).
Parameters: - prefix – IRI prefix.
- fragment – IRI fragment to append to the hash-less IRI. Defaults to None.
-
class
oldman.storage.id_generation.
UUIDFragmentPermanentIDGenerator
[source]¶ Bases:
oldman.storage.id_generation.PermanentIDGenerator
Generates an hashed IRI from a hash-less IRI.
Its fragment is a unique UUID1 number.
oldman.storage.resource module¶
-
class
oldman.storage.resource.
StoreResource
(previous_id, model_manager, store, session, types=None, is_new=True, **kwargs)[source]¶ Bases:
oldman.core.resource.resource.Resource
StoreResource: resource manipulated by the data store.
End-users should not manipulate it.
Is serializable (pickable).
Parameters: - previous_id – TODO: describe (maybe a temporary one).
- model_manager –
ModelManager
object. Gives access to its models. - store –
Store
object. Store that has authority on this resource. - kwargs – Other parameters considered by the
Resource
constructor and values indexed by their attribute names.
-
classmethod
load_from_graph
(model_manager, store, session, iri, subgraph, is_new=True)[source]¶ Loads a new
StoreResource
object from a sub-graph.TODO: update the comments.
Parameters: - model_manager –
StoreModelManager
object. - iri – IRI of the resource.
- subgraph –
rdflib.Graph
object containing triples about the resource. - is_new – When is True and id given, checks that the IRI is not already existing in the union_graph. Defaults to True.
Returns: The
StoreResource
object created.- model_manager –
-
store
¶
oldman.storage.session module¶
-
class
oldman.storage.session.
CrossStoreSession
[source]¶ Bases:
oldman.core.session.session.Session
-
new
(id, store, types=None, hashless_iri=None, collection_iri=None, is_new=True, former_types=None, **kwargs)[source]¶ Creates a new
Resource
object without saving it in the data_store.The kwargs dict can contains regular attribute key-values that will be assigned to
OMAttribute
objects.TODO: update this doc
Parameters: - id – TODO: explain
- types – IRIs of RDFS classes the resource is instance of. Defaults to None.
Note that these IRIs are used to find the models of the resource
(see
find_models_and_types()
for more details). - hashless_iri – hash-less IRI that MAY be considered when generating an IRI for the new resource. Defaults to None. Ignored if id is given. Must be None if collection_iri is given.
- collection_iri – IRI of the controller to which this resource belongs. This information is used to generate a new IRI if no id is given. The IRI generator may ignore it. Defaults to None. Must be None if hashless_iri is given.
Returns: A new
Resource
object.
-
tracker
¶
-
-
class
oldman.storage.session.
DefaultCrossStoreSession
(store_selector)[source]¶ Bases:
oldman.storage.session.CrossStoreSession
TODO: explain because the name can be counter-intuitive
-
delete
(store_resource)[source]¶ TODO: describe.
Wait for the next flush() to remove the resource from the store.
-
tracker
¶
-
Module contents¶
Module Index, Index and Search Page.