removed xmlrpc package
This commit is contained in:
parent
f2a737e0a8
commit
74ce78dae9
5 changed files with 0 additions and 455 deletions
|
@ -1,213 +0,0 @@
|
||||||
===============================================================
|
|
||||||
loops.xmlrpc
|
|
||||||
===============================================================
|
|
||||||
|
|
||||||
($Id$)
|
|
||||||
|
|
||||||
Let's do some basic set up
|
|
||||||
|
|
||||||
>>> from zope.app.testing.setup import placefulSetUp, placefulTearDown
|
|
||||||
>>> site = placefulSetUp(True)
|
|
||||||
>>> from zope import component, interface
|
|
||||||
>>> from zope.publisher.browser import TestRequest
|
|
||||||
>>> from loops.concept import Concept
|
|
||||||
>>> from loops.resource import Resource
|
|
||||||
>>>
|
|
||||||
|
|
||||||
and set up a simple loops site with a concept manager and some concepts
|
|
||||||
(with all the type machinery, what in real life is done via standard
|
|
||||||
ZCML setup):
|
|
||||||
|
|
||||||
>>> from loops.setup import addObject
|
|
||||||
>>> from loops.organize.setup import SetupManager as OrganizeSetupManager
|
|
||||||
>>> component.provideAdapter(OrganizeSetupManager, name='organize')
|
|
||||||
>>> from loops.tests.setup import TestSite
|
|
||||||
>>> t = TestSite(site)
|
|
||||||
>>> concepts, resources, views = t.setup()
|
|
||||||
|
|
||||||
>>> from loops import util
|
|
||||||
>>> loopsRoot = site['loops']
|
|
||||||
>>> loopsId = util.getUidForObject(loopsRoot)
|
|
||||||
|
|
||||||
>>> from loops.knowledge.tests import importData
|
|
||||||
>>> importData(loopsRoot)
|
|
||||||
|
|
||||||
Let's look what setup has provided us with:
|
|
||||||
|
|
||||||
>>> len(concepts)
|
|
||||||
24
|
|
||||||
|
|
||||||
Now let's add a few more concepts:
|
|
||||||
|
|
||||||
>>> topic = concepts[u'topic']
|
|
||||||
>>> zope = addObject(concepts, Concept, 'zope', title=u'Zope', conceptType=topic)
|
|
||||||
>>> zope3 = addObject(concepts, Concept, 'zope3', title=u'Zope 3', conceptType=topic)
|
|
||||||
|
|
||||||
Navigation typically starts at a start object, which by default ist the
|
|
||||||
domain concept (if present, otherwise the top-level type concept):
|
|
||||||
|
|
||||||
>>> from loops.xmlrpc.common import LoopsMethods
|
|
||||||
>>> xrf = LoopsMethods(loopsRoot, TestRequest())
|
|
||||||
>>> startObj = xrf.getStartObject()
|
|
||||||
>>> sorted(startObj.keys())
|
|
||||||
['children', 'description', 'id', 'name', 'parents', 'resources',
|
|
||||||
'title', 'type', 'viewName']
|
|
||||||
>>> startObj['id'], startObj['name'], startObj['title'], startObj['type']
|
|
||||||
('3', u'domain', u'Domain', '0')
|
|
||||||
|
|
||||||
There are a few standard objects we can retrieve directly:
|
|
||||||
|
|
||||||
>>> defaultPred = xrf.getDefaultPredicate()
|
|
||||||
>>> defaultPred['id'], defaultPred['name']
|
|
||||||
('14', u'standard')
|
|
||||||
>>> typePred = xrf.getTypePredicate()
|
|
||||||
>>> typePred['id'], typePred['name']
|
|
||||||
('2', u'hasType')
|
|
||||||
>>> typeConcept = xrf.getTypeConcept()
|
|
||||||
>>> typeConcept['id'], typeConcept['name']
|
|
||||||
('0', u'type')
|
|
||||||
|
|
||||||
In addition we can get a list of all types and all predicates available;
|
|
||||||
note that the 'hasType' predicate is not shown as it should not be
|
|
||||||
applied in an explicit assignment.
|
|
||||||
|
|
||||||
>>> sorted(t['name'] for t in xrf.getConceptTypes())
|
|
||||||
[u'competence', u'customer', u'domain', u'file', u'note', u'person',
|
|
||||||
u'predicate', u'report', u'task', u'textdocument', u'topic', u'type']
|
|
||||||
>>> sorted(t['name'] for t in xrf.getPredicates())
|
|
||||||
[u'depends', u'issubtype', u'knows', u'ownedby', u'provides', u'requires',
|
|
||||||
u'standard']
|
|
||||||
|
|
||||||
We can also retrieve a certain object by its id or its name:
|
|
||||||
|
|
||||||
>>> obj2 = xrf.getObjectById('3')
|
|
||||||
>>> obj2['id'], obj2['name']
|
|
||||||
('3', u'domain')
|
|
||||||
>>> textdoc = xrf.getObjectByName(u'textdocument')
|
|
||||||
>>> textdoc['id'], textdoc['name']
|
|
||||||
('9', u'textdocument')
|
|
||||||
|
|
||||||
All methods that retrieve one object also returns its children and parents:
|
|
||||||
|
|
||||||
>>> ch = typeConcept['children']
|
|
||||||
>>> len(ch)
|
|
||||||
1
|
|
||||||
>>> ch[0]['name']
|
|
||||||
u'hasType'
|
|
||||||
>>> sorted(c['name'] for c in ch[0]['objects'])
|
|
||||||
[u'competence', u'customer', u'domain', u'file', u'note', u'person',
|
|
||||||
u'predicate', u'report', u'task', u'textdocument', u'topic', u'type']
|
|
||||||
|
|
||||||
>>> pa = defaultPred['parents']
|
|
||||||
>>> len(pa)
|
|
||||||
1
|
|
||||||
>>> pa[0]['name']
|
|
||||||
u'hasType'
|
|
||||||
>>> sorted(p['name'] for p in pa[0]['objects'])
|
|
||||||
[u'predicate']
|
|
||||||
|
|
||||||
We can also retrieve children and parents explicitely:
|
|
||||||
|
|
||||||
>>> ch = xrf.getChildren('0')
|
|
||||||
>>> len(ch)
|
|
||||||
1
|
|
||||||
>>> ch[0]['name']
|
|
||||||
u'hasType'
|
|
||||||
>>> sorted(c['name'] for c in ch[0]['objects'])
|
|
||||||
[u'competence', u'customer', u'domain', u'file', u'note', u'person',
|
|
||||||
u'predicate', u'report', u'task', u'textdocument', u'topic', u'type']
|
|
||||||
|
|
||||||
>>> pa = xrf.getParents('5')
|
|
||||||
>>> len(pa)
|
|
||||||
1
|
|
||||||
>>> pa[0]['name']
|
|
||||||
u'hasType'
|
|
||||||
>>> sorted(p['name'] for p in pa[0]['objects'])
|
|
||||||
[u'type']
|
|
||||||
|
|
||||||
Resources
|
|
||||||
---------
|
|
||||||
|
|
||||||
>>> from loops.resource import TextDocumentAdapter
|
|
||||||
>>> from loops.interfaces import IResource, ITextDocument, IFile
|
|
||||||
>>> component.provideAdapter(TextDocumentAdapter, (IResource,), ITextDocument)
|
|
||||||
>>> from loops.resource import FileAdapter
|
|
||||||
>>> component.provideAdapter(FileAdapter, provides=IFile)
|
|
||||||
|
|
||||||
>>> 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
|
|
||||||
------------------------
|
|
||||||
|
|
||||||
>>> zopeId = xrf.getObjectByName('zope')['id']
|
|
||||||
>>> zope3Id = xrf.getObjectByName('zope3')['id']
|
|
||||||
>>> xrf.assignChild(zopeId, defaultPred['id'], zope3Id)
|
|
||||||
'OK'
|
|
||||||
>>> pa = xrf.getParents(zope3Id)
|
|
||||||
>>> len(pa)
|
|
||||||
2
|
|
||||||
|
|
||||||
>>> xrf.deassignChild(zopeId, defaultPred['id'], zope3Id)
|
|
||||||
'OK'
|
|
||||||
>>> pa = xrf.getParents(zope3Id)
|
|
||||||
>>> len(pa)
|
|
||||||
1
|
|
||||||
|
|
||||||
>>> topicId = xrf.getObjectByName('topic')['id']
|
|
||||||
>>> xrf.createConcept(topicId, u'zope2', u'Zope 2')
|
|
||||||
{'description': u'', 'title': u'Zope 2', 'type': '38', 'id': '77',
|
|
||||||
'name': u'zope2'}
|
|
||||||
|
|
||||||
The name of the concept is checked by a name chooser; if the corresponding
|
|
||||||
parameter is empty, the name will be generated from the title.
|
|
||||||
|
|
||||||
>>> xrf.createConcept(topicId, u'', u'Python')
|
|
||||||
{'description': u'', 'title': u'Python', 'type': '38', 'id': '79',
|
|
||||||
'name': u'python'}
|
|
||||||
|
|
||||||
If we try to deassign a ``hasType`` relation nothing will happen; a
|
|
||||||
corresponding error value will be returned.
|
|
||||||
|
|
||||||
>>> xrf.deassignChild(topicId, typePred['id'], zope3Id)
|
|
||||||
'Not allowed'
|
|
||||||
|
|
||||||
Changing the attributes of a concept
|
|
||||||
------------------------------------
|
|
||||||
|
|
||||||
>>> from loops.knowledge.knowledge import Person
|
|
||||||
>>> from loops.knowledge.interfaces import IPerson
|
|
||||||
>>> component.provideAdapter(Person, provides=IPerson)
|
|
||||||
|
|
||||||
>>> xrf.editConcept(john['id'], 'firstName', u'John')
|
|
||||||
'OK'
|
|
||||||
>>> john = xrf.getObjectById(john['id'])
|
|
||||||
>>> john['firstName']
|
|
||||||
u'John'
|
|
||||||
>>> john['lastName']
|
|
||||||
u''
|
|
||||||
|
|
||||||
|
|
||||||
Fin de partie
|
|
||||||
=============
|
|
||||||
|
|
||||||
>>> placefulTearDown()
|
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
"""
|
|
||||||
$Id$
|
|
||||||
"""
|
|
||||||
|
|
|
@ -1,198 +0,0 @@
|
||||||
#
|
|
||||||
# Copyright (c) 2012 Helmut Merz helmutm@cy55.de
|
|
||||||
#
|
|
||||||
# This program is free software; you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation; either version 2 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program; if not, write to the Free Software
|
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
#
|
|
||||||
|
|
||||||
"""
|
|
||||||
XML-RPC views.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from zope.app.container.interfaces import INameChooser
|
|
||||||
from zope.interface import implements
|
|
||||||
from zope.event import notify
|
|
||||||
from zope.lifecycleevent import ObjectCreatedEvent, ObjectModifiedEvent
|
|
||||||
from zope.app.publisher.xmlrpc import XMLRPCView
|
|
||||||
from zope.app.publisher.xmlrpc import MethodPublisher
|
|
||||||
from zope.traversing.api import getName
|
|
||||||
from zope.schema.interfaces import ITextLine
|
|
||||||
from zope.security.proxy import removeSecurityProxy
|
|
||||||
from zope.cachedescriptors.property import Lazy
|
|
||||||
|
|
||||||
from cybertools.typology.interfaces import IType
|
|
||||||
from loops.common import adapted, AdapterBase
|
|
||||||
from loops.concept import Concept
|
|
||||||
from loops.i18n.browser import I18NView
|
|
||||||
from loops.util import getUidForObject, getObjectForUid, toUnicode
|
|
||||||
|
|
||||||
|
|
||||||
class LoopsMethods(MethodPublisher, I18NView):
|
|
||||||
""" XML-RPC methods for the loops root object.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, context, request):
|
|
||||||
self.context = removeSecurityProxy(context)
|
|
||||||
self.request = request
|
|
||||||
|
|
||||||
@Lazy
|
|
||||||
def concepts(self):
|
|
||||||
return self.context.getConceptManager()
|
|
||||||
|
|
||||||
@Lazy
|
|
||||||
def typePredicate(self):
|
|
||||||
return self.concepts.getTypePredicate()
|
|
||||||
|
|
||||||
def getStartObject(self):
|
|
||||||
so = self.concepts.get('domain', self.concepts.getTypeConcept())
|
|
||||||
return self.getObjectWithChildren(so)
|
|
||||||
|
|
||||||
def getObjectById(self, id):
|
|
||||||
return self.getObjectWithChildren(getObjectForUid(id))
|
|
||||||
|
|
||||||
def getObjectByName(self, name):
|
|
||||||
return self.getObjectWithChildren(self.concepts[name])
|
|
||||||
|
|
||||||
def getDefaultPredicate(self):
|
|
||||||
return self.getObjectWithChildren(self.concepts.getDefaultPredicate())
|
|
||||||
|
|
||||||
def getTypePredicate(self):
|
|
||||||
return self.getObjectWithChildren(self.typePredicate)
|
|
||||||
|
|
||||||
def getTypeConcept(self):
|
|
||||||
return self.getObjectWithChildren(self.concepts.getTypeConcept())
|
|
||||||
|
|
||||||
def getConceptTypes(self):
|
|
||||||
tc = self.concepts.getTypeConcept()
|
|
||||||
types = tc.getChildren((self.typePredicate,))
|
|
||||||
#types = [t for t in types if ITypeConcept(t).typeInterface ... ]
|
|
||||||
return [objectAsDict(t, self.languageInfo) for t in types]
|
|
||||||
|
|
||||||
def getPredicates(self):
|
|
||||||
pt = self.concepts.getDefaultPredicate().conceptType
|
|
||||||
preds = pt.getChildren((self.concepts.getTypePredicate(),))
|
|
||||||
return [objectAsDict(p, self.languageInfo)
|
|
||||||
for p in preds if p is not self.typePredicate]
|
|
||||||
|
|
||||||
def getChildren(self, id, predicates=[], child=''):
|
|
||||||
obj = getObjectForUid(id)
|
|
||||||
preds = [getObjectForUid(p) for p in predicates]
|
|
||||||
child = child and getObjectForUid(child) or None
|
|
||||||
rels = obj.getChildRelations(preds or None, child)
|
|
||||||
return formatRelations(rels, langInfo=self.languageInfo)
|
|
||||||
|
|
||||||
def getParents(self, id, predicates=[], parent=''):
|
|
||||||
obj = getObjectForUid(id)
|
|
||||||
preds = [getObjectForUid(p) for p in predicates]
|
|
||||||
parent = parent and getObjectForUid(parent) or None
|
|
||||||
rels = obj.getParentRelations(preds or None, parent)
|
|
||||||
return formatRelations(rels, useSecond=False, langInfo=self.languageInfo)
|
|
||||||
|
|
||||||
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, langInfo=self.languageInfo)
|
|
||||||
|
|
||||||
def getObjectWithChildren(self, obj):
|
|
||||||
mapping = objectAsDict(obj, self.languageInfo)
|
|
||||||
mapping['children'] = formatRelations(obj.getChildRelations(sort=None),
|
|
||||||
langInfo=self.languageInfo)
|
|
||||||
mapping['parents'] = formatRelations(obj.getParentRelations(sort=None),
|
|
||||||
useSecond=False,
|
|
||||||
langInfo=self.languageInfo)
|
|
||||||
mapping['resources'] = formatRelations(obj.getResourceRelations(sort=None),
|
|
||||||
langInfo=self.languageInfo)
|
|
||||||
return mapping
|
|
||||||
|
|
||||||
def assignChild(self, objId, predicateId, childId):
|
|
||||||
pred = getObjectForUid(predicateId)
|
|
||||||
if pred == self.typePredicate:
|
|
||||||
return 'Not allowed'
|
|
||||||
obj = getObjectForUid(objId)
|
|
||||||
child = getObjectForUid(childId)
|
|
||||||
obj.assignChild(child, pred)
|
|
||||||
return 'OK'
|
|
||||||
|
|
||||||
def deassignChild(self, objId, predicateId, childId):
|
|
||||||
pred = getObjectForUid(predicateId)
|
|
||||||
if pred == self.typePredicate:
|
|
||||||
return 'Not allowed'
|
|
||||||
obj = getObjectForUid(objId)
|
|
||||||
child = getObjectForUid(childId)
|
|
||||||
obj.deassignChild(child, [pred])
|
|
||||||
return 'OK'
|
|
||||||
|
|
||||||
def createConcept(self, typeId, name, title):
|
|
||||||
type = getObjectForUid(typeId)
|
|
||||||
title = toUnicode(title)
|
|
||||||
c = Concept(title)
|
|
||||||
name = INameChooser(self.concepts).chooseName(name, c)
|
|
||||||
self.concepts[name] = c
|
|
||||||
c.conceptType = type
|
|
||||||
adapted(c, self.languageInfo).title = title
|
|
||||||
notify(ObjectCreatedEvent(c))
|
|
||||||
notify(ObjectModifiedEvent(c))
|
|
||||||
return objectAsDict(c, self.languageInfo)
|
|
||||||
|
|
||||||
def editConcept(self, objId, attr, value):
|
|
||||||
obj = getObjectForUid(objId)
|
|
||||||
adapter = adapted(obj, self.languageInfo)
|
|
||||||
# TODO: provide conversion if necessary - use cybertools.composer.schema
|
|
||||||
value = value.strip() # remove spaces appended by Flash
|
|
||||||
setattr(adapter, attr, toUnicode(value))
|
|
||||||
notify(ObjectModifiedEvent(obj))
|
|
||||||
return 'OK'
|
|
||||||
|
|
||||||
|
|
||||||
def objectAsDict(obj, langInfo=None):
|
|
||||||
objType = IType(obj)
|
|
||||||
adapter = adapted(obj, langInfo)
|
|
||||||
mapping = {'id': getUidForObject(obj), 'name': getName(obj),
|
|
||||||
'title': adapter.title, 'description': adapter.description,
|
|
||||||
'type': getUidForObject(objType.typeProvider)}
|
|
||||||
ti = objType.typeInterface
|
|
||||||
if ti is not None and isinstance(adapter, AdapterBase): #adapter != obj:
|
|
||||||
#for attr in (list(adapter._adapterAttributes) + list(ti)):
|
|
||||||
for attr in list(ti):
|
|
||||||
if attr not in ('__parent__', 'context', 'id', 'name',
|
|
||||||
'title', 'description', 'type', 'data'):
|
|
||||||
value = getattr(adapter, attr)
|
|
||||||
# TODO: provide conversion and schema information -
|
|
||||||
# use cybertools.composer.schema
|
|
||||||
#if value is None or type(value) in (str, unicode):
|
|
||||||
if ITextLine.providedBy(ti[attr]):
|
|
||||||
mapping[attr] = value or u''
|
|
||||||
#elif type(value) is list:
|
|
||||||
# mapping[attr] = ' | '.join(value)
|
|
||||||
return mapping
|
|
||||||
|
|
||||||
def formatRelations(rels, useSecond=True, langInfo=None):
|
|
||||||
predIds = {}
|
|
||||||
result = []
|
|
||||||
for rel in rels:
|
|
||||||
pred = rel.predicate
|
|
||||||
predId = getUidForObject(pred)
|
|
||||||
if not predId in predIds:
|
|
||||||
predIds[predId] = len(result)
|
|
||||||
result.append({'id': predId, 'name': getName(pred),
|
|
||||||
'title': pred.title, 'objects': []})
|
|
||||||
if useSecond:
|
|
||||||
other = rel.second
|
|
||||||
else:
|
|
||||||
other = rel.first
|
|
||||||
result[predIds[predId]]['objects'].append(objectAsDict(other, langInfo))
|
|
||||||
return sorted(result, key=lambda x: x['title'])
|
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
<!-- $Id$ -->
|
|
||||||
|
|
||||||
<configure
|
|
||||||
xmlns:zope="http://namespaces.zope.org/zope"
|
|
||||||
xmlns="http://namespaces.zope.org/xmlrpc"
|
|
||||||
i18n_domain="zope">
|
|
||||||
|
|
||||||
<view
|
|
||||||
name="xrf"
|
|
||||||
for="loops.interfaces.ILoops"
|
|
||||||
class="loops.xmlrpc.common.LoopsMethods"
|
|
||||||
methods="getStartObject getObjectById getObjectByName
|
|
||||||
getDefaultPredicate getTypePredicate getTypeConcept
|
|
||||||
getConceptTypes getPredicates
|
|
||||||
getChildren getParents getResources
|
|
||||||
assignChild deassignChild createConcept editConcept"
|
|
||||||
permission="loops.xmlrpc.ManageConcepts"
|
|
||||||
/>
|
|
||||||
|
|
||||||
</configure>
|
|
|
@ -1,20 +0,0 @@
|
||||||
|
|
||||||
import unittest, doctest
|
|
||||||
|
|
||||||
|
|
||||||
class Test(unittest.TestCase):
|
|
||||||
"Basic tests for the loops.xmlrpc package."
|
|
||||||
|
|
||||||
def testBasics(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def test_suite():
|
|
||||||
flags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS
|
|
||||||
return unittest.TestSuite((
|
|
||||||
unittest.makeSuite(Test),
|
|
||||||
doctest.DocFileSuite('README.txt', optionflags=flags),
|
|
||||||
))
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
unittest.main(defaultTest='test_suite')
|
|
Loading…
Add table
Reference in a new issue