set up knowledge stuff for loops
git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@1230 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
parent
98c195492e
commit
8423fcea57
14 changed files with 569 additions and 9 deletions
|
@ -142,8 +142,12 @@ a special concept type.
|
|||
|
||||
>>> from loops.concept import PredicateSourceList
|
||||
>>> predicates = PredicateSourceList(cc1)
|
||||
|
||||
Note that the 'hasType' predicate is suppressed from this list as the
|
||||
corresponding relation is only assigned via the conceptType attribute:
|
||||
|
||||
>>> sorted(t.title for t in predicates)
|
||||
[u'has type', u'subconcept']
|
||||
[u'subconcept']
|
||||
|
||||
Concept Views
|
||||
-------------
|
||||
|
@ -209,8 +213,7 @@ types and predicates.
|
|||
(u'Unknown Type', '.loops/concepts/unknown')]
|
||||
|
||||
>>> sorted((t.title, t.token) for t in view.predicates())
|
||||
[(u'has type', '.loops/concepts/hasType'),
|
||||
(u'subconcept', '.loops/concepts/standard')]
|
||||
[(u'subconcept', '.loops/concepts/standard')]
|
||||
|
||||
Index attributes adapter
|
||||
------------------------
|
||||
|
|
|
@ -272,6 +272,10 @@ class ConceptRelationView(BaseView):
|
|||
return ':'.join((self.loopsRoot.getLoopsUri(self.context),
|
||||
self.loopsRoot.getLoopsUri(self.predicate)))
|
||||
|
||||
@Lazy
|
||||
def isProtected(self):
|
||||
return zapi.getName(self.predicate) == 'hasType'
|
||||
|
||||
@Lazy
|
||||
def predicateTitle(self):
|
||||
return self.predicate.title
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
<td class="field">
|
||||
<input class="formSelection"
|
||||
type="checkbox" name="tokens:list" id="#" value=""
|
||||
tal:condition="not:item/isProtected|nothing"
|
||||
tal:attributes="value item/token" />
|
||||
</td>
|
||||
<td>
|
||||
|
|
|
@ -271,11 +271,12 @@ class PredicateSourceList(object):
|
|||
typePred = cm.getTypePredicate()
|
||||
if defPred is not None and typePred is not None:
|
||||
result.append(defPred)
|
||||
result.append(typePred)
|
||||
#result.append(typePred)
|
||||
predType = defPred.conceptType
|
||||
if predType is not None and predType != cm.getTypeConcept():
|
||||
result.extend(p for p in predType.getChildren([typePred])
|
||||
if p not in result)
|
||||
if p not in result
|
||||
and p != typePred)
|
||||
return result
|
||||
|
||||
def __len__(self):
|
||||
|
|
207
knowledge/README.txt
Normal file
207
knowledge/README.txt
Normal file
|
@ -0,0 +1,207 @@
|
|||
===============================================================
|
||||
loops - Linked Objects for Organization and Processing Services
|
||||
===============================================================
|
||||
|
||||
($Id$)
|
||||
|
||||
Note: This package depends on cybertools.knowledge and cybertools.organize.
|
||||
|
||||
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.app import zapi
|
||||
|
||||
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
|
||||
ZCML setup):
|
||||
|
||||
>>> from loops import Loops
|
||||
>>> from loops.concept import ConceptManager, Concept
|
||||
>>> from loops.resource import ResourceManager
|
||||
>>> from loops.interfaces import IResource, IConcept, ITypeConcept
|
||||
|
||||
>>> loopsRoot = site['loops'] = Loops()
|
||||
|
||||
>>> from cybertools.relation.interfaces import IRelationRegistry
|
||||
>>> from cybertools.relation.registry import DummyRelationRegistry
|
||||
>>> relations = DummyRelationRegistry()
|
||||
>>> component.provideUtility(relations, IRelationRegistry)
|
||||
|
||||
>>> from cybertools.typology.interfaces import IType
|
||||
>>> from loops.type import ConceptType, TypeConcept
|
||||
>>> component.provideAdapter(ConceptType, (IConcept,), IType)
|
||||
>>> component.provideAdapter(TypeConcept, (IConcept,), ITypeConcept)
|
||||
|
||||
>>> concepts = loopsRoot['concepts'] = ConceptManager()
|
||||
>>> resources = loopsRoot['resources'] = ResourceManager()
|
||||
|
||||
>>> hasType = concepts['hasType'] = Concept(u'has type')
|
||||
>>> type = concepts['type'] = Concept(u'Type')
|
||||
>>> type.conceptType = type
|
||||
|
||||
>>> predicate = concepts['predicate'] = Concept(u'Predicate')
|
||||
>>> predicate.conceptType = type
|
||||
>>> hasType.conceptType = predicate
|
||||
|
||||
We need some predicates to set up the relationships between our concepts:
|
||||
|
||||
>>> standard = concepts['standard'] = Concept(u'subobject')
|
||||
>>> depends = concepts['depends'] = Concept(u'depends')
|
||||
>>> knows = concepts['knows'] = Concept(u'knows')
|
||||
>>> requires = concepts['requires'] = Concept(u'requires')
|
||||
>>> provides = concepts['provides'] = Concept(u'provides')
|
||||
|
||||
>>> for p in (standard, depends, knows, requires, provides):
|
||||
... p.conceptType = predicate
|
||||
|
||||
And last not least we need some type concepts for controlling the
|
||||
meaning of the concepts objects:
|
||||
|
||||
>>> from cybertools.knowledge.interfaces import IKnowledgeElement
|
||||
>>> topic = concepts['topic'] = Concept(u'Topic')
|
||||
>>> topic.conceptType = type
|
||||
>>> ITypeConcept(topic).typeInterface = IKnowledgeElement
|
||||
|
||||
>>> from loops.knowledge.interfaces import IPerson
|
||||
>>> person = concepts['person'] = Concept(u'Person')
|
||||
>>> person.conceptType = type
|
||||
>>> ITypeConcept(person).typeInterface = IPerson
|
||||
|
||||
>>> from loops.knowledge.interfaces import ITask
|
||||
>>> task = concepts['task'] = Concept(u'Task')
|
||||
>>> task.conceptType = type
|
||||
>>> ITypeConcept(task).typeInterface = ITask
|
||||
|
||||
|
||||
Manage knowledge and knowledge requirements
|
||||
===========================================
|
||||
|
||||
The classes used in this package are just adapters to IConcept.
|
||||
|
||||
>>> from loops.knowledge.knowledge import Person, Topic, Task
|
||||
>>> component.provideAdapter(Person, (IConcept,), IPerson)
|
||||
>>> component.provideAdapter(Topic, (IConcept,), IKnowledgeElement)
|
||||
>>> component.provideAdapter(Task, (IConcept,), ITask)
|
||||
|
||||
First we want to set up a tree of knowledge elements (topics) and their
|
||||
interdependencies. Note that in order to discern the concepts created
|
||||
from their typeInterface adapters we here append a 'C' to the name of
|
||||
the variables:
|
||||
|
||||
>>> progLangC = concepts['progLang'] = Concept(u'Programming Language')
|
||||
>>> ooProgC = concepts['ooProg'] = Concept(u'Object-oriented Programming')
|
||||
>>> pythonC = concepts['python'] = Concept(u'Python')
|
||||
>>> pyBasicsC = concepts['pyBasics'] = Concept(u'Python Basics')
|
||||
>>> pyOoC = concepts['pyOo'] = Concept(u'OO Programming with Python')
|
||||
>>> pySpecialsC = concepts['pySpecials'] = Concept(u'Python Specials')
|
||||
|
||||
>>> topicConcepts = (progLangC, ooProgC, pythonC, pyBasicsC, pyOoC, pySpecialsC)
|
||||
|
||||
>>> for c in topicConcepts: c.conceptType = topic
|
||||
|
||||
>>> progLang, ooProg, python, pyBasics, pyOo, pySpecials = (IKnowledgeElement(c)
|
||||
... for c in topicConcepts)
|
||||
|
||||
>>> python.parent = progLang
|
||||
>>> pyBasics.parent = python
|
||||
>>> pyOo.parent = python
|
||||
>>> pySpecials.parent = python
|
||||
|
||||
>>> pyOo.dependsOn(ooProg)
|
||||
>>> pyOo.dependsOn(pyBasics)
|
||||
|
||||
We now create a person and assign some knowledge to it:
|
||||
|
||||
>>> johnC = concepts['john'] = Concept(u'John')
|
||||
>>> johnC.conceptType = person
|
||||
|
||||
>>> john = IPerson(johnC)
|
||||
>>> john.knows(pyBasics)
|
||||
>>> list(john.getKnowledge())[0].title
|
||||
u'Python Basics'
|
||||
|
||||
Now let's get to tasks - a task is used as a requirement profile, i.e.
|
||||
it requires a certain set of knowledge elements:
|
||||
|
||||
>>> task01C = concepts['task01C'] = Concept('Task: needs Python OO')
|
||||
>>> task01C.conceptType = task
|
||||
|
||||
>>> task01 = ITask(task01C)
|
||||
>>> task01.requires(pyOo)
|
||||
|
||||
Now we can ask what knowledge john is lacking if he would like to take
|
||||
a position with the requirement profile:
|
||||
|
||||
>>> missing = john.getMissingKnowledge(task01)
|
||||
>>> [m.title for m in missing]
|
||||
[u'Object-oriented Programming', u'OO Programming with Python']
|
||||
|
||||
Luckily there are a few elearning content objects out there that
|
||||
provide some of the knowledge needed:
|
||||
|
||||
>>> from cybertools.knowledge.interfaces import IKnowledgeProvider
|
||||
>>> from loops.knowledge.knowledge import ConceptKnowledgeProvider
|
||||
>>> component.provideAdapter(ConceptKnowledgeProvider, (IConcept,))
|
||||
>>> from loops.knowledge.knowledge import ResourceKnowledgeProvider
|
||||
>>> component.provideAdapter(ResourceKnowledgeProvider, (IResource,))
|
||||
|
||||
>>> doc01C = concepts['doc01'] = Concept('Objectorienting Programming')
|
||||
>>> doc01 = IKnowledgeProvider(doc01C)
|
||||
>>> from loops.resource import Document
|
||||
>>> doc02D = resources['doc02'] = Document('oopython.pdf')
|
||||
>>> doc02 = IKnowledgeProvider(doc02D)
|
||||
|
||||
>>> doc01.provides(ooProg)
|
||||
>>> doc02.provides(pyOo)
|
||||
|
||||
So that we are now able to find out what john has to study in order to
|
||||
fulfill the position offered:
|
||||
|
||||
>>> prov = list(john.getProvidersNeeded(task01))
|
||||
>>> len(prov)
|
||||
2
|
||||
>>> [list(d)[0].title for k, d in prov]
|
||||
['Objectorienting Programming', 'oopython.pdf']
|
||||
|
||||
|
||||
Views that make use of the knowledge management modules
|
||||
-------------------------------------------------------
|
||||
|
||||
One of the practical applications of this stuff is searching for missing
|
||||
knowledge and corresponding knowledge providers for the user currently
|
||||
logged in.
|
||||
|
||||
For testing, we first have to provide the needed utilities and settings
|
||||
(in real life this is all done during Zope startup):
|
||||
|
||||
>>> from zope.app.security.interfaces import IAuthentication
|
||||
>>> from zope.app.security.principalregistry import PrincipalRegistry
|
||||
>>> auth = PrincipalRegistry()
|
||||
>>> component.provideUtility(auth, IAuthentication)
|
||||
|
||||
>>> from zope.app.principalannotation.interfaces import IPrincipalAnnotationUtility
|
||||
>>> from zope.app.principalannotation import PrincipalAnnotationUtility
|
||||
>>> principalAnnotations = PrincipalAnnotationUtility()
|
||||
>>> component.provideUtility(principalAnnotations, IPrincipalAnnotationUtility)
|
||||
|
||||
>>> principal = auth.definePrincipal('users.john', u'John', login='john')
|
||||
>>> john.userId = 'users.john'
|
||||
|
||||
>>> from zope.publisher.browser import TestRequest
|
||||
>>> request = TestRequest()
|
||||
>>> request.setPrincipal(principal)
|
||||
|
||||
>>> from loops.knowledge.browser import MyKnowledge
|
||||
>>> view = MyKnowledge(task01C, request)
|
||||
>>> prov = view.myKnowledgeProvidersForTask()
|
||||
|
||||
|
||||
|
||||
Fin de partie
|
||||
=============
|
||||
|
||||
>>> placefulTearDown()
|
||||
|
4
knowledge/__init__.py
Normal file
4
knowledge/__init__.py
Normal file
|
@ -0,0 +1,4 @@
|
|||
"""
|
||||
$Id$
|
||||
"""
|
||||
|
64
knowledge/browser.py
Normal file
64
knowledge/browser.py
Normal file
|
@ -0,0 +1,64 @@
|
|||
#
|
||||
# Copyright (c) 2004 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
|
||||
#
|
||||
|
||||
"""
|
||||
Definition of view classes and other browser related stuff for the
|
||||
loops.knowledge package.
|
||||
|
||||
$Id$
|
||||
"""
|
||||
|
||||
from zope import interface, component
|
||||
from zope.app import zapi
|
||||
from zope.app.pagetemplate import ViewPageTemplateFile
|
||||
from zope.cachedescriptors.property import Lazy
|
||||
from zope.formlib.namedtemplate import NamedTemplate
|
||||
from zope.i18nmessageid import MessageFactory
|
||||
|
||||
from cybertools.typology.interfaces import IType
|
||||
from loops.browser.common import BaseView
|
||||
from loops.knowledge.interfaces import IPerson, ITask
|
||||
from loops.organize.browser import getPersonForLoggedInUser
|
||||
|
||||
_ = MessageFactory('zope')
|
||||
|
||||
|
||||
class MyKnowledge(BaseView):
|
||||
|
||||
def __init__(self, context, request):
|
||||
self.context = context
|
||||
self.request = request
|
||||
person = getPersonForLoggedInUser(request)
|
||||
if person is not None:
|
||||
person = IPerson(person)
|
||||
self.person = person
|
||||
|
||||
def myKnowledge(self):
|
||||
if self.person is None:
|
||||
return ()
|
||||
knowledge = self.person.getKnowledge()
|
||||
return knowledge
|
||||
|
||||
def myKnowledgeProvidersForTask(self):
|
||||
if self.person is None:
|
||||
return ()
|
||||
task = ITask(self.context)
|
||||
# TODO: check correct conceptType for context!
|
||||
providers = self.person.getProvidersNeeded(task)
|
||||
return providers
|
||||
|
20
knowledge/configure.zcml
Normal file
20
knowledge/configure.zcml
Normal file
|
@ -0,0 +1,20 @@
|
|||
<!-- $Id$ -->
|
||||
|
||||
<configure
|
||||
xmlns:zope="http://namespaces.zope.org/zope"
|
||||
xmlns:browser="http://namespaces.zope.org/browser"
|
||||
i18n_domain="zope"
|
||||
>
|
||||
|
||||
<!-- knowledge/learning management stuff -->
|
||||
|
||||
<zope:adapter factory="loops.knowledge.knowledge.Person"
|
||||
provides="loops.knowledge.interfaces.IPerson"
|
||||
trusted="True" />
|
||||
|
||||
<zope:class class="loops.knowledge.knowledge.Person">
|
||||
<require permission="zope.View"
|
||||
interface="loops.knowledge.interfaces.IPerson" />
|
||||
</zope:class>
|
||||
|
||||
</configure>
|
45
knowledge/interfaces.py
Normal file
45
knowledge/interfaces.py
Normal file
|
@ -0,0 +1,45 @@
|
|||
#
|
||||
# Copyright (c) 2006 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
|
||||
#
|
||||
|
||||
"""
|
||||
Interfaces for knowledge management and elearning with loops.
|
||||
|
||||
$Id$
|
||||
"""
|
||||
|
||||
from zope.interface import Interface, Attribute
|
||||
from zope import interface, component, schema
|
||||
from zope.app import zapi
|
||||
from zope.i18nmessageid import MessageFactory
|
||||
from zope.security.proxy import removeSecurityProxy
|
||||
|
||||
from cybertools.knowledge.interfaces import IKnowing, IRequirementProfile
|
||||
from cybertools.organize.interfaces import IPerson as IBasePerson
|
||||
from cybertools.organize.interfaces import ITask as IBaseTask
|
||||
|
||||
_ = MessageFactory('zope')
|
||||
|
||||
|
||||
class IPerson(IBasePerson, IKnowing):
|
||||
""" A person, including knowledge/learning management features.
|
||||
"""
|
||||
|
||||
|
||||
class ITask(IBaseTask, IRequirementProfile):
|
||||
""" A task, also acting as a knowledge requirement profile.
|
||||
"""
|
183
knowledge/knowledge.py
Normal file
183
knowledge/knowledge.py
Normal file
|
@ -0,0 +1,183 @@
|
|||
#
|
||||
# Copyright (c) 2006 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
|
||||
#
|
||||
|
||||
"""
|
||||
Adapters for IConcept providing interfaces from the
|
||||
cybertools.knowledge package.
|
||||
|
||||
$Id$
|
||||
"""
|
||||
|
||||
from zope import interface, component
|
||||
from zope.app import zapi
|
||||
from zope.component import adapts
|
||||
from zope.interface import implements
|
||||
from zope.cachedescriptors.property import Lazy
|
||||
|
||||
from cybertools.typology.interfaces import IType
|
||||
from cybertools.knowledge.interfaces import IKnowledgeElement, IKnowledgeProvider
|
||||
from cybertools.knowledge.knowing import Knowing
|
||||
from loops.interfaces import IConcept
|
||||
from loops.knowledge.interfaces import IPerson, ITask
|
||||
from loops.organize.party import Person as BasePerson
|
||||
from loops.organize.task import Task as BaseTask
|
||||
from loops.type import TypeInterfaceSourceList, AdapterBase
|
||||
|
||||
|
||||
# register type interfaces - (TODO: use a function for this)
|
||||
|
||||
TypeInterfaceSourceList.typeInterfaces += (IPerson, IKnowledgeElement, ITask)
|
||||
|
||||
|
||||
class KnowledgeAdapterMixin(object):
|
||||
|
||||
@Lazy
|
||||
def conceptManager(self):
|
||||
return self.context.getLoopsRoot().getConceptManager()
|
||||
|
||||
@Lazy
|
||||
def standardPred(self):
|
||||
return self.conceptManager.getDefaultPredicate()
|
||||
|
||||
@Lazy
|
||||
def dependsPred(self):
|
||||
return self.conceptManager['depends']
|
||||
|
||||
@Lazy
|
||||
def knowsPred(self):
|
||||
return self.conceptManager['knows']
|
||||
|
||||
@Lazy
|
||||
def requiresPred(self):
|
||||
return self.conceptManager['requires']
|
||||
|
||||
@Lazy
|
||||
def providesPred(self):
|
||||
return self.conceptManager['provides']
|
||||
|
||||
def __eq__(self, other):
|
||||
return self.context == other.context
|
||||
|
||||
|
||||
class Person(BasePerson, Knowing, KnowledgeAdapterMixin):
|
||||
""" A typeInterface adapter for concepts of type 'person', including
|
||||
knowledge/learning management features.
|
||||
"""
|
||||
|
||||
implements(IPerson)
|
||||
|
||||
def getKnowledge(self):
|
||||
return (IKnowledgeElement(c)
|
||||
for c in self.context.getParents((self.knowsPred,)))
|
||||
|
||||
def knows(self, obj):
|
||||
self.context.assignParent(obj.context, self.knowsPred)
|
||||
|
||||
def removeKnowledge(self, obj):
|
||||
self.context.deassignParent(obj.context, (self.knowsPred,))
|
||||
|
||||
|
||||
class Topic(AdapterBase, KnowledgeAdapterMixin):
|
||||
""" A typeInterface adapter for concepts of type 'topic' that
|
||||
may act as a knowledge element.
|
||||
"""
|
||||
|
||||
implements(IKnowledgeElement)
|
||||
_attributes = ('context', '__parent__', 'parent')
|
||||
|
||||
def getParent(self):
|
||||
parents = self.context.getParents((self.standardPred,))
|
||||
return parents and IKnowledgeElement(parents[0]) or None
|
||||
def setParent(self, obj):
|
||||
old = self.getParent()
|
||||
if old is not None and old.context != self.context:
|
||||
self.context.deassignParent(old.context, (self.standardPred,))
|
||||
self.context.assignParent(obj.context, self.standardPred)
|
||||
parent = property(getParent, setParent)
|
||||
|
||||
def getDependencies(self):
|
||||
return (IKnowledgeElement(c)
|
||||
for c in self.context.getParents((self.dependsPred,)))
|
||||
|
||||
def dependsOn(self, obj):
|
||||
self.context.assignParent(obj.context, self.dependsPred)
|
||||
|
||||
def removeDependency(self, obj):
|
||||
self.context.deassignParent(obj.context, (self.dependsPred,))
|
||||
|
||||
def getDependents(self):
|
||||
return (IKnowledgeElement(c)
|
||||
for c in self.context.getChildren((self.dependsPred,)))
|
||||
|
||||
def getKnowers(self):
|
||||
return (IPerson(c)
|
||||
for c in self.context.getChildren((self.knowsPred,)))
|
||||
|
||||
def getProviders(self):
|
||||
return (IKnowledgeProvider(c)
|
||||
for c in self.context.getChildren((self.providesPred,))
|
||||
+ self.context.getResources((self.providesPred,)))
|
||||
|
||||
|
||||
class Task(BaseTask, KnowledgeAdapterMixin):
|
||||
""" A typeInterface adapter for concepts of type 'task' that
|
||||
may act as a knowledge requirement profile.
|
||||
"""
|
||||
|
||||
implements(ITask)
|
||||
|
||||
def getRequirements(self):
|
||||
return (IKnowledgeElement(c)
|
||||
for c in self.context.getParents((self.requiresPred,)))
|
||||
|
||||
def requires(self, obj):
|
||||
self.context.assignParent(obj.context, self.requiresPred)
|
||||
|
||||
def removeRequirement(self, obj):
|
||||
self.context.deassignParent(obj.context, (self.requiresPred,))
|
||||
|
||||
|
||||
class ConceptKnowledgeProvider(AdapterBase, KnowledgeAdapterMixin):
|
||||
|
||||
implements(IKnowledgeProvider)
|
||||
|
||||
def getProvidedKnowledge(self):
|
||||
return (IKnowledgeElement(c)
|
||||
for c in self.context.getParents((self.providesPred,)))
|
||||
|
||||
def provides(self, obj):
|
||||
self.context.assignParent(obj.context, self.providesPred)
|
||||
|
||||
def removeProvidedKnowledge(self, obj):
|
||||
self.context.deassignParent(obj.context, (self.providesPred,))
|
||||
|
||||
|
||||
class ResourceKnowledgeProvider(AdapterBase, KnowledgeAdapterMixin):
|
||||
|
||||
implements(IKnowledgeProvider)
|
||||
|
||||
def getProvidedKnowledge(self):
|
||||
return (IKnowledgeElement(c)
|
||||
for c in self.context.getConcepts((self.providesPred,)))
|
||||
|
||||
def provides(self, obj):
|
||||
self.context.assignConcept(obj.context, self.providesPred)
|
||||
|
||||
def removeProvidedKnowledge(self, obj):
|
||||
self.context.deassignConcept(obj.context, (self.providesPred,))
|
||||
|
24
knowledge/tests.py
Executable file
24
knowledge/tests.py
Executable file
|
@ -0,0 +1,24 @@
|
|||
# $Id$
|
||||
|
||||
import unittest, doctest
|
||||
from zope.testing.doctestunit import DocFileSuite
|
||||
from zope.app.testing import ztapi
|
||||
from zope.interface.verify import verifyClass
|
||||
from loops.organize.party import Person
|
||||
|
||||
class Test(unittest.TestCase):
|
||||
"Basic tests for the knowledge sub-package."
|
||||
|
||||
def testSomething(self):
|
||||
pass
|
||||
|
||||
|
||||
def test_suite():
|
||||
flags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS
|
||||
return unittest.TestSuite((
|
||||
unittest.makeSuite(Test),
|
||||
DocFileSuite('README.txt', optionflags=flags),
|
||||
))
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(defaultTest='test_suite')
|
|
@ -44,13 +44,17 @@ from loops.organize.interfaces import IMemberRegistration
|
|||
_ = MessageFactory('zope')
|
||||
|
||||
|
||||
def getPersonForLoggedInUser(request):
|
||||
pa = annotations(request.principal)
|
||||
return pa.get(ANNOTATION_KEY, None)
|
||||
|
||||
|
||||
class MyStuff(ConceptView):
|
||||
|
||||
def __init__(self, context, request):
|
||||
self.context = context
|
||||
self.request = request
|
||||
pa = annotations(request.principal)
|
||||
self.person = pa.get(ANNOTATION_KEY, None)
|
||||
self.person = getPersonForLoggedInUser(request)
|
||||
if self.person is not None:
|
||||
self.context = self.person
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ from loops.organize.interfaces import IPerson, ANNOTATION_KEY
|
|||
from loops.type import TypeInterfaceSourceList, AdapterBase
|
||||
|
||||
|
||||
# register IPerson as a type interface - (TODO: use a function for this)
|
||||
# register type interfaces - (TODO: use a function for this)
|
||||
|
||||
TypeInterfaceSourceList.typeInterfaces += (IPerson, IAddress)
|
||||
|
||||
|
|
2
type.py
2
type.py
|
@ -224,7 +224,7 @@ class AdapterBase(object):
|
|||
adapts(IConcept)
|
||||
|
||||
_attributes = ('context', '__parent__', )
|
||||
_schemas = (IConcept,)
|
||||
_schemas = list(IConcept)
|
||||
|
||||
def __init__(self, context):
|
||||
self.context = context # to get the permission stuff right
|
||||
|
|
Loading…
Add table
Reference in a new issue