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
|
>>> from loops.concept import PredicateSourceList
|
||||||
>>> predicates = PredicateSourceList(cc1)
|
>>> 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)
|
>>> sorted(t.title for t in predicates)
|
||||||
[u'has type', u'subconcept']
|
[u'subconcept']
|
||||||
|
|
||||||
Concept Views
|
Concept Views
|
||||||
-------------
|
-------------
|
||||||
|
@ -209,8 +213,7 @@ types and predicates.
|
||||||
(u'Unknown Type', '.loops/concepts/unknown')]
|
(u'Unknown Type', '.loops/concepts/unknown')]
|
||||||
|
|
||||||
>>> sorted((t.title, t.token) for t in view.predicates())
|
>>> 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
|
Index attributes adapter
|
||||||
------------------------
|
------------------------
|
||||||
|
|
|
@ -272,6 +272,10 @@ class ConceptRelationView(BaseView):
|
||||||
return ':'.join((self.loopsRoot.getLoopsUri(self.context),
|
return ':'.join((self.loopsRoot.getLoopsUri(self.context),
|
||||||
self.loopsRoot.getLoopsUri(self.predicate)))
|
self.loopsRoot.getLoopsUri(self.predicate)))
|
||||||
|
|
||||||
|
@Lazy
|
||||||
|
def isProtected(self):
|
||||||
|
return zapi.getName(self.predicate) == 'hasType'
|
||||||
|
|
||||||
@Lazy
|
@Lazy
|
||||||
def predicateTitle(self):
|
def predicateTitle(self):
|
||||||
return self.predicate.title
|
return self.predicate.title
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
<td class="field">
|
<td class="field">
|
||||||
<input class="formSelection"
|
<input class="formSelection"
|
||||||
type="checkbox" name="tokens:list" id="#" value=""
|
type="checkbox" name="tokens:list" id="#" value=""
|
||||||
|
tal:condition="not:item/isProtected|nothing"
|
||||||
tal:attributes="value item/token" />
|
tal:attributes="value item/token" />
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
|
|
@ -271,11 +271,12 @@ class PredicateSourceList(object):
|
||||||
typePred = cm.getTypePredicate()
|
typePred = cm.getTypePredicate()
|
||||||
if defPred is not None and typePred is not None:
|
if defPred is not None and typePred is not None:
|
||||||
result.append(defPred)
|
result.append(defPred)
|
||||||
result.append(typePred)
|
#result.append(typePred)
|
||||||
predType = defPred.conceptType
|
predType = defPred.conceptType
|
||||||
if predType is not None and predType != cm.getTypeConcept():
|
if predType is not None and predType != cm.getTypeConcept():
|
||||||
result.extend(p for p in predType.getChildren([typePred])
|
result.extend(p for p in predType.getChildren([typePred])
|
||||||
if p not in result)
|
if p not in result
|
||||||
|
and p != typePred)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def __len__(self):
|
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')
|
_ = MessageFactory('zope')
|
||||||
|
|
||||||
|
|
||||||
|
def getPersonForLoggedInUser(request):
|
||||||
|
pa = annotations(request.principal)
|
||||||
|
return pa.get(ANNOTATION_KEY, None)
|
||||||
|
|
||||||
|
|
||||||
class MyStuff(ConceptView):
|
class MyStuff(ConceptView):
|
||||||
|
|
||||||
def __init__(self, context, request):
|
def __init__(self, context, request):
|
||||||
self.context = context
|
self.context = context
|
||||||
self.request = request
|
self.request = request
|
||||||
pa = annotations(request.principal)
|
self.person = getPersonForLoggedInUser(request)
|
||||||
self.person = pa.get(ANNOTATION_KEY, None)
|
|
||||||
if self.person is not None:
|
if self.person is not None:
|
||||||
self.context = self.person
|
self.context = self.person
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@ from loops.organize.interfaces import IPerson, ANNOTATION_KEY
|
||||||
from loops.type import TypeInterfaceSourceList, AdapterBase
|
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)
|
TypeInterfaceSourceList.typeInterfaces += (IPerson, IAddress)
|
||||||
|
|
||||||
|
|
2
type.py
2
type.py
|
@ -224,7 +224,7 @@ class AdapterBase(object):
|
||||||
adapts(IConcept)
|
adapts(IConcept)
|
||||||
|
|
||||||
_attributes = ('context', '__parent__', )
|
_attributes = ('context', '__parent__', )
|
||||||
_schemas = (IConcept,)
|
_schemas = list(IConcept)
|
||||||
|
|
||||||
def __init__(self, context):
|
def __init__(self, context):
|
||||||
self.context = context # to get the permission stuff right
|
self.context = context # to get the permission stuff right
|
||||||
|
|
Loading…
Add table
Reference in a new issue