Python3 fixes for expert tests (+dependencies)

This commit is contained in:
Helmut Merz 2024-09-25 10:58:27 +02:00
parent ce7015b224
commit 509000a996
19 changed files with 108 additions and 307 deletions

View file

@ -5,8 +5,6 @@ loops - Linked Objects for Organization and Processing Services
The loops expert - knows what is in a loops site and how to make The loops expert - knows what is in a loops site and how to make
use of it. use of it.
($Id$)
Setting up a loops Site and Utilities Setting up a loops Site and Utilities
===================================== =====================================
@ -88,7 +86,7 @@ corresponding adapter and activate it for the current loops site.
We have now to reindex all documents so that the state index gets populated We have now to reindex all documents so that the state index gets populated
according to the new settings. according to the new settings.
>>> from zope.app.catalog.interfaces import ICatalog >>> from zope.catalog.interfaces import ICatalog
>>> catalog = component.getUtility(ICatalog) >>> catalog = component.getUtility(ICatalog)
>>> from loops import util >>> from loops import util
>>> for r in resources.values(): >>> for r in resources.values():
@ -152,7 +150,7 @@ filtering the results; this defaults to ``canListObjects``.
>>> from loops.expert.query import getObjects >>> from loops.expert.query import getObjects
>>> objs = getObjects(query.Title('ty*').apply(), root=loopsRoot) >>> objs = getObjects(query.Title('ty*').apply(), root=loopsRoot)
>>> sorted(o.title for o in objs) >>> sorted(o.title for o in objs)
[u'Document Type', u'Type', u'has Type'] ['Document Type', 'Type', 'has Type']
Filters Filters
@ -180,19 +178,19 @@ concepts) that are direct or indirect children of jim.
>>> qu = query.Type('loops:resource:textdocument') >>> qu = query.Type('loops:resource:textdocument')
>>> objs = getObjects(qu.apply()) >>> objs = getObjects(qu.apply())
>>> sorted(o.title for o in objs) >>> sorted(o.title for o in objs)
[u'Doc 001', u'Doc 002', u'Doc 003'] ['Doc 001', 'Doc 002', 'Doc 003']
>>> from loops.expert import filter >>> from loops.expert import filter
>>> fltr = filter.Children(jim, recursive=True, includeResources=True) >>> fltr = filter.Children(jim, recursive=True, includeResources=True)
>>> sorted(o.title for o in getObjects((qu & fltr.query()).apply())) >>> sorted(o.title for o in getObjects((qu & fltr.query()).apply()))
[u'Doc 001', u'Doc 003'] ['Doc 001', 'Doc 003']
>>> #fltr.check(resources['d001.txt']) >>> #fltr.check(resources['d001.txt'])
>>> #fltr.check(resources['d002.txt']) >>> #fltr.check(resources['d002.txt'])
>>> r1 = qu.apply() >>> r1 = qu.apply()
>>> r2 = fltr.apply(dict(zip(r1, getObjects(r1)))) >>> r2 = fltr.apply(dict(zip(r1, getObjects(r1))))
>>> sorted(o.title for o in r2.values()) >>> sorted(o.title for o in r2.values())
[u'Doc 001', u'Doc 003'] ['Doc 001', 'Doc 003']
Organizing Queries and Filters with Query Instances Organizing Queries and Filters with Query Instances
@ -235,7 +233,7 @@ Reports
>>> from loops.expert.report import ReportTypeSourceList >>> from loops.expert.report import ReportTypeSourceList
>>> source = ReportTypeSourceList(report) >>> source = ReportTypeSourceList(report)
>>> list(source) >>> list(source)
[(u'default_concept_report', u'Default Concept Report')] [('default_concept_report', 'Default Concept Report')]
Fin de partie Fin de partie

View file

@ -117,7 +117,7 @@ class FullQuery(BaseQuery):
return ScoredSet(result, scores) return ScoredSet(result, scores)
if text or type != 'loops:*': # TODO: this may be highly inefficient! if text or type != 'loops:*': # TODO: this may be highly inefficient!
cat = self.catalog cat = self.catalog
if isinstance(type, basestring): if isinstance(type, str):
type = [type] type = [type]
for tp in type: for tp in type:
if tp.endswith('*'): if tp.endswith('*'):

View file

