more Python3 fixes: compound, knowledge, versioning

This commit is contained in:
Helmut Merz 2024-09-27 09:37:54 +02:00
parent 010106406d
commit 1da71c72a9
12 changed files with 99 additions and 244 deletions

View file

@ -1,26 +1,9 @@
# # loops.browser.lobo.standard
# 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
#
""" """ View classes for lobo (blueprint-based) layouts.
View classes for lobo (blueprint-based) layouts.
""" """
from cgi import parse_qs from urllib.parse import parse_qs
from zope import interface, component from zope import interface, component
from zope.app.pagetemplate import ViewPageTemplateFile from zope.app.pagetemplate import ViewPageTemplateFile
from zope.cachedescriptors.property import Lazy from zope.cachedescriptors.property import Lazy

View file

@ -33,13 +33,13 @@ We first create the compound type and one instance of the newly created
type. We also need an ``ispartof`` predicate. type. We also need an ``ispartof`` predicate.
>>> tCompound = addAndConfigureObject(concepts, Concept, 'compound', >>> tCompound = addAndConfigureObject(concepts, Concept, 'compound',
... title=u'Compound', ... title='Compound',
... conceptType=tType, typeInterface=ICompound) ... conceptType=tType, typeInterface=ICompound)
>>> c01 = addAndConfigureObject(concepts, Concept, 'c01', >>> c01 = addAndConfigureObject(concepts, Concept, 'c01',
... title=u'Compound #01', conceptType=tCompound) ... title='Compound #01', conceptType=tCompound)
>>> tPredicate = concepts.getPredicateType() >>> tPredicate = concepts.getPredicateType()
>>> isPartof = addAndConfigureObject(concepts, Concept, 'ispartof', >>> isPartof = addAndConfigureObject(concepts, Concept, 'ispartof',
... title=u'is Part of', conceptType=tPredicate) ... title='is Part of', conceptType=tPredicate)
In order to access the compound concept's attributes we have to adapt In order to access the compound concept's attributes we have to adapt
it. it.
@ -49,31 +49,31 @@ it.
Now we are able to add resources to it. Now we are able to add resources to it.
>>> aC01.add(resources[u'd003.txt']) >>> aC01.add(resources['d003.txt'])
>>> aC01.add(resources[u'd001.txt']) >>> aC01.add(resources['d001.txt'])
>>> [getName(p) for p in aC01.getParts()] >>> [getName(p) for p in aC01.getParts()]
[u'd003.txt', u'd001.txt'] ['d003.txt', 'd001.txt']
>>> aC01.add(resources[u'd001.txt'], 0) >>> aC01.add(resources['d001.txt'], 0)
>>> [getName(p) for p in aC01.getParts()] >>> [getName(p) for p in aC01.getParts()]
[u'd001.txt', u'd003.txt', u'd001.txt'] ['d001.txt', 'd003.txt', 'd001.txt']
>>> aC01.add(resources[u'd002.txt'], -1) >>> aC01.add(resources['d002.txt'], -1)
>>> [getName(p) for p in aC01.getParts()] >>> [getName(p) for p in aC01.getParts()]
[u'd001.txt', u'd003.txt', u'd002.txt', u'd001.txt'] ['d001.txt', 'd003.txt', 'd002.txt', 'd001.txt']
We can reorder the parts of a compound. We can reorder the parts of a compound.
>>> aC01.reorder([resources[u'd002.txt'], resources[u'd001.txt'], ]) >>> aC01.reorder([resources['d002.txt'], resources['d001.txt'], ])
>>> [getName(p) for p in aC01.getParts()] >>> [getName(p) for p in aC01.getParts()]
[u'd002.txt', u'd001.txt', u'd003.txt', u'd001.txt'] ['d002.txt', 'd001.txt', 'd003.txt', 'd001.txt']
And remove a part from the compound. And remove a part from the compound.
>>> aC01.remove(resources[u'd001.txt'], 1) >>> aC01.remove(resources['d001.txt'], 1)
>>> [getName(p) for p in aC01.getParts()] >>> [getName(p) for p in aC01.getParts()]
[u'd002.txt', u'd003.txt', u'd001.txt'] ['d002.txt', 'd003.txt', 'd001.txt']
Blogs Blogs
@ -83,23 +83,23 @@ Blogs
>>> from loops.compound.blog.interfaces import IBlogPost >>> from loops.compound.blog.interfaces import IBlogPost
>>> component.provideAdapter(BlogPost, provides=IBlogPost) >>> component.provideAdapter(BlogPost, provides=IBlogPost)
>>> tBlog = addAndConfigureObject(concepts, Concept, 'blog', title=u'Blog', >>> tBlog = addAndConfigureObject(concepts, Concept, 'blog', title='Blog',
... conceptType=tType) ... conceptType=tType)
>>> tBlogPost = addAndConfigureObject(concepts, Concept, 'blogpost', >>> tBlogPost = addAndConfigureObject(concepts, Concept, 'blogpost',
... title=u'Blog Post', conceptType=tType, ... title='Blog Post', conceptType=tType,
... typeInterface=IBlogPost) ... typeInterface=IBlogPost)
>>> myBlog = addAndConfigureObject(concepts, Concept, 'myblog', title=u'My Blog', >>> myBlog = addAndConfigureObject(concepts, Concept, 'myblog', title='My Blog',
... conceptType=tBlog) ... conceptType=tBlog)
>>> firstPost = addAndConfigureObject(concepts, Concept, 'firstpost', >>> firstPost = addAndConfigureObject(concepts, Concept, 'firstpost',
... title=u'My first post', conceptType=tBlogPost) ... title='My first post', conceptType=tBlogPost)
>>> aFirstPost = adapted(firstPost) >>> aFirstPost = adapted(firstPost)
>>> aFirstPost.date >>> aFirstPost.date
>>> aFirstPost.text = u'My first blog post.' >>> aFirstPost.text = 'My first blog post.'
>>> aFirstPost.text >>> aFirstPost.text
u'My first blog post.' 'My first blog post.'
>>> aFirstPost.creator >>> aFirstPost.creator
Blog and BlogPost views Blog and BlogPost views
@ -114,7 +114,7 @@ a new post.
>>> view = BlogView(myBlog, TestRequest()) >>> view = BlogView(myBlog, TestRequest())
>>> for act in view.getActions('portlet'): >>> for act in view.getActions('portlet'):
... print act.name ... print(act.name)
createBlogPost createBlogPost
>>> view = BlogPostView(firstPost, TestRequest()) >>> view = BlogPostView(firstPost, TestRequest())
@ -143,13 +143,13 @@ and a corresponding person.
>>> auth = setupData.auth >>> auth = setupData.auth
>>> tPerson = concepts['person'] >>> tPerson = concepts['person']
>>> userJohn = auth.definePrincipal('users.john', u'John', login='john') >>> userJohn = auth.definePrincipal('users.john', 'John', login='john')
>>> persJohn = addAndConfigureObject(concepts, Concept, 'person.john', >>> persJohn = addAndConfigureObject(concepts, Concept, 'person.john',
... title=u'John Smith', conceptType=tPerson, ... title='John Smith', conceptType=tPerson,
... userId='users.john') ... userId='users.john')
>>> blogJohn = addAndConfigureObject(concepts, Concept, 'blog.john', >>> blogJohn = addAndConfigureObject(concepts, Concept, 'blog.john',
... title=u'John\'s Blog', conceptType=tBlog) ... title='John\'s Blog', conceptType=tBlog)
>>> persJohn.assignChild(blogJohn) >>> persJohn.assignChild(blogJohn)
Let's now login as the newly defined user. Let's now login as the newly defined user.
@ -178,9 +178,9 @@ used for creating the blog post.
>>> home.target = myBlog >>> home.target = myBlog
>>> from loops.compound.blog.browser import CreateBlogPostForm, CreateBlogPost >>> from loops.compound.blog.browser import CreateBlogPostForm, CreateBlogPost
>>> input = {'title': u'John\'s first post', 'text': u'Text of John\'s post', >>> input = {'title': 'John\'s first post', 'text': 'Text of John\'s post',
... 'date': '2008-02-02T15:54:11', ... 'date': '2008-02-02T15:54:11',
... 'privateComment': u'John\'s private comment', ... 'privateComment': 'John\'s private comment',
... 'form.type': '.loops/concepts/blogpost'} ... 'form.type': '.loops/concepts/blogpost'}
>>> cbpForm = CreateBlogPostForm(home, TestRequest(form=input)) >>> cbpForm = CreateBlogPostForm(home, TestRequest(form=input))
>>> cbpController = CreateBlogPost(cbpForm, cbpForm.request) >>> cbpController = CreateBlogPost(cbpForm, cbpForm.request)
@ -192,11 +192,11 @@ used for creating the blog post.
1 1
>>> postJohn0 = posts[0] >>> postJohn0 = posts[0]
>>> postJohn0.title >>> postJohn0.title
u"John's first post" "John's first post"
>>> postJohn0Text = adapted(postJohn0.getResources()[0]) >>> postJohn0Text = adapted(postJohn0.getResources()[0])
>>> postJohn0Text.data >>> postJohn0Text.data
u"Text of John's post" "Text of John's post"
Security Security
@ -269,7 +269,7 @@ So let's now switch to another user. On a global level, Martha also has
the ContentManager role, i.e. she is allowed to edit content objects. the ContentManager role, i.e. she is allowed to edit content objects.
Nevertheless she is not allowed to change John's blog post. Nevertheless she is not allowed to change John's blog post.
>>> userMartha = auth.definePrincipal('users.martha', u'Martha', login='martha') >>> userMartha = auth.definePrincipal('users.martha', 'Martha', login='martha')
>>> assignRole('zope.Member', 'users.martha') >>> assignRole('zope.Member', 'users.martha')
>>> assignRole('zope.ContentManager', 'users.martha') >>> assignRole('zope.ContentManager', 'users.martha')
@ -322,29 +322,29 @@ Micro Articles
>>> component.provideAdapter(MicroArt, provides=IMicroArt) >>> component.provideAdapter(MicroArt, provides=IMicroArt)
>>> tMicroArt = addAndConfigureObject(concepts, Concept, 'microart', >>> tMicroArt = addAndConfigureObject(concepts, Concept, 'microart',
... title=u'MicroArt', conceptType=tType, ... title='MicroArt', conceptType=tType,
... typeInterface=IMicroArt) ... typeInterface=IMicroArt)
>>> ma01 = addAndConfigureObject(concepts, Concept, 'ma01', >>> ma01 = addAndConfigureObject(concepts, Concept, 'ma01',
... conceptType=tMicroArt, ... conceptType=tMicroArt,
... title=u'Organizational Knowledge', ... title='Organizational Knowledge',
... story=u'Systemic KM talks about organizational knowledge.', ... story='Systemic KM talks about organizational knowledge.',
... insight=u'Organizational knowledge is not visible.', ... insight='Organizational knowledge is not visible.',
... consequences=u'Use examples. Look for strucure and rules. ' ... consequences='Use examples. Look for strucure and rules. '
... u'Knowledge shows itself in actions.', ... 'Knowledge shows itself in actions.',
... followUps=u'What about collective intelligence? ' ... followUps='What about collective intelligence? '
... u'How does an organization express itself?') ... 'How does an organization express itself?')
>>> ma01._insight >>> ma01._insight
u'Organizational knowledge is not visible.' 'Organizational knowledge is not visible.'
>>> list(resources) >>> list(resources)
[..., u'ma01_story'] [..., 'ma01_story']
>>> adMa01 = adapted(ma01) >>> adMa01 = adapted(ma01)
>>> adMa01.insight >>> adMa01.insight
u'Organizational knowledge is not visible.' 'Organizational knowledge is not visible.'
>>> adMa01.story >>> adMa01.story
u'Systemic KM talks about organizational knowledge.' 'Systemic KM talks about organizational knowledge.'
Books, Sections, and Pages Books, Sections, and Pages

