merge branch master

This commit is contained in:
Helmut Merz 2012-05-20 15:58:52 +02:00
commit 7813f8d806
25 changed files with 357 additions and 140 deletions

View file

@ -27,7 +27,7 @@ configuration):
>>> concepts, resources, views = t.setup()
>>> len(concepts), len(resources)
(20, 0)
(15, 0)
Let's now add an external collection that reads in a set of resources
from external files so we have something to work with.

View file

@ -24,7 +24,7 @@ from loops.integrator.collection import DirectoryCollectionProvider
from loops.integrator.collection import ExternalCollectionAdapter
from loops.integrator.interfaces import IExternalCollection, IExternalCollectionProvider
from loops.organize.setup import SetupManager as OrganizeSetupManager
from loops.knowledge.setup import SetupManager as KnowledgeSetupManager
#from loops.knowledge.setup import SetupManager as KnowledgeSetupManager
from loops.knowledge.knowledge import Person
from loops.knowledge.interfaces import IPerson
from loops.setup import SetupManager, addAndConfigureObject
@ -39,7 +39,7 @@ class TestSite(BaseTestSite):
self.site = site
def setup(self):
component.provideAdapter(KnowledgeSetupManager, name='knowledge')
#component.provideAdapter(KnowledgeSetupManager, name='knowledge')
component.provideAdapter(OrganizeSetupManager, name='organize')
concepts, resources, views = self.baseSetup()

View file

@ -27,7 +27,7 @@ configuration):
>>> concepts, resources, views = t.setup()
>>> len(concepts) + len(resources)
33
37
>>> loopsRoot = site['loops']
@ -47,19 +47,19 @@ Type- and text-based queries
>>> from loops.expert import query
>>> qu = query.Title('ty*')
>>> list(qu.apply())
[0, 1, 47]
[0, 1, 68]
>>> qu = query.Type('loops:*')
>>> len(list(qu.apply()))
33
37
>>> qu = query.Type('loops:concept:predicate')
>>> len(list(qu.apply()))
7
8
>>> qu = query.Type('loops:concept:predicate') & query.Title('t*')
>>> list(qu.apply())
[1, 43]
[1, 29]
State-based queries
-------------------

View file

@ -66,13 +66,13 @@ zcml in real life:
>>> t = searchView.typesForSearch()
>>> len(t)
14
16
>>> t.getTermByToken('loops:resource:*').title
'Any Resource'
>>> t = searchView.conceptTypesForSearch()
>>> len(t)
11
13
>>> t.getTermByToken('loops:concept:*').title
'Any Concept'
@ -91,7 +91,7 @@ a controller attribute for the search view.
>>> searchView.submitReplacing('1.results', '1.search.form', pageView)
'submitReplacing("1.results", "1.search.form",
"http://127.0.0.1/loops/views/page/.target80/@@searchresults.html");...'
"http://127.0.0.1/loops/views/page/.target99/@@searchresults.html");...'
Basic (text/title) search
-------------------------
@ -177,7 +177,7 @@ of the concepts' titles:
>>> request = TestRequest(form=form)
>>> view = Search(page, request)
>>> view.listConcepts()
u"{identifier: 'id', items: [{label: 'Zope (Topic)', name: 'Zope', id: '85'}, {label: 'Zope 2 (Topic)', name: 'Zope 2', id: '87'}, {label: 'Zope 3 (Topic)', name: 'Zope 3', id: '89'}]}"
u"{identifier: 'id', items: [{label: 'Zope (Thema)', name: 'Zope', id: '104'}, {label: 'Zope 2 (Thema)', name: 'Zope 2', id: '106'}, {label: 'Zope 3 (Thema)', name: 'Zope 3', id: '108'}]}"
Preset Concept Types on Search Forms
------------------------------------
@ -219,13 +219,13 @@ and thus include the customer type in the preset search types.
>>> searchView.conceptsForType('loops:concept:customer')
[{'token': 'none', 'title': u'not selected'},
{'token': '58', 'title': u'Customer 1'},
{'token': '60', 'title': u'Customer 2'},
{'token': '62', 'title': u'Customer 3'}]
{'token': '77', 'title': u'Customer 1'},
{'token': '79', 'title': u'Customer 2'},
{'token': '81', 'title': u'Customer 3'}]
Let's use this new search option for querying:
>>> form = {'search.4.text_selected': u'58'}
>>> form = {'search.4.text_selected': u'77'}
>>> resultsView = SearchResults(page, TestRequest(form=form))
>>> results = list(resultsView.results)
>>> results[0].title