@ -1,29 +1,10 @@
# # loops.expert.filter
# Copyright (c) 2008 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
#
""" """ Filter query results.
Filter query results.
$Id$
""" """
from BTrees.IOBTree import IOBTree from BTrees.IOBTree import IOBTree
from zope.interface import implements from zope.interface import implementer
from cybertools.catalog.query import And from cybertools.catalog.query import And
from loops.expert.interfaces import IFilter from loops.expert.interfaces import IFilter
@ -31,10 +12,9 @@ from loops.expert.query import Children as ChildrenQuery
from loops import util from loops import util
@implementer(IFilter)
class Filter(object): class Filter(object):
implements(IFilter)
query = None query = None
def __init__(self, **kw): def __init__(self, **kw):
@ -54,10 +34,9 @@ class Filter(object):
return uid in self.query().apply() #.keys() return uid in self.query().apply() #.keys()
@implementer(IFilter)
class Children(Filter): class Children(Filter):
implements(IFilter)
def __init__(self, parent, **kw): def __init__(self, parent, **kw):
self.parent = parent self.parent = parent
super(Children, self).__init__(**kw) super(Children, self).__init__(**kw)

View file

@ -1,36 +1,16 @@
# # loops.expert.instance
# Copyright (c) 2008 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
#
""" """ Filter query results.
Filter query results.
$Id$
""" """
from zope.interface import implements from zope.interface import implementer
from loops.expert.interfaces import IQueryInstance from loops.expert.interfaces import IQueryInstance
@implementer(IQueryInstance)
class QueryInstance(object): class QueryInstance(object):
implements(IQueryInstance)
def __init__(self, query, *filters, **kw): def __init__(self, query, *filters, **kw):
self.query = query self.query = query
self.filters = filters self.filters = filters

View file

@ -1,28 +1,11 @@
# # loops.expert.report
# Copyright (c) 2017 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
#
""" """ Report type, report concept adapter, and other reporting stuff.
Report type, report concept adapter, and other reporting stuff.
""" """
from zope import schema, component from zope import schema, component
from zope.component import adapts from zope.component import adapts
from zope.interface import Interface, Attribute, implements from zope.interface import Interface, Attribute, implementer
from zope.cachedescriptors.property import Lazy from zope.cachedescriptors.property import Lazy
from zope.security.proxy import removeSecurityProxy from zope.security.proxy import removeSecurityProxy
from zope.traversing.api import getName from zope.traversing.api import getName
@ -67,10 +50,9 @@ class IReportInstance(IBaseReport):
# report concept adapter and instances # report concept adapter and instances
@implementer(IReport)
class Report(QueryConcept): class Report(QueryConcept):
implements(IReport)
_contextAttributes = list(IReport) _contextAttributes = list(IReport)
@Lazy @Lazy
@ -80,9 +62,9 @@ class Report(QueryConcept):
TypeInterfaceSourceList.typeInterfaces += (IReport,) TypeInterfaceSourceList.typeInterfaces += (IReport,)
@implementer(IReportInstance)
class ReportInstance(BaseReport): class ReportInstance(BaseReport):
implements(IReportInstance)
adapts(IReport) adapts(IReport)
rowFactory = Row rowFactory = Row
@ -144,10 +126,9 @@ class ReportInstance(BaseReport):
return self.conceptManager['hasreport'] return self.conceptManager['hasreport']
@implementer(schema.interfaces.IIterableSource)
class ReportTypeSourceList(object): class ReportTypeSourceList(object):
implements(schema.interfaces.IIterableSource)
def __init__(self, context): def __init__(self, context):
self.context = context self.context = context

View file