View file

@ -1,37 +1,19 @@
# # loops.compound.base
# 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
#
""" """ Compound objects like articles, blog posts, storyboard items, ...
Compound objects like articles, blog posts, storyboard items, ...
""" """
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 from zope.traversing.api import getName
from loops.common import AdapterBase from loops.common import AdapterBase
from loops.compound.interfaces import ICompound, compoundPredicateNames from loops.compound.interfaces import ICompound, compoundPredicateNames
@implementer(ICompound)
class Compound(AdapterBase): class Compound(AdapterBase):
implements(ICompound)
compoundPredicateNames = compoundPredicateNames compoundPredicateNames = compoundPredicateNames
@Lazy @Lazy

View file

@ -1,28 +1,11 @@
# # loops.compound.blog.post
# 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
#
""" """ Blogs and blog posts.
Blogs and blog posts.
""" """
from zope.cachedescriptors.property import Lazy from zope.cachedescriptors.property import Lazy
from zope.dublincore.interfaces import IZopeDublinCore from zope.dublincore.interfaces import IZopeDublinCore
from zope.interface import implements from zope.interface import implementer
from zope.event import notify from zope.event import notify
from zope.lifecycleevent import ObjectCreatedEvent, ObjectModifiedEvent from zope.lifecycleevent import ObjectCreatedEvent, ObjectModifiedEvent
from zope import schema from zope import schema
@ -40,10 +23,9 @@ from loops.type import TypeInterfaceSourceList
TypeInterfaceSourceList.typeInterfaces += (ISimpleBlogPost, IBlogPost,) TypeInterfaceSourceList.typeInterfaces += (ISimpleBlogPost, IBlogPost,)
@implementer(ISimpleBlogPost)
class SimpleBlogPost(Compound): class SimpleBlogPost(Compound):
implements(ISimpleBlogPost)
textContentType = 'text/html' textContentType = 'text/html'
_adapterAttributes = Compound._adapterAttributes + ('creator',) _adapterAttributes = Compound._adapterAttributes + ('creator',)
@ -57,10 +39,9 @@ class SimpleBlogPost(Compound):
return cr and cr[0] or None return cr and cr[0] or None
@implementer(IBlogPost)
class BlogPost(Compound): class BlogPost(Compound):
implements(IBlogPost)
_adapterAttributes = Compound._adapterAttributes + ('text', 'private', 'creator',) _adapterAttributes = Compound._adapterAttributes + ('text', 'private', 'creator',)
_contextAttributes = Compound._contextAttributes + ['date', 'privateComment'] _contextAttributes = Compound._contextAttributes + ['date', 'privateComment']
_noexportAttributes = ('creator', 'text', 'private') _noexportAttributes = ('creator', 'text', 'private')

