provide attributes and resources via XML-RPC
git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@1647 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
parent
70810bdb6d
commit
685ac858b0
6 changed files with 95 additions and 19 deletions
1
base.py
1
base.py
|
@ -70,4 +70,3 @@ class Loops(Folder):
|
||||||
prefix = loopsPrefix + '/'
|
prefix = loopsPrefix + '/'
|
||||||
if uri.startswith(prefix):
|
if uri.startswith(prefix):
|
||||||
return traverse(self, uri[len(prefix):])
|
return traverse(self, uri[len(prefix):])
|
||||||
|
|
||||||
|
|
|
@ -122,6 +122,9 @@ class Concept(Contained, Persistent):
|
||||||
self.assignParent(concept, typePred)
|
self.assignParent(concept, typePred)
|
||||||
conceptType = property(getConceptType, setConceptType)
|
conceptType = property(getConceptType, setConceptType)
|
||||||
|
|
||||||
|
def getType(self):
|
||||||
|
return self.conceptType
|
||||||
|
|
||||||
def getLoopsRoot(self):
|
def getLoopsRoot(self):
|
||||||
return zapi.getParent(self).getLoopsRoot()
|
return zapi.getParent(self).getLoopsRoot()
|
||||||
|
|
||||||
|
|
|
@ -90,6 +90,10 @@ class IConcept(ILoopsObject, IPotentialTarget):
|
||||||
source="loops.conceptTypeSource",
|
source="loops.conceptTypeSource",
|
||||||
required=False)
|
required=False)
|
||||||
|
|
||||||
|
def getType():
|
||||||
|
""" Return a concept that provides the object's type.
|
||||||
|
"""
|
||||||
|
|
||||||
def getChildren(predicates=None):
|
def getChildren(predicates=None):
|
||||||
""" Return a sequence of concepts related to self as child concepts,
|
""" Return a sequence of concepts related to self as child concepts,
|
||||||
optionally restricted to the predicates given.
|
optionally restricted to the predicates given.
|
||||||
|
@ -223,6 +227,11 @@ class IBaseResource(ILoopsObject):
|
||||||
source="loops.resourceTypeSource",
|
source="loops.resourceTypeSource",
|
||||||
required=False)
|
required=False)
|
||||||
|
|
||||||
|
def getType():
|
||||||
|
""" Return a concept that provides the object's type, i.e. the
|
||||||
|
resourceType attribute.
|
||||||
|
"""
|
||||||
|
|
||||||
data = schema.Bytes(
|
data = schema.Bytes(
|
||||||
title=_(u'Data'),
|
title=_(u'Data'),
|
||||||
description=_(u'Resource raw data'),
|
description=_(u'Resource raw data'),
|
||||||
|
|
|
@ -117,6 +117,9 @@ class Resource(Image, Contained):
|
||||||
self.assignConcept(concept, typePred)
|
self.assignConcept(concept, typePred)
|
||||||
resourceType = property(getResourceType, setResourceType)
|
resourceType = property(getResourceType, setResourceType)
|
||||||
|
|
||||||
|
def getType(self):
|
||||||
|
return self.resourceType
|
||||||
|
|
||||||
def _setData(self, data):
|
def _setData(self, data):
|
||||||
dataFile = StringIO(data) # let File tear it into pieces
|
dataFile = StringIO(data) # let File tear it into pieces
|
||||||
super(Resource, self)._setData(dataFile)
|
super(Resource, self)._setData(dataFile)
|
||||||
|
|
|
@ -12,6 +12,7 @@ Let's do some basic set up
|
||||||
>>> from zope import component, interface
|
>>> from zope import component, interface
|
||||||
>>> from zope.publisher.browser import TestRequest
|
>>> from zope.publisher.browser import TestRequest
|
||||||
>>> from loops.concept import Concept
|
>>> from loops.concept import Concept
|
||||||
|
>>> from loops.resource import Resource
|
||||||
|
|
||||||
and setup a simple loops site with a concept manager and some concepts
|
and setup a simple loops site with a concept manager and some concepts
|
||||||
(with all the type machinery, what in real life is done via standard
|
(with all the type machinery, what in real life is done via standard
|
||||||
|
@ -23,7 +24,8 @@ ZCML setup):
|
||||||
>>> intIds = IntIdsStub()
|
>>> intIds = IntIdsStub()
|
||||||
>>> component.provideUtility(intIds)
|
>>> component.provideUtility(intIds)
|
||||||
|
|
||||||
>>> from loops.type import ConceptType, TypeConcept
|
>>> from loops.type import LoopsType, ConceptType, TypeConcept
|
||||||
|
>>> component.provideAdapter(LoopsType)
|
||||||
>>> component.provideAdapter(ConceptType)
|
>>> component.provideAdapter(ConceptType)
|
||||||
>>> component.provideAdapter(TypeConcept)
|
>>> component.provideAdapter(TypeConcept)
|
||||||
|
|
||||||
|
@ -31,28 +33,30 @@ ZCML setup):
|
||||||
>>> loopsRoot = site['loops'] = Loops()
|
>>> loopsRoot = site['loops'] = Loops()
|
||||||
|
|
||||||
>>> from loops.setup import SetupManager
|
>>> from loops.setup import SetupManager
|
||||||
|
>>> from loops.organize.setup import SetupManager as OrganizeSetupManager
|
||||||
|
>>> component.provideAdapter(OrganizeSetupManager, name='organize')
|
||||||
>>> setup = SetupManager(loopsRoot)
|
>>> setup = SetupManager(loopsRoot)
|
||||||
>>> concepts, resources, views = setup.setup()
|
>>> concepts, resources, views = setup.setup()
|
||||||
|
|
||||||
Let's look what setup has provided us with:
|
Let's look what setup has provided us with:
|
||||||
|
|
||||||
>>> sorted(concepts)
|
>>> sorted(concepts)
|
||||||
[u'domain', u'file', u'hasType', u'note', u'predicate', u'query',
|
[u'domain', u'file', u'hasType', u'note', u'person', u'predicate', u'query',
|
||||||
u'standard', u'textdocument', u'type']
|
u'standard', u'textdocument', u'type']
|
||||||
|
|
||||||
Now let's add a few more concepts:
|
Now let's add a few more concepts:
|
||||||
|
|
||||||
>>> topic = concepts[u'topic'] = Concept(u'Topic')
|
>>> topic = concepts[u'topic'] = Concept(u'Topic')
|
||||||
>>> intIds.register(topic)
|
>>> intIds.register(topic)
|
||||||
8
|
9
|
||||||
>>> zope = concepts[u'zope'] = Concept(u'Zope')
|
>>> zope = concepts[u'zope'] = Concept(u'Zope')
|
||||||
>>> zope.conceptType = topic
|
>>> zope.conceptType = topic
|
||||||
>>> intIds.register(zope)
|
>>> intIds.register(zope)
|
||||||
9
|
10
|
||||||
>>> zope3 = concepts[u'zope3'] = Concept(u'Zope 3')
|
>>> zope3 = concepts[u'zope3'] = Concept(u'Zope 3')
|
||||||
>>> zope3.conceptType = topic
|
>>> zope3.conceptType = topic
|
||||||
>>> intIds.register(zope3)
|
>>> intIds.register(zope3)
|
||||||
10
|
11
|
||||||
|
|
||||||
Navigation typically starts at a start object, which by default ist the
|
Navigation typically starts at a start object, which by default ist the
|
||||||
domain concept (if present, otherwise the top-level type concept):
|
domain concept (if present, otherwise the top-level type concept):
|
||||||
|
@ -61,7 +65,8 @@ domain concept (if present, otherwise the top-level type concept):
|
||||||
>>> xrf = LoopsMethods(loopsRoot, TestRequest())
|
>>> xrf = LoopsMethods(loopsRoot, TestRequest())
|
||||||
>>> startObj = xrf.getStartObject()
|
>>> startObj = xrf.getStartObject()
|
||||||
>>> sorted(startObj.keys())
|
>>> sorted(startObj.keys())
|
||||||
['children', 'id', 'name', 'parents', 'title', 'type']
|
['children', 'description', 'id', 'name', 'options', 'parents', 'resources',
|
||||||
|
'title', 'type', 'typeInterface', 'viewName']
|
||||||
>>> startObj['id'], startObj['name'], startObj['title'], startObj['type']
|
>>> startObj['id'], startObj['name'], startObj['title'], startObj['type']
|
||||||
('1', u'domain', u'Domain', '0')
|
('1', u'domain', u'Domain', '0')
|
||||||
|
|
||||||
|
@ -80,7 +85,7 @@ There are a few standard objects we can retrieve directly:
|
||||||
In addition we can get a list of all types and all predicates available:
|
In addition we can get a list of all types and all predicates available:
|
||||||
|
|
||||||
>>> sorted(t['name'] for t in xrf.getConceptTypes())
|
>>> sorted(t['name'] for t in xrf.getConceptTypes())
|
||||||
[u'domain', u'file', u'predicate', u'query', u'textdocument', u'type']
|
[u'domain', u'file', u'person', u'predicate', u'query', u'textdocument', u'type']
|
||||||
>>> sorted(t['name'] for t in xrf.getPredicates())
|
>>> sorted(t['name'] for t in xrf.getPredicates())
|
||||||
[u'hasType', u'standard']
|
[u'hasType', u'standard']
|
||||||
|
|
||||||
|
@ -101,7 +106,7 @@ All methods that retrieve one object also returns its children and parents:
|
||||||
>>> ch[0]['name']
|
>>> ch[0]['name']
|
||||||
u'hasType'
|
u'hasType'
|
||||||
>>> sorted(c['name'] for c in ch[0]['objects'])
|
>>> sorted(c['name'] for c in ch[0]['objects'])
|
||||||
[u'domain', u'file', u'predicate', u'query', u'textdocument', u'type']
|
[u'domain', u'file', u'person', u'predicate', u'query', u'textdocument', u'type']
|
||||||
|
|
||||||
>>> pa = defaultPred['parents']
|
>>> pa = defaultPred['parents']
|
||||||
>>> len(pa)
|
>>> len(pa)
|
||||||
|
@ -119,7 +124,7 @@ We can also retrieve children and parents explicitely:
|
||||||
>>> ch[0]['name']
|
>>> ch[0]['name']
|
||||||
u'hasType'
|
u'hasType'
|
||||||
>>> sorted(c['name'] for c in ch[0]['objects'])
|
>>> sorted(c['name'] for c in ch[0]['objects'])
|
||||||
[u'domain', u'file', u'predicate', u'query', u'textdocument', u'type']
|
[u'domain', u'file', u'person', u'predicate', u'query', u'textdocument', u'type']
|
||||||
|
|
||||||
>>> pa = xrf.getParents('6')
|
>>> pa = xrf.getParents('6')
|
||||||
>>> len(pa)
|
>>> len(pa)
|
||||||
|
@ -129,6 +134,34 @@ We can also retrieve children and parents explicitely:
|
||||||
>>> sorted(p['name'] for p in pa[0]['objects'])
|
>>> sorted(p['name'] for p in pa[0]['objects'])
|
||||||
[u'predicate']
|
[u'predicate']
|
||||||
|
|
||||||
|
Resources
|
||||||
|
---------
|
||||||
|
|
||||||
|
>>> from loops.resource import TextDocumentAdapter
|
||||||
|
>>> from loops.interfaces import IResource, ITextDocument
|
||||||
|
>>> component.provideAdapter(TextDocumentAdapter, (IResource,), ITextDocument)
|
||||||
|
|
||||||
|
>>> zope3Id = xrf.getObjectByName('zope3')['id']
|
||||||
|
>>> td01 = resources['td01'] = Resource(u'Doc1')
|
||||||
|
>>> td01.resourceType = concepts['textdocument']
|
||||||
|
>>> zope3.assignResource(td01)
|
||||||
|
|
||||||
|
>>> obj = xrf.getObjectById(zope3Id)
|
||||||
|
>>> obj['resources'][0]['objects'][0]['title']
|
||||||
|
u'Doc1'
|
||||||
|
|
||||||
|
Attributes
|
||||||
|
----------
|
||||||
|
|
||||||
|
>>> from loops.organize.party import Person
|
||||||
|
>>> from loops.organize.interfaces import IPerson
|
||||||
|
>>> component.provideAdapter(Person, provides=IPerson)
|
||||||
|
>>> p01 = concepts['p01'] = Concept(u'John Smith')
|
||||||
|
>>> p01.conceptType = concepts['person']
|
||||||
|
|
||||||
|
>>> john = xrf.getObjectByName('p01')
|
||||||
|
>>> #john
|
||||||
|
|
||||||
Updating the concept map
|
Updating the concept map
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
|
@ -142,7 +175,13 @@ Updating the concept map
|
||||||
|
|
||||||
>>> topicId = xrf.getObjectByName('topic')['id']
|
>>> topicId = xrf.getObjectByName('topic')['id']
|
||||||
>>> xrf.createConcept(topicId, u'zope2', u'Zope 2')
|
>>> xrf.createConcept(topicId, u'zope2', u'Zope 2')
|
||||||
{'title': u'Zope 2', 'type': '8', 'id': '12', 'name': u'zope2'}
|
{'description': u'', 'title': u'Zope 2', 'type': '9', 'id': '15',
|
||||||
|
'name': u'zope2'}
|
||||||
|
|
||||||
|
Changing the attributes of a concept
|
||||||
|
------------------------------------
|
||||||
|
|
||||||
|
Not implemented yet.
|
||||||
|
|
||||||
|
|
||||||
Fin de partie
|
Fin de partie
|
||||||
|
|
|
@ -31,6 +31,7 @@ from zope.traversing.api import getName
|
||||||
from zope.security.proxy import removeSecurityProxy
|
from zope.security.proxy import removeSecurityProxy
|
||||||
from zope.cachedescriptors.property import Lazy
|
from zope.cachedescriptors.property import Lazy
|
||||||
|
|
||||||
|
from cybertools.typology.interfaces import IType
|
||||||
from loops.concept import Concept
|
from loops.concept import Concept
|
||||||
from loops.util import getUidForObject, getObjectForUid, toUnicode
|
from loops.util import getUidForObject, getObjectForUid, toUnicode
|
||||||
|
|
||||||
|
@ -90,11 +91,19 @@ class LoopsMethods(MethodPublisher):
|
||||||
rels = obj.getParentRelations(preds or None, parent)
|
rels = obj.getParentRelations(preds or None, parent)
|
||||||
return formatRelations(rels, useSecond=False)
|
return formatRelations(rels, useSecond=False)
|
||||||
|
|
||||||
|
def getResources(self, id, predicates=[], resource=''):
|
||||||
|
obj = getObjectForUid(id)
|
||||||
|
preds = [getObjectForUid(p) for p in predicates]
|
||||||
|
resource = resource and getObjectForUid(child) or None
|
||||||
|
rels = obj.getResourceRelations(preds or None, resource)
|
||||||
|
return formatRelations(rels)
|
||||||
|
|
||||||
def getObjectWithChildren(self, obj):
|
def getObjectWithChildren(self, obj):
|
||||||
mapping = objectAsDict(obj)
|
mapping = objectAsDict(obj)
|
||||||
mapping['children'] = formatRelations(obj.getChildRelations())
|
mapping['children'] = formatRelations(obj.getChildRelations())
|
||||||
mapping['parents'] = formatRelations(
|
mapping['parents'] = formatRelations(
|
||||||
obj.getParentRelations(), useSecond=False)
|
obj.getParentRelations(), useSecond=False)
|
||||||
|
mapping['resources'] = formatRelations(obj.getResourceRelations())
|
||||||
return mapping
|
return mapping
|
||||||
|
|
||||||
def assignChild(self, objId, predicateId, childId):
|
def assignChild(self, objId, predicateId, childId):
|
||||||
|
@ -122,8 +131,22 @@ class LoopsMethods(MethodPublisher):
|
||||||
|
|
||||||
|
|
||||||
def objectAsDict(obj):
|
def objectAsDict(obj):
|
||||||
mapping = {'id': getUidForObject(obj), 'name': getName(obj), 'title': obj.title,
|
objType = IType(obj)
|
||||||
'type': getUidForObject(obj.conceptType)}
|
mapping = {'id': getUidForObject(obj), 'name': getName(obj),
|
||||||
|
'title': obj.title, 'description': obj.description,
|
||||||
|
'type': getUidForObject(objType.typeProvider)}
|
||||||
|
ti = objType.typeInterface
|
||||||
|
if ti is not None:
|
||||||
|
adapter = ti(obj)
|
||||||
|
for attr in (list(adapter._adapterAttributes) + list(ti)):
|
||||||
|
if attr not in ('__parent__', 'context', 'id', 'name',
|
||||||
|
'title', 'description', 'type'):
|
||||||
|
value = getattr(adapter, attr)
|
||||||
|
# TODO: better selection and conversion
|
||||||
|
if value is None or type(value) in (str, unicode):
|
||||||
|
mapping[attr] = value or u''
|
||||||
|
elif type(value) is list:
|
||||||
|
mapping[attr] = ' | '.join(value)
|
||||||
return mapping
|
return mapping
|
||||||
|
|
||||||
def formatRelations(rels, useSecond=True):
|
def formatRelations(rels, useSecond=True):
|
||||||
|
|
Loading…
Add table
Reference in a new issue