@ -2,8 +2,6 @@
loops.search - Provide search functionality for the loops framework loops.search - Provide search functionality for the loops framework
=================================================================== ===================================================================
($Id$)
Let's do some basic set up Let's do some basic set up
@ -11,7 +9,6 @@ Let's do some basic set up
>>> site = placefulSetUp(True) >>> site = placefulSetUp(True)
>>> from zope import component, interface >>> from zope import component, interface
>>> from zope.interface import implements
and setup a simple loops site with a concept manager and some concepts 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 (with all the type machinery, what in real life is done via standard
@ -32,7 +29,7 @@ ZCML setup):
In addition we create a concept that holds the search page and a node In addition we create a concept that holds the search page and a node
(page) that links to this concept: (page) that links to this concept:
>>> search = concepts['search'] = Concept(u'Search') >>> search = concepts['search'] = Concept('Search')
>>> search.conceptType = query >>> search.conceptType = query
>>> from loops.view import Node >>> from loops.view import Node
@ -105,13 +102,13 @@ resource we can search for and index it in the catalog.
>>> from loops.resource import Resource >>> from loops.resource import Resource
>>> rplone = resources['plone'] = Resource() >>> rplone = resources['plone'] = Resource()
>>> from zope.app.catalog.interfaces import ICatalog >>> from zope.catalog.interfaces import ICatalog
>>> from loops import util >>> from loops import util
>>> catalog = component.getUtility(ICatalog) >>> catalog = component.getUtility(ICatalog)
>>> catalog.index_doc(int(util.getUidForObject(rplone)), rplone) >>> catalog.index_doc(int(util.getUidForObject(rplone)), rplone)
>>> from loops.expert.browser.search import SearchResults >>> from loops.expert.browser.search import SearchResults
>>> form = {'search.2.title': True, 'search.2.text': u'plone'} >>> form = {'search.2.title': True, 'search.2.text': 'plone'}
>>> request = TestRequest(form=form) >>> request = TestRequest(form=form)
>>> resultsView = SearchResults(page, request) >>> resultsView = SearchResults(page, request)
@ -121,7 +118,7 @@ resource we can search for and index it in the catalog.
>>> results[0].context == rplone >>> results[0].context == rplone
True True
>>> form = {'search.2.title': True, 'search.2.text': u'foo'} >>> form = {'search.2.title': True, 'search.2.text': 'foo'}
>>> request = TestRequest(form=form) >>> request = TestRequest(form=form)
>>> resultsView = SearchResults(page, request) >>> resultsView = SearchResults(page, request)
>>> len(list(resultsView.results)) >>> len(list(resultsView.results))
@ -133,10 +130,10 @@ Search via related concepts
We first have to prepare some test concepts (topics); we also assign our test We first have to prepare some test concepts (topics); we also assign our test
resource (rplone) from above to one of the topics: resource (rplone) from above to one of the topics:
>>> czope = concepts['zope'] = Concept(u'Zope') >>> czope = concepts['zope'] = Concept('Zope')
>>> czope2 = concepts['zope2'] = Concept(u'Zope 2') >>> czope2 = concepts['zope2'] = Concept('Zope 2')
>>> czope3 = concepts['zope3'] = Concept(u'Zope 3') >>> czope3 = concepts['zope3'] = Concept('Zope 3')
>>> cplone = concepts['plone'] = Concept(u'Plone') >>> cplone = concepts['plone'] = Concept('Plone')
>>> for c in (czope, czope2, czope3, cplone): >>> for c in (czope, czope2, czope3, cplone):
... c.conceptType = topic ... c.conceptType = topic
... catalog.index_doc(int(util.getUidForObject(c)), c) ... catalog.index_doc(int(util.getUidForObject(c)), c)
@ -157,7 +154,7 @@ with them:
>>> len(results) >>> len(results)
5 5
>>> results[0].context.__name__ >>> results[0].context.__name__
u'plone' 'plone'
>>> uid = util.getUidForObject(concepts['zope3']) >>> uid = util.getUidForObject(concepts['zope3'])
>>> form = {'search.3.type': 'loops:concept:topic', 'search.3.text': uid} >>> form = {'search.3.type': 'loops:concept:topic', 'search.3.text': uid}
@ -167,17 +164,19 @@ with them:
>>> len(results) >>> len(results)
1 1
>>> results[0].context.__name__ >>> results[0].context.__name__
u'zope3' 'zope3'
To support easy entry of concepts to search for we can preselect the available To support easy entry of concepts to search for we can preselect the available
concepts (optionally restricted to a certain type) by entering text parts concepts (optionally restricted to a certain type) by entering text parts
of the concepts' titles: of the concepts' titles:
>>> form = {'searchType': 'loops:concept:topic', 'name': u'zope'} >>> form = {'searchType': 'loops:concept:topic', 'name': 'zope'}
>>> request = TestRequest(form=form) >>> request = TestRequest(form=form)
>>> view = Search(page, request) >>> view = Search(page, request)
>>> view.listConcepts() >>> view.listConcepts()
'{"items": [{"id": "...", "name": "Zope", "label": "Zope (Thema)"}, {"id": "...", "name": "Zope 2", "label": "Zope 2 (Thema)"}, {"id": "...", "name": "Zope 3", "label": "Zope 3 (Thema)"}], "identifier": "id"}' '{"identifier": "id", "items": [{...}]}'
'{"items": [{"id": "...", "name": "Zope", "label": "Zope (Thema)"}, {"id": "...", "name": "Zope 2", "label": "Zope 2 (Thema)"}, {"id": "...", "name": "Zope 3", "label": "Zope 3 (Thema)"}], "identifier": "id"}'
Preset Concept Types on Search Forms Preset Concept Types on Search Forms
------------------------------------ ------------------------------------
@ -215,21 +214,23 @@ and thus include the customer type in the preset search types.
('concept', 'search') ('concept', 'search')
>>> searchView = Search(search, TestRequest()) >>> searchView = Search(search, TestRequest())
>>> list(searchView.presetSearchTypes) >>> list(searchView.presetSearchTypes)
[{'token': 'loops:concept:customer', 'title': u'Customer'}] [{'token': 'loops:concept:customer', 'title': 'Customer'}]
>>> searchView.conceptsForType('loops:concept:customer') >>> searchView.conceptsForType('loops:concept:customer')
[{'token': 'none', 'title': u'not selected'}, [{'token': 'none', 'title': 'not selected'},
{'token': '...', 'title': u'Customer 1'}, {...}, {...}, {...}]
{'token': '...', 'title': u'Customer 2'},
{'token': '...', 'title': u'Customer 3'}] {'token': '...', 'title': 'Customer 1'},
{'token': '...', 'title': 'Customer 2'},
{'token': '...', 'title': 'Customer 3'}]
Let's use this new search option for querying: Let's use this new search option for querying:
>>> form = {'search.4.text_selected': u'75'} >>> form = {'search.4.text_selected': '75'}
>>> resultsView = SearchResults(page, TestRequest(form=form)) >>> resultsView = SearchResults(page, TestRequest(form=form))
>>> results = list(resultsView.results) >>> results = list(resultsView.results)
>>> results[0].title >>> results[0].title
u'Customer 1' 'Customer 1'
Automatic Filtering Automatic Filtering