View file

@ -1,28 +1,10 @@
# # loops.compound.blog.security
# 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
#
""" """ Security settings for blogs and blog posts.
Security settings for blogs and blog posts.
""" """
from zope.cachedescriptors.property import Lazy from zope.cachedescriptors.property import Lazy
from zope.component import adapts from zope.component import adapts
from zope.interface import implements
from zope.traversing.api import getName from zope.traversing.api import getName
from loops.compound.blog.interfaces import IBlogPost from loops.compound.blog.interfaces import IBlogPost

View file

@ -1,28 +1,11 @@
# # loops.compound.book.browser
# 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
#
""" """ View class(es) book/section/page structures.
View class(es) book/section/page structures.
""" """
from cgi import parse_qs from urllib.parse import parse_qs
from zope import interface, component from zope import interface, component
from zope.app.pagetemplate import ViewPageTemplateFile from zope.browserpage import ViewPageTemplateFile
from zope.cachedescriptors.property import Lazy from zope.cachedescriptors.property import Lazy
from zope.traversing.api import getName from zope.traversing.api import getName

View file

@ -1,28 +1,11 @@
# # loops.compound.microart.base
# Copyright (c) 2011 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
#
""" """ Micro articles (MicroArt).
Micro articles (MicroArt).
""" """
from zope.cachedescriptors.property import Lazy from zope.cachedescriptors.property import Lazy
from zope.dublincore.interfaces import IZopeDublinCore from zope.dublincore.interfaces import IZopeDublinCore
from zope.interface import implements from zope.interface import implementer
from zope.event import notify from zope.event import notify
from zope.lifecycleevent import ObjectCreatedEvent, ObjectModifiedEvent from zope.lifecycleevent import ObjectCreatedEvent, ObjectModifiedEvent
from zope import schema from zope import schema
@ -39,10 +22,9 @@ from loops.type import TypeInterfaceSourceList
TypeInterfaceSourceList.typeInterfaces += (IMicroArt,) TypeInterfaceSourceList.typeInterfaces += (IMicroArt,)
@implementer(IMicroArt)
class MicroArt(Compound): class MicroArt(Compound):
implements(IMicroArt)
_contextAttributes = list(IMicroArt) _contextAttributes = list(IMicroArt)
_adapterAttributes = Compound._adapterAttributes + ('story',) _adapterAttributes = Compound._adapterAttributes + ('story',)
_noexportAttributes = ('story',) _noexportAttributes = ('story',)