View file

@ -14,7 +14,8 @@ from loops.expert.setup import SetupManager as ExpertSetupManager
from loops.resource import Resource
from loops.knowledge.interfaces import IPerson
from loops.knowledge.knowledge import Person
from loops.knowledge.setup import SetupManager as KnowledgeSetupManager
#from loops.knowledge.setup import SetupManager as KnowledgeSetupManager
from loops.knowledge.tests import importData
from loops.setup import SetupManager, addObject
from loops.tests.setup import TestSite as BaseTestSite
from loops.type import ConceptType, ResourceType, TypeConcept
@ -32,10 +33,11 @@ class TestSite(BaseTestSite):
component.provideAdapter(Person, provides=IPerson)
component.provideAdapter(KnowledgeSetupManager, name='knowledge')
#component.provideAdapter(KnowledgeSetupManager, name='knowledge')
component.provideAdapter(ExpertSetupManager, name='expert')
setup = SetupManager(loopsRoot)
concepts, resources, views = setup.setup()
importData(loopsRoot)
tType = concepts.getTypeConcept()
tDomain = concepts['domain']

8
external/README.txt vendored
View file

@ -17,7 +17,7 @@ Let's set up a loops site with basic and example concepts and resources.
>>> concepts, resources, views = t.setup()
>>> loopsRoot = site['loops']
>>> len(concepts), len(resources), len(views)
(30, 3, 1)
(34, 3, 1)
Importing loops Objects
@ -44,7 +44,7 @@ Creating the corresponding objects
>>> loader = Loader(loopsRoot)
>>> loader.load(elements)
>>> len(concepts), len(resources), len(views)
(31, 3, 1)
(35, 3, 1)
>>> from loops.common import adapted
>>> adMyquery = adapted(concepts['myquery'])
@ -131,7 +131,7 @@ Extracting elements
>>> extractor = Extractor(loopsRoot, os.path.join(dataDirectory, 'export'))
>>> elements = list(extractor.extract())
>>> len(elements)
53
68
Writing object information to the external storage
--------------------------------------------------
@ -143,6 +143,7 @@ Writing object information to the external storage
>>> writer = PyWriter()
>>> writer.write(elements, output)
>>> print output.getvalue()
type(u'task', ...)...
type(u'country', u'Country', viewName=u'', typeInterface=u''..., options=u''...)...
type(u'query', u'Query', viewName=u'', typeInterface='loops.expert.concept.IQueryConcept'..., options=u''...)...
concept(u'myquery', u'My Query', u'query', options=u'option1\noption2',
@ -184,6 +185,7 @@ corresponding extractor adapter.
>>> PyWriter().write(extractor.extract(), output)
>>> print output.getvalue()
type(u'task', ...)...
type(u'country', u'Country', viewName=u'', typeInterface=u''..., options=u''...)...
concept(u'myquery', u'My Query', u'query', options=u'option1\noption2',
viewName=u'mystuff.html')[

33
external/element.py vendored
View file

@ -30,10 +30,11 @@ from zope.traversing.api import getName, traverse
from cybertools.composer.interfaces import IInstance
from cybertools.composer.schema.interfaces import ISchemaFactory
from cybertools.tracking.btree import TrackingStorage
from cybertools.typology.interfaces import IType
from loops.common import adapted
from loops.interfaces import IConceptSchema
from loops.external.interfaces import IElement
from loops.interfaces import IConceptSchema
from loops.i18n.common import I18NValue
from loops.layout.base import LayoutNode
from loops.predicate import adaptedRelation
@ -132,6 +133,33 @@ class TypeElement(ConceptElement):
adapted(self.object).typeInterface = kw['typeInterface']
class RecordManagerElement(Element):
elementType = 'records'
posArgs = ('name', 'trackFactory')
def __init__(self, name, trackFactory, **kw):
self['name'] = name
tf = self['trackFactory'] = trackFactory
if not isinstance(tf, basestring):
self['trackFactory'] = '.'.join((tf.__module__, tf.__name__))
for k, v in kw.items():
self[k] = v
def execute(self, loader):
name = self['name']
tf = resolve(self['trackFactory'])
records = loader.context.getRecordManager()
obj = records.get(name)
if obj is None:
obj = records[name] = TrackingStorage(trackFactory=tf)
else:
obj.trackFactory = tf
obj.indexAttributes = tf.index_attributes
obj.setupIndexes()
self.object = obj
class ChildElement(Element):
elementType = 'child'
@ -261,6 +289,7 @@ class LayoutNodeElement(NodeElement):
elementTypes = dict(
type=TypeElement,
concept=ConceptElement,
records=RecordManagerElement,
child=ChildElement,
resource=ResourceElement,
resourceRelation=ResourceRelationElement,
@ -270,5 +299,5 @@ elementTypes = dict(
I18NValue=I18NValue,
)
toplevelElements = ('type', 'concept', 'resource',
toplevelElements = ('type', 'concept', 'resource', 'records',
'child', 'resourceRelation', 'node', 'deassign')

View file

@ -18,15 +18,15 @@ ZCML setup):
>>> from loops.interfaces import ILoops, IConcept
>>> from loops.concept import Concept
>>> from loops.setup import ISetupManager
>>> from loops.knowledge.setup import SetupManager
>>> component.provideAdapter(SetupManager, (ILoops,), ISetupManager,
... name='knowledge')
>>> from loops.tests.setup import TestSite
>>> t = TestSite(site)
>>> concepts, resources, views = t.setup()
>>> loopsRoot = site['loops']
>>> from loops.knowledge.tests import importData
>>> importData(loopsRoot)
>>> from loops.knowledge.knowledge import Topic
>>> component.provideAdapter(Topic)

View file

@ -27,7 +27,7 @@ configuration):
>>> concepts, resources, views = t.setup()
>>> len(concepts) + len(resources)
18
11
>>> loopsRoot = site['loops']
>>> #loopsRoot.options = ['useVersioning:rev']

View file

@ -18,7 +18,7 @@ from loops.resource import Resource, FileAdapter, ExternalFileAdapter
from loops.integrator.interfaces import IExternalSourceInfo, IExternalCollection
from loops.integrator.interfaces import IOfficeFile
from loops.integrator.office.base import OfficeFile
from loops.knowledge.setup import SetupManager as KnowledgeSetupManager
#from loops.knowledge.setup import SetupManager as KnowledgeSetupManager
from loops.setup import SetupManager, addAndConfigureObject
from loops.tests.setup import TestSite as BaseTestSite
from loops.versioning.versionable import VersionableResource
@ -32,7 +32,7 @@ class TestSite(BaseTestSite):
self.site = site
def setup(self):
component.provideAdapter(KnowledgeSetupManager, name='knowledge')
#component.provideAdapter(KnowledgeSetupManager, name='knowledge')
concepts, resources, views = self.baseSetup()
component.provideAdapter(FileAdapter, provides=IFile)

View file

@ -2,33 +2,32 @@
loops - Linked Objects for Organization and Processing Services
===============================================================
($Id$)
Note: This package depends on cybertools.knowledge and cybertools.organize.
Note: This package depends on cybertools.knowledge and loops.organize.
Let's do some basic set up
>>> from zope import component, interface
>>> from zope.app.testing.setup import placefulSetUp, placefulTearDown
>>> site = placefulSetUp(True)
>>> from zope import component, interface
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.interfaces import ILoops, IConcept
>>> from loops.setup import ISetupManager
>>> from loops.knowledge.setup import SetupManager
>>> component.provideAdapter(SetupManager, (ILoops,), ISetupManager,
... name='knowledge')
>>> from loops.tests.setup import TestSite
>>> t = TestSite(site)
>>> concepts, resources, views = t.setup()
>>> loopsRoot = site['loops']
We then import a loops .dmp file containing all necessary types and
predicates.
>>> from loops.knowledge.tests import importData
>>> importData(loopsRoot)
We need some type concepts for controlling the meaning of the concepts objects,
these have already been created during setup:
these have already been created during setup and .dmp import:
>>> topic = concepts['topic']
>>> person = concepts['person']
@ -40,6 +39,7 @@ Manage knowledge and knowledge requirements
The classes used in this package are just adapters to IConcept.
>>> from loops.interfaces import IConcept
>>> from loops.knowledge.knowledge import Person, Topic, Task
>>> from loops.knowledge.interfaces import IPerson
>>> from cybertools.knowledge.interfaces import IKnowledgeElement
@ -166,6 +166,34 @@ For testing, we first have to provide the needed utilities and settings
>>> view = MyKnowledge(task01C, request)
>>> prov = view.myKnowledgeProvidersForTask()
Competence and Certification Management
=======================================
>>> from cybertools.stateful.interfaces import IStatesDefinition
>>> from loops.knowledge.qualification import qualificationStates
>>> from loops.knowledge.interfaces import IQualificationRecords
>>> from loops.knowledge.qualification import QualificationRecords
>>> component.provideUtility(qualificationStates,
... provides=IStatesDefinition,
... name='knowledge.qualification')
>>> component.provideAdapter(QualificationRecords,
... provides=IQualificationRecords)
>>> qurecs = loopsRoot.getRecordManager()['qualification']
We first create a training that provides knowledge in Python specials.
>>> trainingPySpecC = concepts['trpyspec'] = Concept(
... u'Python Specials Training')
>>> trainingPySpecC.assignParent(pySpecialsC)
Then we record the need for John to acquire this knowledge.
>>> from loops.knowledge.browser import CreateQualificationRecordForm
>>> from loops.knowledge.browser import CreateQualificationRecord
Glossaries
==========

View file

@ -1,5 +1,5 @@
#
# Copyright (c) 2011 Helmut Merz helmutm@cy55.de
# 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
@ -19,8 +19,6 @@
"""
Definition of view classes and other browser related stuff for the
loops.knowledge package.
$Id$
"""
from zope import interface, component
@ -32,11 +30,17 @@ from cybertools.typology.interfaces import IType
from loops.browser.action import DialogAction
from loops.browser.common import BaseView
from loops.browser.concept import ConceptView
from loops.expert.browser.report import ResultsConceptView
from loops.knowledge.interfaces import IPerson, ITask
from loops.organize.work.browser import CreateWorkItemForm, CreateWorkItem
from loops.organize.party import getPersonForUser
from loops.util import _
template = ViewPageTemplateFile('knowledge_macros.pt')
knowledge_macros = template.macros
actions.register('createTopic', 'portlet', DialogAction,
title=_(u'Create Topic...'),
description=_(u'Create a new topic.'),
@ -54,10 +58,19 @@ actions.register('editTopic', 'portlet', DialogAction,
dialogName='editTopic',
)
actions.register('createQualification', 'portlet', DialogAction,
title=_(u'Create Qualification Record...'),
description=_(u'Create a work item for this person.'),
viewName='create_qualification.html',
dialogName='createQualification',
prerequisites=['registerDojoDateWidget', 'registerDojoNumberWidget',
'registerDojoTextarea'],
)
class MyKnowledge(ConceptView):
template = ViewPageTemplateFile('knowledge_macros.pt')
template = template
@Lazy
def macro(self):
@ -90,9 +103,30 @@ class MyKnowledge(ConceptView):
class Candidates(ConceptView):
template = ViewPageTemplateFile('knowledge_macros.pt')
template = template
@Lazy
def macro(self):
return self.template.macros['requirement_candidates']
# qualification stuff
class PersonQualificationView(ResultsConceptView):
pass
class CreateQualificationRecordForm(CreateWorkItemForm):
macros = knowledge_macros
@Lazy
def macro(self):
return self.macros['create_qualification']
class CreateQualificationRecord(CreateWorkItem):
pass

View file

@ -66,6 +66,22 @@
interface="cybertools.knowledge.interfaces.IKnowledgeProvider" />
</zope:class>
<!-- records -->
<zope:class class="loops.knowledge.qualification.QualificationRecord">
<require permission="zope.View"
interface="loops.knowledge.interfaces.IQualificationRecord" />
<require permission="zope.ManageContent"
set_schema="loops.knowledge.interfaces.IQualificationRecord" />
</zope:class>
<zope:adapter factory="loops.knowledge.qualification.QualificationRecords"
provides="loops.knowledge.interfaces.IQualificationRecords" />
<zope:utility factory="loops.knowledge.qualification.qualificationStates"
provides="cybertools.stateful.interfaces.IStatesDefinition"
name="knowledge.qualification" />
<!-- views -->
<zope:adapter
@ -88,9 +104,6 @@
<zope:adapter factory="loops.knowledge.schema.PersonSchemaFactory" />
<zope:adapter factory="loops.knowledge.setup.SetupManager"
name="knowledge" />
<!-- sub-packages -->
<include package=".glossary" />

View file

@ -0,0 +1,44 @@
type(u'competence', u'Competence', viewName=u'',
typeInterface=u'', options=u'action.portlet:edit_concept')
type(u'person', u'Person', viewName=u'',
typeInterface=u'loops.knowledge.interfaces.IPerson',
options=u'action.portlet:editPerson')
type(u'task', u'Aufgabe', viewName=u'',
typeInterface=u'loops.knowledge.interfaces.ITask',
options=u'action.portlet:createTopic,editTopic')
type(u'topic', u'Thema', viewName=u'',
typeInterface=u'loops.knowledge.interfaces.ITopic',
options=u'action.portlet:createTopic,editTopic')
type(u'training', u'Schulung', viewName=u'',
typeInterface=u'loops.organize.interfaces.ITask',
options=u'action.portlet:create_subtype,edit_concept')
concept(u'general', u'Allgemein', u'domain')
concept(u'system', u'System', u'domain')
# predicates
concept(u'depends', u'depends', u'predicate')
concept(u'knows', u'knows', u'predicate')
concept(u'provides', u'provides', u'predicate')
concept(u'requires', u'requires', u'predicate')
concept(u'issubtype', u'is Subtype', u'predicate', options=u'hide_children',
predicateInterface='loops.interfaces.IIsSubtype')
# structure
child(u'competence', u'general', u'standard')
child(u'depends', u'general', u'standard')
child(u'knows', u'general', u'standard')
child(u'person', u'general', u'standard')
child(u'provides', u'general', u'standard')
child(u'requires', u'general', u'standard')
child(u'task', u'general', u'standard')
child(u'topic', u'general', u'standard')
child(u'training', u'general', u'standard')
child(u'issubtype', u'system', u'standard')
child(u'training', u'competence', u'issubtype', usePredicate=u'provides')
# records
records(u'qualification', u'loops.knowledge.qualification.QualificationRecord')

View file

@ -1,5 +1,5 @@
#
# Copyright (c) 2011 Helmut Merz helmutm@cy55.de
# 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
@ -18,8 +18,6 @@
"""
Interfaces for knowledge management and elearning with loops.
$Id$
"""
from zope.interface import Interface, Attribute
@ -29,6 +27,7 @@ from zope.security.proxy import removeSecurityProxy
from cybertools.knowledge.interfaces import IKnowing, IRequirementProfile
from cybertools.knowledge.interfaces import IKnowledgeElement
from cybertools.organize.interfaces import IWorkItem, IWorkItems
from loops.interfaces import IConceptSchema, ILoopsAdapter
from loops.organize.interfaces import IPerson as IBasePerson
from loops.organize.interfaces import ITask as IBaseTask
@ -63,3 +62,13 @@ class ITopic(IConceptSchema, IKnowledgeElement, ILoopsAdapter):
""" Just a topic, some general classification concept.
"""
class IQualificationRecord(IWorkItem):
""" Records needs for qualification (acqusition of competence)
and corresponding participations in training events etc.
"""
class IQualificationRecords(IWorkItems):
""" Container for qualification records.
"""

View file

@ -1,5 +1,5 @@
#
# Copyright (c) 2007 Helmut Merz helmutm@cy55.de
# 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
@ -19,8 +19,6 @@
"""
Adapters for IConcept providing interfaces from the
cybertools.knowledge package.
$Id$
"""
from zope import interface, component

View file

@ -57,4 +57,19 @@
</metal:candidates>
<!-- forms -->
<metal:block define-macro="create_qualification">
<form method="post" id="addQualification_form" class="dialog"
dojoType="dijit.form.Form">
<div class="buttons">
<input value="Save" type="submit"
i18n:attributes="value">
<input type="button" value="Cancel"
onClick="return closeDialog(false)"
i18n:attributes="value"></div>
</form>
</metal:block>
</html>

View file

@ -0,0 +1,96 @@
#
# 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
#
"""
Controlling qualification activities of persons.
Central part of CCM competence and certification management framework.
"""
from zope.component import adapts
from zope.interface import implementer, implements
from cybertools.stateful.base import Stateful
from cybertools.stateful.definition import StatesDefinition
from cybertools.stateful.definition import State, Transition
from cybertools.stateful.interfaces import IStatesDefinition
from cybertools.tracking.interfaces import ITrackingStorage
from loops.knowledge.interfaces import IQualificationRecord, \
IQualificationRecords
from loops.organize.work.base import WorkItem, WorkItems
@implementer(IStatesDefinition)
def qualificationStates():
return StatesDefinition('qualification',
State('open', 'open',
('register', 'pass', 'fail', 'cancel', 'modify'),
color='red'),
State('registered', 'registered',
('register', 'pass', 'fail', 'unregister', 'cancel', 'modify'),
color='yellow'),
State('passed', 'passed',
('cancel', 'close', 'modify', 'open', 'expire'),
color='green'),
State('failed', 'failed',
('register', 'cancel', 'modify', 'open'),
color='green'),
State('expired', 'expired',
('register', 'cancel', 'modify', 'open'),
color='red'),
State('cancelled', 'cancelled', ('modify', 'open'),
color='grey'),
State('closed', 'closed', ('modify', 'open'),
color='lightblue'),
# not directly reachable states:
State('open_x', 'open', ('modify',), color='red'),
State('registered_x', 'registered', ('modify',), color='yellow'),
# transitions:
Transition('register', 'register', 'registered'),
Transition('pass', 'pass', 'passed'),
Transition('fail', 'fail', 'failed'),
Transition('unregister', 'unregister', 'open'),
Transition('cancel', 'cancel', 'cancelled'),
Transition('close', 'close', 'closed'),
Transition('open', 'open', 'open'),
initialState='open')
class QualificationRecord(WorkItem):
implements(IQualificationRecord)
typeName = 'QualificationRecord'
typeInterface = IQualificationRecord
statesDefinition = 'knowledge.qualification'
def doAction(self, action, userName, **kw):
new = self.createNew(action, userName, **kw)
new.userName = self.userName
new.doTransition(action)
new.reindex()
return new
class QualificationRecords(WorkItems):
""" A tracking storage adapter managing qualification records.
"""
implements(IQualificationRecords)
adapts(ITrackingStorage)

View file

@ -1,61 +0,0 @@
#
# 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
#
"""
Automatic setup of a loops site for the organize package.
$Id$
"""
from zope.component import adapts
from zope.interface import implements, Interface
from cybertools.knowledge.interfaces import IKnowledgeElement
from loops.concept import Concept
from loops.interfaces import ITypeConcept
from loops.knowledge.interfaces import IPerson, ITask, ITopic
from loops.setup import SetupManager as BaseSetupManager
class SetupManager(BaseSetupManager):
def setup(self):
concepts = self.context.getConceptManager()
type = concepts.getTypeConcept()
predicate = concepts['predicate']
# type concepts:
person = self.addObject(concepts, Concept, 'person', title=u'Person',
conceptType=type)
ITypeConcept(person).typeInterface = IPerson # this may override other packages!
topic = self.addObject(concepts, Concept, 'topic', title=u'Topic',
conceptType=type)
ITypeConcept(topic).typeInterface = ITopic
task = self.addObject(concepts, Concept, 'task', title=u'Task',
conceptType=type)
ITypeConcept(task).typeInterface = ITask
# predicates:
depends = self.addObject(concepts, Concept, 'depends', title=u'depends',
conceptType=predicate)
knows = self.addObject(concepts, Concept, 'knows', title=u'knows',
conceptType=predicate)
requires = self.addObject(concepts, Concept, 'requires', title=u'requires',
conceptType=predicate)
provides = self.addObject(concepts, Concept, 'provides', title=u'provides',
conceptType=predicate)

View file

@ -1,10 +1,18 @@
# $Id$
# tests.py - loops.knowledge package
import os
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
from loops.setup import importData as baseImportData
def importData(loopsRoot):
importPath = os.path.join(os.path.dirname(__file__), 'data')
baseImportData(loopsRoot, importPath, 'loops_knowledge_de.dmp')
class Test(unittest.TestCase):
"Basic tests for the knowledge sub-package."

View file

@ -260,7 +260,7 @@ Automatic security settings on persons
>>> from zope.traversing.api import getName
>>> list(sorted(getName(c) for c in concepts['person'].getChildren()))
[u'jim', u'john', u'martha', u'person.newuser']
[u'general', u'jim', u'john', u'martha', u'person.newuser']
Person objects that have a user assigned to them receive this user
(principal) as their owner.
@ -358,7 +358,7 @@ Task view with edit action
>>> from loops.organize.browser.task import TaskView
>>> view = TaskView(task01, TestRequest())
>>> list(view.getActions('portlet'))
[]
[...]
OK, the action is not provided automatically any more by the TaskView
but has to be entered as a type option.
@ -404,7 +404,7 @@ Send Email to Members
>>> form.subject
u"loops Notification from '$site'"
>>> form.mailBody
u'\n\nEvent #1\nhttp://127.0.0.1/loops/views/menu/.97\n\n'
u'\n\nEvent #1\nhttp://127.0.0.1/loops/views/menu/.116\n\n'
Show Presence of Other Users

View file

@ -18,7 +18,7 @@ Let's set up a loops site with basic and example concepts and resources.
>>> concepts, resources, views = t.setup()
>>> loopsRoot = site['loops']
>>> len(concepts), len(resources), len(views)
(30, 3, 1)
(34, 3, 1)
>>> from cybertools.tracking.btree import TrackingStorage
>>> from loops.system.job import JobRecord

View file

@ -26,14 +26,12 @@ configuration):
>>> t = TestSite(site)
>>> concepts, resources, views = t.setup()
>>> #sorted(concepts)
>>> #sorted(resources)
>>> len(concepts) + len(resources)
23
>>> loopsRoot = site['loops']
>>> loopsRoot.options = ['useVersioning']
>>> len(concepts) + len(resources)
16
Version Information
===================

View file

@ -33,7 +33,7 @@ from loops.config.base import LoopsOptions
from loops.interfaces import ILoopsObject, IConcept
from loops.resource import Resource
from loops.resource import IndexAttributes as ResourceIndexAttributes
from loops.knowledge.setup import SetupManager as KnowledgeSetupManager
#from loops.knowledge.setup import SetupManager as KnowledgeSetupManager
from loops.setup import SetupManager, addObject
from loops.type import ConceptType, ResourceType, TypeConcept
from loops.versioning.versionable import cleanupVersions
@ -74,7 +74,7 @@ class TestSite(object):
loopsRoot = site['loops'] = Loops()
component.provideAdapter(KnowledgeSetupManager, name='knowledge')
#component.provideAdapter(KnowledgeSetupManager, name='knowledge')
setup = SetupManager(loopsRoot)
concepts, resources, views = setup.setup()

View file

@ -21,8 +21,6 @@ ZCML setup):
>>> from loops.setup import addObject
>>> from loops.organize.setup import SetupManager as OrganizeSetupManager
>>> component.provideAdapter(OrganizeSetupManager, name='organize')
>>> from loops.knowledge.setup import SetupManager as KnowledgeSetupManager
>>> component.provideAdapter(KnowledgeSetupManager, name='knowledge')
>>> from loops.tests.setup import TestSite
>>> t = TestSite(site)
>>> concepts, resources, views = t.setup()
@ -31,10 +29,13 @@ ZCML setup):
>>> 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)
18
23
Now let's add a few more concepts:
@ -71,10 +72,11 @@ 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'customer', u'domain', u'file', u'note', u'person', u'predicate',
u'task', u'textdocument', u'topic', u'type']
[u'competence', u'customer', u'domain', u'file', u'note', u'person',
u'predicate', u'task', u'textdocument', u'topic', u'training', u'type']
>>> sorted(t['name'] for t in xrf.getPredicates())
[u'depends', u'knows', u'ownedby', u'provides', u'requires', u'standard']
[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:
@ -93,8 +95,8 @@ 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'customer', u'domain', u'file', u'note', u'person', u'predicate',
u'task', u'textdocument', u'topic', u'type']
[u'competence', u'customer', u'domain', u'file', u'note', u'person',
u'predicate', u'task', u'textdocument', u'topic', u'training', u'type']
>>> pa = defaultPred['parents']
>>> len(pa)
@ -112,8 +114,8 @@ We can also retrieve children and parents explicitely:
>>> ch[0]['name']
u'hasType'
>>> sorted(c['name'] for c in ch[0]['objects'])
[u'customer', u'domain', u'file', u'note', u'person', u'predicate',
u'task', u'textdocument', u'topic', u'type']
[u'competence', u'customer', u'domain', u'file', u'note', u'person',
u'predicate', u'task', u'textdocument', u'topic', u'training', u'type']
>>> pa = xrf.getParents('6')
>>> len(pa)
@ -172,14 +174,14 @@ Updating the concept map
>>> topicId = xrf.getObjectByName('topic')['id']
>>> xrf.createConcept(topicId, u'zope2', u'Zope 2')
{'description': u'', 'title': u'Zope 2', 'type': '22', 'id': '54',
{'description': u'', 'title': u'Zope 2', 'type': '36', 'id': '75',
'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': '22', 'id': '56',
{'description': u'', 'title': u'Python', 'type': '36', 'id': '77',
'name': u'python'}
If we try to deassign a ``hasType`` relation nothing will happen; a