View file

@ -5,7 +5,7 @@ try:
from loops.expert import query from loops.expert import query
ignore = False ignore = False
except ImportError: except ImportError:
print 'Skipping loops.expert' print('Skipping loops.expert')
ignore = True ignore = True
class Test(unittest.TestCase): class Test(unittest.TestCase):

View file

@ -1,11 +1,10 @@
""" # loops.expert.testsetup
Set up a loops site for testing.
$Id$ """ Set up a loops site for testing.
""" """
from zope import component from zope import component
from zope.app.catalog.interfaces import ICatalog from zope.catalog.interfaces import ICatalog
from cybertools.typology.interfaces import IType from cybertools.typology.interfaces import IType
from loops import util from loops import util

View file

@ -1,32 +1,13 @@
# # loops.external.annotation
# Copyright (c) 2008 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
#
""" """ Export/import of annotations.
Export/import of annotations.
$Id$
""" """
from datetime import datetime from datetime import datetime
import time import time
from zope.component import adapts from zope.component import adapts
from zope.dublincore.interfaces import IZopeDublinCore from zope.dublincore.interfaces import IZopeDublinCore
from zope.interface import implements from zope.interface import implementer
from loops.external.element import Element, elementTypes from loops.external.element import Element, elementTypes
from loops.external.interfaces import ISubExtractor from loops.external.interfaces import ISubExtractor
@ -51,9 +32,9 @@ class AnnotationsElement(Element):
setattr(dc, k, v) setattr(dc, k, v)
@implementer(ISubExtractor)
class AnnotationsExtractor(object): class AnnotationsExtractor(object):
implements(ISubExtractor)
adapts(ILoopsObject) adapts(ILoopsObject)
dcAttributes = ('title', 'description', 'creators', 'created', 'modified') dcAttributes = ('title', 'description', 'creators', 'created', 'modified')

View file