View file

@ -54,12 +54,12 @@ from their typeInterface adapters we here append a 'C' to the name of
the variables: the variables:
>>> from loops.concept import Concept >>> from loops.concept import Concept
>>> progLangC = concepts['progLang'] = Concept(u'Programming Language') >>> progLangC = concepts['progLang'] = Concept('Programming Language')
>>> ooProgC = concepts['ooProg'] = Concept(u'Object-oriented Programming') >>> ooProgC = concepts['ooProg'] = Concept('Object-oriented Programming')
>>> pythonC = concepts['python'] = Concept(u'Python') >>> pythonC = concepts['python'] = Concept('Python')
>>> pyBasicsC = concepts['pyBasics'] = Concept(u'Python Basics') >>> pyBasicsC = concepts['pyBasics'] = Concept('Python Basics')
>>> pyOoC = concepts['pyOo'] = Concept(u'OO Programming with Python') >>> pyOoC = concepts['pyOo'] = Concept('OO Programming with Python')
>>> pySpecialsC = concepts['pySpecials'] = Concept(u'Python Specials') >>> pySpecialsC = concepts['pySpecials'] = Concept('Python Specials')
>>> topicConcepts = (progLangC, ooProgC, pythonC, pyBasicsC, pyOoC, pySpecialsC) >>> topicConcepts = (progLangC, ooProgC, pythonC, pyBasicsC, pyOoC, pySpecialsC)
@ -78,13 +78,13 @@ the variables:
We now create a person and assign some knowledge to it: We now create a person and assign some knowledge to it:
>>> johnC = concepts['john'] = Concept(u'John') >>> johnC = concepts['john'] = Concept('John')
>>> johnC.conceptType = person >>> johnC.conceptType = person
>>> john = IPerson(johnC) >>> john = IPerson(johnC)
>>> john.knows(pyBasics) >>> john.knows(pyBasics)
>>> list(john.getKnowledge())[0].title >>> list(john.getKnowledge())[0].title
u'Python Basics' 'Python Basics'
Now let's get to tasks - a task is used as a requirement profile, i.e. Now let's get to tasks - a task is used as a requirement profile, i.e.
it requires a certain set of knowledge elements: it requires a certain set of knowledge elements:
@ -100,7 +100,7 @@ a position with the requirement profile:
>>> missing = john.getMissingKnowledge(task01) >>> missing = john.getMissingKnowledge(task01)
>>> [m.title for m in missing] >>> [m.title for m in missing]
[u'Object-oriented Programming', u'OO Programming with Python'] ['Object-oriented Programming', 'OO Programming with Python']
Luckily there are a few elearning content objects out there that Luckily there are a few elearning content objects out there that
provide some of the knowledge needed: provide some of the knowledge needed:
@ -155,7 +155,7 @@ For testing, we first have to provide the needed utilities and settings
>>> principalAnnotations = PrincipalAnnotationUtility() >>> principalAnnotations = PrincipalAnnotationUtility()
>>> component.provideUtility(principalAnnotations, IPrincipalAnnotationUtility) >>> component.provideUtility(principalAnnotations, IPrincipalAnnotationUtility)
>>> principal = auth.definePrincipal('users.john', u'John', login='john') >>> principal = auth.definePrincipal('users.john', 'John', login='john')
>>> john.userId = 'users.john' >>> john.userId = 'users.john'
>>> from zope.publisher.browser import TestRequest >>> from zope.publisher.browser import TestRequest

