work in progress: concept map, starting with types
This commit is contained in:
parent
0b765ad16b
commit
3e1127e798
6 changed files with 91 additions and 12 deletions
|
@ -5,7 +5,7 @@ from zope.interface import Interface
|
||||||
|
|
||||||
class ITraversable(Interface):
|
class ITraversable(Interface):
|
||||||
|
|
||||||
def get(key, default):
|
def get(key, default=None):
|
||||||
"""Return the item addressed by `key`; return `default` if not found."""
|
"""Return the item addressed by `key`; return `default` if not found."""
|
||||||
|
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ class IContainer(ITraversable):
|
||||||
"""Return a sequence of child objects."""
|
"""Return a sequence of child objects."""
|
||||||
|
|
||||||
def __getitem__(key):
|
def __getitem__(key):
|
||||||
"""Return the item addressed by `key`; rais KeyError if not found."""
|
"""Return the item addressed by `key`; raise KeyError if not found."""
|
||||||
|
|
||||||
def __setitem__(key, value):
|
def __setitem__(key, value):
|
||||||
"""Store the `value` under the `key`.
|
"""Store the `value` under the `key`.
|
||||||
|
@ -24,6 +24,17 @@ class IContainer(ITraversable):
|
||||||
and the value object (e.g. `parent´ and `name`) are stored correctly."""
|
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):
|
class IView(Interface):
|
||||||
|
|
||||||
def __call__():
|
def __call__():
|
||||||
|
|
|
@ -4,12 +4,15 @@ import json
|
||||||
from zope.interface import implementer
|
from zope.interface import implementer
|
||||||
from scopes.interfaces import IContainer, IView
|
from scopes.interfaces import IContainer, IView
|
||||||
|
|
||||||
views = {}
|
views = {} # registry for all views: {name: {prefix: viewClass, ...}, ...}
|
||||||
|
|
||||||
def register(contextClass, name):
|
def register(name, *contextClasses):
|
||||||
|
"""Use as decorator: `@register(name, class, ...).
|
||||||
|
class `None` means default view for all classes."""
|
||||||
def doRegister(viewClass):
|
def doRegister(viewClass):
|
||||||
nameEntry = views.setdefault(name, {})
|
nameEntry = views.setdefault(name, {})
|
||||||
key = contextClass and contextClass.prefix or ''
|
for cl in contextClasses:
|
||||||
|
key = cl and cl.prefix or ''
|
||||||
nameEntry[key] = viewClass
|
nameEntry[key] = viewClass
|
||||||
return viewClass
|
return viewClass
|
||||||
return doRegister
|
return doRegister
|
||||||
|
@ -26,8 +29,8 @@ def getView(request, ob, name):
|
||||||
return viewClass(ob, request)
|
return viewClass(ob, request)
|
||||||
|
|
||||||
|
|
||||||
@register(None, 'index.html')
|
@register('index.html', None)
|
||||||
@register(None, 'index.json')
|
@register('index.json', None)
|
||||||
@implementer(IView)
|
@implementer(IView)
|
||||||
class DefaultView:
|
class DefaultView:
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,66 @@
|
||||||
# scopes.storage.concept
|
# scopes.storage.concept
|
||||||
|
|
||||||
"""Abstract base classes for concept map application classes."""
|
"""Core classes for concept map structure."""
|
||||||
|
|
||||||
|
from zope.interface import implementer
|
||||||
|
from scopes.interfaces import IConcept
|
||||||
from scopes.storage.common import registerContainerClass
|
from scopes.storage.common import registerContainerClass
|
||||||
from scopes.storage.tracking import Container, Track
|
from scopes.storage.tracking import Container, Track
|
||||||
|
|
||||||
|
|
||||||
|
@implementer(IConcept)
|
||||||
class Concept(Track):
|
class Concept(Track):
|
||||||
|
|
||||||
headFields = ['name']
|
headFields = ['name']
|
||||||
|
|
||||||
|
|
||||||
|
class Concepts(Container):
|
||||||
|
|
||||||
|
insertOnChange = False
|
||||||
|
|
||||||
|
|
||||||
|
class Predicate(Concept):
|
||||||
|
|
||||||
|
prefix = 'pred'
|
||||||
|
|
||||||
|
|
||||||
|
@registerContainerClass
|
||||||
|
class Predicates(Concepts):
|
||||||
|
|
||||||
|
itemFactory = Predicate
|
||||||
|
tableName = 'preds'
|
||||||
|
|
||||||
|
|
||||||
|
class Triple(Track):
|
||||||
|
|
||||||
|
headFields = ['first', 'second', 'predicate']
|
||||||
|
prefix = 'rel'
|
||||||
|
|
||||||
|
|
||||||
|
@registerContainerClass
|
||||||
|
class Rels(Container):
|
||||||
|
|
||||||
|
itemFactory = Triple
|
||||||
|
indexes = [('first', 'predicate', 'second'),
|
||||||
|
('first', 'second'), ('predicate', 'second')]
|
||||||
|
tableName = 'rels'
|
||||||
|
insertOnChange = False
|
||||||
|
|
||||||
|
|
||||||
|
# types stuff
|
||||||
|
|
||||||
|
class Type(Concept):
|
||||||
|
|
||||||
|
headFields = ['name', 'prefix']
|
||||||
|
prefix = 'type'
|
||||||
|
|
||||||
|
def get(key, default=None):
|
||||||
|
return self.container.queryLast(name=key) or default
|
||||||
|
|
||||||
|
|
||||||
|
@registerContainerClass
|
||||||
|
class Types(Concepts):
|
||||||
|
|
||||||
|
itemFactory = Type
|
||||||
|
indexes = [('name',), ('prefix',)]
|
||||||
|
tableName = 'types'
|
||||||
|
|
|
@ -9,7 +9,6 @@ from scopes.storage.tracking import Container, Track
|
||||||
|
|
||||||
@implementer(IContainer)
|
@implementer(IContainer)
|
||||||
class Folder(Track):
|
class Folder(Track):
|
||||||
"""Needs docstring to be traversable."""
|
|
||||||
|
|
||||||
headFields = ['parent', 'name', 'ref']
|
headFields = ['parent', 'name', 'ref']
|
||||||
prefix = 'fldr'
|
prefix = 'fldr'
|
||||||
|
|
|
@ -21,7 +21,10 @@ class Test(unittest.TestCase):
|
||||||
def test_002_folder(self):
|
def test_002_folder(self):
|
||||||
tlib_storage.test_folder(self, config)
|
tlib_storage.test_folder(self, config)
|
||||||
|
|
||||||
def test_003_server(self):
|
def test_003_type(self):
|
||||||
|
tlib_storage.test_type(self, config)
|
||||||
|
|
||||||
|
def test_013_server(self):
|
||||||
tlib_server.test_app(self, config)
|
tlib_server.test_app(self, config)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
"""Test implementation for the `scopes.storage` package."""
|
"""Test implementation for the `scopes.storage` package."""
|
||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from scopes.storage import folder, tracking
|
from scopes.storage import concept, folder, tracking
|
||||||
|
|
||||||
|
|
||||||
def test_tracking(self, config):
|
def test_tracking(self, config):
|
||||||
|
@ -73,3 +73,12 @@ def test_folder(self, config):
|
||||||
|
|
||||||
storage.commit()
|
storage.commit()
|
||||||
|
|
||||||
|
|
||||||
|
def test_type(self, config):
|
||||||
|
storage = config.storageFactory(config.dbschema)
|
||||||
|
storage.dropTable('types')
|
||||||
|
types = storage.create(concept.Types)
|
||||||
|
tid01 = types.save(concept.Type('type', 'type'))
|
||||||
|
self.assertEqual(tid01, 1)
|
||||||
|
|
||||||
|
storage.commit()
|
||||||
|
|
Loading…
Add table
Reference in a new issue