@ -1,35 +1,16 @@
# # loops.external.base
# Copyright (c) 2010 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
#
""" """ Reading and writing loops objects (represented by IElement objects)
Reading and writing loops objects (represented by IElement objects)
in Python function notation. in Python function notation.
$Id$
""" """
from cStringIO import StringIO from io import StringIO
import itertools import itertools
import os, sys import os, sys
import zdaemon import zdaemon
from zope import component from zope import component
from zope.cachedescriptors.property import Lazy from zope.cachedescriptors.property import Lazy
from zope.interface import implements from zope.interface import implementer
from zope.traversing.api import getName, getParent from zope.traversing.api import getName, getParent
from cybertools.composer.interfaces import IInstance from cybertools.composer.interfaces import IInstance
@ -73,10 +54,9 @@ class Base(object):
return self.concepts.getTypePredicate() return self.concepts.getTypePredicate()
@implementer(ILoader)
class Loader(Base, BaseLoader, SetupManager): class Loader(Base, BaseLoader, SetupManager):
implements(ILoader)
def __init__(self, context, resourceDirectory=None): def __init__(self, context, resourceDirectory=None):
#super(Loader, self).__init__(context, resourceDirectory) #super(Loader, self).__init__(context, resourceDirectory)
Base.__init__(self, context, resourceDirectory) Base.__init__(self, context, resourceDirectory)
@ -89,10 +69,9 @@ class Loader(Base, BaseLoader, SetupManager):
# def addConcept(self, ...): # def addConcept(self, ...):
@implementer(IExtractor)
class Extractor(Base): class Extractor(Base):
implements(IExtractor)
count = 0 count = 0
def extract(self): def extract(self):

View file

@ -99,7 +99,7 @@ class TypeElement(ConceptElement):
super(TypeElement, self).__init__(name, title, *args, **kw) super(TypeElement, self).__init__(name, title, *args, **kw)
ti = self.get('typeInterface') ti = self.get('typeInterface')
if ti: if ti:
if not isinstance(ti, basestring): if not isinstance(ti, str):
self['typeInterface'] = '.'.join((ti.__module__, ti.__name__)) self['typeInterface'] = '.'.join((ti.__module__, ti.__name__))
def execute(self, loader): def execute(self, loader):
@ -125,7 +125,7 @@ class RecordManagerElement(Element):
def __init__(self, name, trackFactory, **kw): def __init__(self, name, trackFactory, **kw):
self['name'] = name self['name'] = name
tf = self['trackFactory'] = trackFactory tf = self['trackFactory'] = trackFactory
if not isinstance(tf, basestring): if not isinstance(tf, str):
self['trackFactory'] = '.'.join((tf.__module__, tf.__name__)) self['trackFactory'] = '.'.join((tf.__module__, tf.__name__))
for k, v in kw.items(): for k, v in kw.items():
self[k] = v self[k] = v

View file

@ -1,50 +1,30 @@
# # loops.external.pyfunc
# Copyright (c) 2008 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
#
""" """ Reading and writing loops objects (represented by IElement objects)
Reading and writing loops objects (represented by IElement objects)
in Python function notation. in Python function notation.
$Id$
""" """
from zope.cachedescriptors.property import Lazy from zope.cachedescriptors.property import Lazy
from zope.interface import implements from zope.interface import implementer
from loops.external.interfaces import IReader, IWriter from loops.external.interfaces import IReader, IWriter
from loops.external.element import elementTypes, toplevelElements from loops.external.element import elementTypes, toplevelElements
@implementer(IReader)
class PyReader(object): class PyReader(object):
implements(IReader)
def read(self, input): def read(self, input):
if not isinstance(input, str): if not isinstance(input, str):
input = input.read() input = input.read()
proc = InputProcessor() proc = InputProcessor()
exec input in proc exec(input, proc)
return proc.elements return proc.elements
class InputProcessor(dict): class InputProcessor(dict):
_constants = dict(True=True, False=False) _constants = {'True': True, 'False': False}
def __init__(self): def __init__(self):
self.elements = [] self.elements = []
@ -61,10 +41,9 @@ class InputProcessor(dict):
return factory return factory
@implementer(IWriter)
class PyWriter(object): class PyWriter(object):
implements(IWriter)
def write(self, elements, output, level=0): def write(self, elements, output, level=0):
for idx, element in enumerate(elements): for idx, element in enumerate(elements):
args = [] args = []

View file