View file

@ -1,30 +1,13 @@
# # loops.knowledge.survey.browser
# 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
#
""" """ Definition of view classes and other browser related stuff for
Definition of view classes and other browser related stuff for
surveys and self-assessments. surveys and self-assessments.
""" """
import csv import csv
from cStringIO import StringIO from io import StringIO
import math import math
from zope.app.pagetemplate import ViewPageTemplateFile from zope.browserpage import ViewPageTemplateFile
from zope.cachedescriptors.property import Lazy from zope.cachedescriptors.property import Lazy
from zope.i18n import translate from zope.i18n import translate

View file

@ -1,27 +1,10 @@
# # loops.knowledge.survey.response
# 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
#
""" """ Handling survey responses.
Handling survey responses.
""" """
from zope.component import adapts from zope.component import adapts
from zope.interface import implements from zope.interface import implementer
from cybertools.tracking.btree import Track from cybertools.tracking.btree import Track
from cybertools.tracking.interfaces import ITrackingStorage from cybertools.tracking.interfaces import ITrackingStorage
@ -29,10 +12,9 @@ from loops.knowledge.survey.interfaces import IResponse, IResponses
from loops.organize.tracking.base import BaseRecordManager from loops.organize.tracking.base import BaseRecordManager
@implementer(IResponses)
class Responses(BaseRecordManager): class Responses(BaseRecordManager):
implements(IResponses)
storageName = 'survey_responses' storageName = 'survey_responses'
personId = None personId = None
institutionId = None institutionId = None
@ -84,9 +66,8 @@ class Responses(BaseRecordManager):
return self.storage.query(taskId=self.uid) return self.storage.query(taskId=self.uid)
@implementer(IResponse)
class Response(Track): class Response(Track):
implements(IResponse)
typeName = 'Response' typeName = 'Response'

