From a108ad9fc307b37fdb87f3a8e958b650f46ec135 Mon Sep 17 00:00:00 2001 From: Helmut Merz Date: Fri, 15 Mar 2024 09:15:41 +0100 Subject: [PATCH] work in progress: rels --- scopes/interfaces.py | 11 ----------- scopes/storage/concept.py | 32 +++++++++++++++++++++++++++++--- scopes/storage/tracking.py | 2 +- 3 files changed, 30 insertions(+), 15 deletions(-) diff --git a/scopes/interfaces.py b/scopes/interfaces.py index 194e4f1..82cad03 100644 --- a/scopes/interfaces.py +++ b/scopes/interfaces.py @@ -24,17 +24,6 @@ class IContainer(ITraversable): and the value object (e.g. `parent´ and `name`) are stored correctly.""" -class IConcept(IContainer): - - def parents(*predicates): - """Return a sequence of `Triple`s in which this object is - referenced as `second`.""" - - def children(*predicates): - """Return a sequence of `Triple`s in which this object is - referenced as `first`.""" - - class IView(Interface): def __call__(): diff --git a/scopes/storage/concept.py b/scopes/storage/concept.py index daf7c94..ba0764a 100644 --- a/scopes/storage/concept.py +++ b/scopes/storage/concept.py @@ -3,23 +3,39 @@ """Core classes for concept map structure.""" from zope.interface import implementer -from scopes.interfaces import IConcept from scopes.storage.common import registerContainerClass, registry from scopes.storage.tracking import Container, Track -@implementer(IConcept) class Concept(Track): headFields = ['name'] + def parents(self, predicate=None): + return self.container.queryRels(second=self, predicate=predicate) + + def children(self, predicate=None): + return self.container.queryRels(first=self, predicate=predicate) + class Concepts(Container): insertOnChange = False indexes = None + + def queryRels(self, **crit): + pred = crit.get(predicate) + if pred is not None and isinstance(pred, ('string', 'bytes')): + crit['predicate'] = self.storage.getContainer('pred').queryLast(name=pred) + for k, v in crit.items: + if isinstance(v, Track): + crit[k] = v.uid + rels = self.storage.getContainer('rel') + return rels.query(**crit) + # implementation of relationships between concepts using RDF-like triples + class Predicate(Concept): prefix = 'pred' @@ -37,6 +53,15 @@ class Triple(Track): headFields = ['first', 'second', 'predicate'] prefix = 'rel' + def getFirst(self): + return self.container.storage.getItem(self.first) + + def getSecond(self): + return self.container.storage.getItem(self.second) + + def getPredicate(self): + return self.container.storage.getItem(self.second) + @registerContainerClass class Rels(Container): @@ -47,6 +72,8 @@ class Rels(Container): tableName = 'rels' insertOnChange = False + defaultPredicate = 'standard' + # types stuff @@ -75,7 +102,6 @@ class Types(Concepts): def storeType(storage, cls, name): types = storage.create(Types) types.save(Type(name, cls.prefix)) - storage.commit() def setupCoreTypes(storage): for c in registry.values(): diff --git a/scopes/storage/tracking.py b/scopes/storage/tracking.py index e33e574..e2ebe59 100644 --- a/scopes/storage/tracking.py +++ b/scopes/storage/tracking.py @@ -169,7 +169,7 @@ class Container(object): *r[1:-2], trackId=r[0],timeStamp=r[-2], data=r[-1], container=self) def setupWhere(self, crit): - return [self.table.c[k.lower()] == v for k, v in crit.items()] + return [self.table.c[k.lower()] == v for k, v in crit.items() if v is not None] def setupValues(self, track, withTrackId=False): values = {}