@ -1,29 +1,12 @@
# # loops.knowledge.knowledge
# 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
#
""" """ Adapters for IConcept providing interfaces from the
Adapters for IConcept providing interfaces from the
cybertools.knowledge package. cybertools.knowledge package.
""" """
from zope import interface, component from zope import interface, component
from zope.component import adapts from zope.component import adapts
from zope.interface import implements from zope.interface import implementer
from zope.cachedescriptors.property import Lazy from zope.cachedescriptors.property import Lazy
from cybertools.typology.interfaces import IType from cybertools.typology.interfaces import IType
@ -75,6 +58,7 @@ class KnowledgeAdapterMixin(object):
return self.context == other.context return self.context == other.context
@implementer(IPerson)
class Person(BasePerson, Knowing, KnowledgeAdapterMixin): class Person(BasePerson, Knowing, KnowledgeAdapterMixin):
""" A typeInterface adapter for concepts of type 'person', including """ A typeInterface adapter for concepts of type 'person', including
knowledge/learning management features. knowledge/learning management features.
@ -85,8 +69,6 @@ class Person(BasePerson, Knowing, KnowledgeAdapterMixin):
knowledge = ParentRelationSetProperty('knows') knowledge = ParentRelationSetProperty('knows')
implements(IPerson)
def getKnowledge(self): def getKnowledge(self):
return (IKnowledgeElement(c) return (IKnowledgeElement(c)
for c in self.context.getParents((self.knowsPred,))) for c in self.context.getParents((self.knowsPred,)))
@ -98,12 +80,12 @@ class Person(BasePerson, Knowing, KnowledgeAdapterMixin):
self.context.deassignParent(obj.context, (self.knowsPred,)) self.context.deassignParent(obj.context, (self.knowsPred,))
@implementer(ITopic)
class Topic(I18NAdapterBase, KnowledgeAdapterMixin): class Topic(I18NAdapterBase, KnowledgeAdapterMixin):
""" A typeInterface adapter for concepts of type 'topic' that """ A typeInterface adapter for concepts of type 'topic' that
may act as a knowledge element. may act as a knowledge element.
""" """
implements(ITopic)
_adapterAttributes = I18NAdapterBase._adapterAttributes + ('parent',) _adapterAttributes = I18NAdapterBase._adapterAttributes + ('parent',)
def getParent(self): def getParent(self):
@ -140,13 +122,12 @@ class Topic(I18NAdapterBase, KnowledgeAdapterMixin):
+ self.context.getResources((self.providesPred,))) + self.context.getResources((self.providesPred,)))
@implementer(ITask)
class Task(BaseTask, KnowledgeAdapterMixin): class Task(BaseTask, KnowledgeAdapterMixin):
""" A typeInterface adapter for concepts of type 'task' that """ A typeInterface adapter for concepts of type 'task' that
may act as a knowledge requirement profile. may act as a knowledge requirement profile.
""" """
implements(ITask)
_adapterAttributes = BasePerson._adapterAttributes + ('requirements',) _adapterAttributes = BasePerson._adapterAttributes + ('requirements',)
_noexportAttributes = ('requirements',) _noexportAttributes = ('requirements',)
@ -183,10 +164,9 @@ class Task(BaseTask, KnowledgeAdapterMixin):
return sorted(result, key=lambda x: (-x['fit'], x['person'].title)) return sorted(result, key=lambda x: (-x['fit'], x['person'].title))
@implementer(IKnowledgeProvider)
class ConceptKnowledgeProvider(AdapterBase, KnowledgeAdapterMixin): class ConceptKnowledgeProvider(AdapterBase, KnowledgeAdapterMixin):
implements(IKnowledgeProvider)
def getProvidedKnowledge(self): def getProvidedKnowledge(self):
return (IKnowledgeElement(c) return (IKnowledgeElement(c)
for c in self.context.getParents((self.providesPred,))) for c in self.context.getParents((self.providesPred,)))
@ -198,9 +178,9 @@ class ConceptKnowledgeProvider(AdapterBase, KnowledgeAdapterMixin):
self.context.deassignParent(obj.context, (self.providesPred,)) self.context.deassignParent(obj.context, (self.providesPred,))
@implementer(IKnowledgeProvider)
class ResourceKnowledgeProvider(AdapterBase, KnowledgeAdapterMixin): class ResourceKnowledgeProvider(AdapterBase, KnowledgeAdapterMixin):
implements(IKnowledgeProvider)
adapts(IResource) adapts(IResource)
def getProvidedKnowledge(self): def getProvidedKnowledge(self):

View file