View file

@ -4,8 +4,6 @@ loops - Linked Objects for Organization and Processing Services
Managing versions of resources. Managing versions of resources.
($Id$)
Setting up a loops Site and Utilities Setting up a loops Site and Utilities
===================================== =====================================
@ -45,7 +43,7 @@ adapter on the object.
>>> d001 = resources['d001.txt'] >>> d001 = resources['d001.txt']
>>> d001.title >>> d001.title
u'Doc 001' 'Doc 001'
>>> vD001 = IVersionable(d001) >>> vD001 = IVersionable(d001)
>>> vD001.versionLevels >>> vD001.versionLevels
['major', 'minor'] ['major', 'minor']
@ -68,9 +66,9 @@ Now we can create a new version for our document:
>>> d001v1_2 = vD001.createVersion() >>> d001v1_2 = vD001.createVersion()
>>> getName(d001v1_2) >>> getName(d001v1_2)
u'd001_1.2.txt' 'd001_1.2.txt'
>>> d001v1_2.title >>> d001v1_2.title
u'Doc 001' 'Doc 001'
>>> vD001v1_2 = IVersionable(d001v1_2) >>> vD001v1_2 = IVersionable(d001v1_2)
>>> vD001v1_2.versionId >>> vD001v1_2.versionId
@ -91,14 +89,14 @@ a major version change, the lower levels are reset to 1:
>>> d001v2_1 = vD001.createVersion(0) >>> d001v2_1 = vD001.createVersion(0)
>>> getName(d001v2_1) >>> getName(d001v2_1)
u'd001_2.1.txt' 'd001_2.1.txt'
The name of the new version is always derived from the name of the master The name of the new version is always derived from the name of the master
even if we create a new version from another one: even if we create a new version from another one:
>>> d001v2_2 = IVersionable(d001v1_2).createVersion() >>> d001v2_2 = IVersionable(d001v1_2).createVersion()
>>> getName(d001v2_2) >>> getName(d001v2_2)
u'd001_2.2.txt' 'd001_2.2.txt'
Providing the Correct Version Providing the Correct Version
@ -151,7 +149,7 @@ derived from it are deleted as well.
>>> del resources['d001.txt'] >>> del resources['d001.txt']
>>> sorted(resources) >>> sorted(resources)
[u'd002.txt', u'd003.txt'] ['d002.txt', 'd003.txt']
Fin de partie Fin de partie

