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 + '/'
|
||||
if uri.startswith(prefix):
|
||||
return traverse(self, uri[len(prefix):])
|
||||
|
||||
|
|
|
@ -122,6 +122,9 @@ class Concept(Contained, Persistent):
|
|||
self.assignParent(concept, typePred)
|
||||
conceptType = property(getConceptType, setConceptType)
|
||||
|
||||
def getType(self):
|
||||
return self.conceptType
|
||||
|
||||
def getLoopsRoot(self):
|
||||
return zapi.getParent(self).getLoopsRoot()
|
||||
|
||||
|
|
|
@ -75,12 +75,12 @@ class IConcept(ILoopsObject, IPotentialTarget):
|
|||
required=True)
|
||||
|
||||
description = schema.Text(
|
||||
title=_(u'Description'),
|
||||
description=_(u'A medium-length description describing the '
|
||||
'content and the purpose of the object'),
|
||||
default=u'',
|
||||
missing_value=u'',
|
||||
required=False)
|
||||
title=_(u'Description'),
|
||||
description=_(u'A medium-length description describing the '
|
||||
'content and the purpose of the object'),
|
||||
default=u'',
|
||||
missing_value=u'',
|
||||
required=False)
|
||||
|
||||
conceptType = schema.Choice(
|
||||
title=_(u'Concept Type'),
|
||||
|
@ -90,6 +90,10 @@ class IConcept(ILoopsObject, IPotentialTarget):
|
|||
source="loops.conceptTypeSource",
|
||||
required=False)
|
||||
|
||||
def getType():
|
||||
""" Return a concept that provides the object's type.
|
||||
"""
|
||||
|
||||
def getChildren(predicates=None):
|
||||
""" Return a sequence of concepts related to self as child concepts,
|
||||
optionally restricted to the predicates given.
|
||||
|
@ -223,6 +227,11 @@ class IBaseResource(ILoopsObject):
|
|||
source="loops.resourceTypeSource",
|
||||
required=False)
|
||||
|
||||
def getType():
|
||||
""" Return a concept that provides the object's type, i.e. the
|
||||
resourceType attribute.
|
||||
"""
|
||||
|
||||
data = schema.Bytes(
|
||||
title=_(u'Data'),
|
||||
description=_(u'Resource raw data'),
|
||||
|
|
|
@ -117,6 +117,9 @@ class Resource(Image, Contained):
|
|||
self.assignConcept(concept, typePred)
|
||||
resourceType = property(getResourceType, setResourceType)
|
||||
|
||||
def getType(self):
|
||||
return self.resourceType
|
||||
|
||||
def _setData(self, data):
|
||||
dataFile = StringIO(data) # let File tear it into pieces
|
||||
super(Resource, self)._setData(dataFile)
|
||||
|
|
|
@ -12,6 +12,7 @@ Let's do some basic set up
|
|||
>>> from zope import component, interface
|
||||
>>> from zope.publisher.browser import TestRequest
|
||||
>>> from loops.concept import Concept
|
||||
>>> from loops.resource import Resource
|
||||
|
||||
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
|
||||
|
@ -23,7 +24,8 @@ ZCML setup):
|
|||
>>> intIds = IntIdsStub()
|
||||
>>> component.provideUtility(intIds)
|
||||
|
||||
>>> from loops.type import ConceptType, TypeConcept
|
||||
>>> from loops.type import LoopsType, ConceptType, TypeConcept
|
||||
>>> component.provideAdapter(LoopsType)
|
||||
>>> component.provideAdapter(ConceptType)
|
||||
>>> component.provideAdapter(TypeConcept)
|
||||
|
||||
|
@ -31,28 +33,30 @@ ZCML setup):
|
|||
>>> loopsRoot = site['loops'] = Loops()
|
||||
|
||||
>>> from loops.setup import SetupManager
|
||||
>>> from loops.organize.setup import SetupManager as OrganizeSetupManager
|
||||
>>> component.provideAdapter(OrganizeSetupManager, name='organize')
|
||||
>>> setup = SetupManager(loopsRoot)
|
||||
>>> concepts, resources, views = setup.setup()
|
||||
|
||||
Let's look what setup has provided us with:
|
||||
|
||||
>>> 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']
|
||||
|
||||
Now let's add a few more concepts:
|
||||
|
||||
>>> topic = concepts[u'topic'] = Concept(u'Topic')
|
||||
>>> intIds.register(topic)
|
||||
8
|
||||
9
|
||||
>>> zope = concepts[u'zope'] = Concept(u'Zope')
|
||||
>>> zope.conceptType = topic
|
||||
>>> intIds.register(zope)
|
||||
9
|
||||
10
|
||||
>>> zope3 = concepts[u'zope3'] = Concept(u'Zope 3')
|
||||
>>> zope3.conceptType = topic
|
||||
>>> intIds.register(zope3)
|
||||
10
|
||||
11
|
||||
|
||||
Navigation typically starts at a start object, which by default ist the
|
||||
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())
|
||||
>>> startObj = xrf.getStartObject()
|
||||
>>> 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']
|
||||
('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:
|
||||
|
||||
>>> 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())
|
||||
[u'hasType', u'standard']
|
||||
|
||||
|
@ -101,7 +106,7 @@ All methods that retrieve one object also returns its children and parents:
|
|||
>>> ch[0]['name']
|
||||
u'hasType'
|
||||
>>> 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']
|
||||
>>> len(pa)
|
||||
|
@ -119,7 +124,7 @@ We can also retrieve children and parents explicitely:
|
|||
>>> ch[0]['name']
|
||||
u'hasType'
|
||||
>>> 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')
|
||||
>>> len(pa)
|
||||
|
@ -129,6 +134,34 @@ We can also retrieve children and parents explicitely:
|
|||
>>> sorted(p['name'] for p in pa[0]['objects'])
|
||||
[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
|
||||
------------------------
|
||||
|
||||
|
@ -142,7 +175,13 @@ Updating the concept map
|
|||
|
||||
>>> topicId = xrf.getObjectByName('topic')['id']
|
||||
>>> 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
|
||||
|
|
|
@ -31,6 +31,7 @@ from zope.traversing.api import getName
|
|||
from zope.security.proxy import removeSecurityProxy
|
||||
from zope.cachedescriptors.property import Lazy
|
||||
|
||||
from cybertools.typology.interfaces import IType
|
||||
from loops.concept import Concept
|
||||
from loops.util import getUidForObject, getObjectForUid, toUnicode
|
||||
|
||||
|
@ -90,11 +91,19 @@ class LoopsMethods(MethodPublisher):
|
|||
rels = obj.getParentRelations(preds or None, parent)
|
||||
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):
|
||||
mapping = objectAsDict(obj)
|
||||
mapping['children'] = formatRelations(obj.getChildRelations())
|
||||
mapping['parents'] = formatRelations(
|
||||
obj.getParentRelations(), useSecond=False)
|
||||
mapping['resources'] = formatRelations(obj.getResourceRelations())
|
||||
return mapping
|
||||
|
||||
def assignChild(self, objId, predicateId, childId):
|
||||
|
@ -122,8 +131,22 @@ class LoopsMethods(MethodPublisher):
|
|||
|
||||
|
||||
def objectAsDict(obj):
|
||||
mapping = {'id': getUidForObject(obj), 'name': getName(obj), 'title': obj.title,
|
||||
'type': getUidForObject(obj.conceptType)}
|
||||
objType = IType(obj)
|
||||
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
|
||||
|
||||
def formatRelations(rels, useSecond=True):
|
||||
|
|
Loading…
Add table
Reference in a new issue