@ -1,17 +1,16 @@
'''package loops.knowledge.qualification''' '''package loops.knowledge.qualification'''
from zope.component import adapts from zope.component import adapts
from zope.interface import implementer, implements from zope.interface import implementer
from cybertools.tracking.interfaces import ITrackingStorage from cybertools.tracking.interfaces import ITrackingStorage
from loops.knowledge.qualification.interfaces import IQualificationRecord, \ from loops.knowledge.qualification.interfaces import IQualificationRecord, \
IQualificationRecords IQualificationRecords
from loops.organize.work.base import WorkItem, WorkItems from loops.organize.work.base import WorkItem, WorkItems
@implementer(IQualificationRecord)
class QualificationRecord(WorkItem): class QualificationRecord(WorkItem):
implements(IQualificationRecord)
typeName = 'QualificationRecord' typeName = 'QualificationRecord'
typeInterface = IQualificationRecord typeInterface = IQualificationRecord
statesDefinition = 'knowledge.qualification' statesDefinition = 'knowledge.qualification'
@ -24,9 +23,9 @@ class QualificationRecord(WorkItem):
return new return new
@implementer(IQualificationRecords)
class QualificationRecords(WorkItems): class QualificationRecords(WorkItems):
""" A tracking storage adapter managing qualification records.""" """ A tracking storage adapter managing qualification records."""
implements(IQualificationRecords)
adapts(ITrackingStorage) adapts(ITrackingStorage)

View file

@ -1,29 +1,12 @@
# # loops.knowledge.qualification.base
# Copyright (c) 2013 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.
Controlling qualification activities of persons.
Central part of CCM competence and certification management framework. Central part of CCM competence and certification management framework.
""" """
from zope.component import adapts from zope.component import adapts
from zope.interface import implementer, implements from zope.interface import implementer
from loops.common import AdapterBase from loops.common import AdapterBase
from loops.interfaces import IConcept from loops.interfaces import IConcept
@ -34,10 +17,9 @@ from loops.type import TypeInterfaceSourceList
TypeInterfaceSourceList.typeInterfaces += (ICompetence,) TypeInterfaceSourceList.typeInterfaces += (ICompetence,)
@implementer(ICompetence)
class Competence(AdapterBase): class Competence(AdapterBase):
implements(ICompetence)
_contextAttributes = list(ICompetence) _contextAttributes = list(ICompetence)

View file