View file

@ -1,22 +1,22 @@
""" # loops.versioning.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.annotation.attribute import AttributeAnnotations from zope.annotation.attribute import AttributeAnnotations
from zope.annotation.interfaces import IAnnotatable from zope.annotation.interfaces import IAnnotatable
from zope.app.catalog.catalog import Catalog from zope.authentication.interfaces import IAuthentication
from zope.app.catalog.interfaces import ICatalog from zope.catalog.catalog import Catalog
from zope.app.catalog.field import FieldIndex from zope.catalog.interfaces import ICatalog
from zope.app.catalog.text import TextIndex from zope.catalog.field import FieldIndex
from zope.app.container.interfaces import IObjectRemovedEvent from zope.catalog.text import TextIndex
from zope.app.security.interfaces import IAuthentication from zope.container.interfaces import IObjectRemovedEvent
from zope.app.security.principalregistry import principalRegistry
from zope.dublincore.annotatableadapter import ZDCAnnotatableAdapter from zope.dublincore.annotatableadapter import ZDCAnnotatableAdapter
from zope.dublincore.interfaces import IZopeDublinCore from zope.dublincore.interfaces import IZopeDublinCore
from zope.principalregistry.principalregistry import principalRegistry
from cybertools.meta.interfaces import IOptions
from cybertools.relation.tests import IntIdsStub from cybertools.relation.tests import IntIdsStub
from cybertools.relation.registry import RelationRegistry from cybertools.relation.registry import RelationRegistry
from cybertools.relation.interfaces import IRelationRegistry from cybertools.relation.interfaces import IRelationRegistry
@ -56,7 +56,7 @@ class TestSite(object):
component.provideAdapter(ZDCAnnotatableAdapter, (ILoopsObject,), IZopeDublinCore) component.provideAdapter(ZDCAnnotatableAdapter, (ILoopsObject,), IZopeDublinCore)
component.provideAdapter(AttributeAnnotations, (ILoopsObject,)) component.provideAdapter(AttributeAnnotations, (ILoopsObject,))
component.provideAdapter(LoopsDCAdapter, (IConcept,), IZopeDublinCore) component.provideAdapter(LoopsDCAdapter, (IConcept,), IZopeDublinCore)
component.provideAdapter(LoopsOptions) component.provideAdapter(LoopsOptions, provides=IOptions)
component.provideAdapter(ConceptType) component.provideAdapter(ConceptType)
component.provideAdapter(ResourceType) component.provideAdapter(ResourceType)