@ -1,27 +1,10 @@
# # loops.knowledge.survey.base
# Copyright (c) 2016 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
#
""" """ Surveys used in knowledge management.
Surveys used in knowledge management.
""" """
from zope.component import adapts from zope.component import adapts
from zope.interface import implementer, implements from zope.interface import implementer
from cybertools.knowledge.survey.questionnaire import Questionnaire, \ from cybertools.knowledge.survey.questionnaire import Questionnaire, \
QuestionGroup, Question, FeedbackItem QuestionGroup, Question, FeedbackItem
@ -35,10 +18,9 @@ TypeInterfaceSourceList.typeInterfaces += (IQuestionnaire,
IQuestionGroup, IQuestion, IFeedbackItem) IQuestionGroup, IQuestion, IFeedbackItem)
@implementer(IQuestionnaire)
class Questionnaire(AdapterBase, Questionnaire): class Questionnaire(AdapterBase, Questionnaire):
implements(IQuestionnaire)
_contextAttributes = list(IQuestionnaire) _contextAttributes = list(IQuestionnaire)
_adapterAttributes = AdapterBase._adapterAttributes + ( _adapterAttributes = AdapterBase._adapterAttributes + (
'teamBasedEvaluation', 'teamBasedEvaluation',
@ -74,10 +56,9 @@ class Questionnaire(AdapterBase, Questionnaire):
yield qu yield qu
@implementer(IQuestionGroup)
class QuestionGroup(AdapterBase, QuestionGroup): class QuestionGroup(AdapterBase, QuestionGroup):
implements(IQuestionGroup)
_contextAttributes = list(IQuestionGroup) _contextAttributes = list(IQuestionGroup)
_adapterAttributes = AdapterBase._adapterAttributes + ( _adapterAttributes = AdapterBase._adapterAttributes + (
'questionnaire', 'questions', 'feedbackItems') 'questionnaire', 'questions', 'feedbackItems')
@ -109,10 +90,9 @@ class QuestionGroup(AdapterBase, QuestionGroup):
return [obj for obj in self.subobjects if IFeedbackItem.providedBy(obj)] return [obj for obj in self.subobjects if IFeedbackItem.providedBy(obj)]
@implementer(IQuestion)
class Question(AdapterBase, Question): class Question(AdapterBase, Question):
implements(IQuestion)
_contextAttributes = list(IQuestion) _contextAttributes = list(IQuestion)
_adapterAttributes = AdapterBase._adapterAttributes + ( _adapterAttributes = AdapterBase._adapterAttributes + (
'text', 'questionnaire', 'answerRange', 'feedbackItems',) 'text', 'questionnaire', 'answerRange', 'feedbackItems',)
@ -134,10 +114,9 @@ class Question(AdapterBase, Question):
return self.questionGroup.questionnaire return self.questionGroup.questionnaire
@implementer(IFeedbackItem)
class FeedbackItem(AdapterBase, FeedbackItem): class FeedbackItem(AdapterBase, FeedbackItem):
implements(IFeedbackItem)
_contextAttributes = list(IFeedbackItem) _contextAttributes = list(IFeedbackItem)
_adapterAttributes = AdapterBase._adapterAttributes + ( _adapterAttributes = AdapterBase._adapterAttributes + (
'text',) 'text',)

View file

@ -1,29 +1,12 @@
# # loops.organize.task
# 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
#
""" """ Adapters for IConcept providing interfaces from the
Adapters for IConcept providing interfaces from the
cybertools.organize package. cybertools.organize package.
""" """
from time import mktime from time import mktime
from zope.component import adapts from zope.component import adapts
from zope.interface import implements from zope.interface import implementer
from loops.organize.interfaces import ITask, IEvent, IAgendaItem from loops.organize.interfaces import ITask, IEvent, IAgendaItem
from loops.interfaces import IConcept from loops.interfaces import IConcept
@ -35,37 +18,34 @@ from loops.type import TypeInterfaceSourceList
TypeInterfaceSourceList.typeInterfaces += (ITask, IEvent, IAgendaItem) TypeInterfaceSourceList.typeInterfaces += (ITask, IEvent, IAgendaItem)
@implementer(ITask)
class Task(AdapterBase): class Task(AdapterBase):
""" typeInterface adapter for concepts of type 'task' or 'project'. """ typeInterface adapter for concepts of type 'task' or 'project'.
""" """
implements(ITask)
_adapterAttributes = AdapterBase._adapterAttributes _adapterAttributes = AdapterBase._adapterAttributes
_contextAttributes = list(ITask) _contextAttributes = list(ITask)
@implementer(IEvent)
class Event(Task): class Event(Task):
""" A scheduled event or appointment. """ A scheduled event or appointment.
""" """
implements(IEvent)
_contextAttributes = list(IEvent) _contextAttributes = list(IEvent)
@implementer(IAgendaItem)
class AgendaItem(AdapterBase): class AgendaItem(AdapterBase):
""" Some topic (a sort of task) that is discussed during an event. """ Some topic (a sort of task) that is discussed during an event.
""" """
implements(IAgendaItem)
_contextAttributes = list(IAgendaItem) _contextAttributes = list(IAgendaItem)
@implementer(IIndexAttributes)
class IndexAttributes(object): class IndexAttributes(object):
implements(IIndexAttributes)
adapts(ITask) adapts(ITask)
def __init__(self, context): def __init__(self, context):

View file

@ -227,14 +227,15 @@ class SetupManager(object):
def getPredicate(self, predicate): def getPredicate(self, predicate):
if predicate is None: if predicate is None:
return self.concepts.getDefaultPredicate() return self.concepts.getDefaultPredicate()
if isinstance(predicate, basestring): if isinstance(predicate, str):
return self.concepts[predicate] return self.concepts[predicate]
return predicate return predicate
def log(self, message): def log(self, message):
if isinstance(message, unicode): #if isinstance(message, str):
message = message.encode('UTF-8') # message = message.encode('UTF-8')
print >> self.logger, message #print >> self.logger, message
print(message, file=self.logger)
def addObject(self, container, class_, name, **kw): def addObject(self, container, class_, name, **kw):
return addObject(container, class_, name, **kw) return addObject(container, class_, name, **kw)

View file

@ -26,9 +26,12 @@ import cybertools
from cybertools.meta.interfaces import IOptions from cybertools.meta.interfaces import IOptions
from loops.browser.util import html_quote from loops.browser.util import html_quote
import config try: # for testing!
from loops.storage.compat.common import StorageFactory import config
storageFactory = StorageFactory(config) from loops.storage.compat.common import StorageFactory
storageFactory = StorageFactory(config)
except ImportError:
pass
_ = MessageFactory('loops') _ = MessageFactory('loops')