Python3 fixes: test setup OK, starting with fixes in README.txt

This commit is contained in:
Helmut Merz 2024-09-24 17:38:15 +02:00
parent 494612235e
commit 42d24a5c3f
4 changed files with 103 additions and 137 deletions

View file

@ -48,14 +48,14 @@ top-level loops container and a concept manager:
>>> cc1 = Concept() >>> cc1 = Concept()
>>> concepts['cc1'] = cc1 >>> concepts['cc1'] = cc1
>>> cc1.title >>> cc1.title
u'' ''
>>> loopsRoot.getLoopsUri(cc1) >>> loopsRoot.getLoopsUri(cc1)
u'.loops/concepts/cc1' '.loops/concepts/cc1'
>>> cc2 = Concept(u'Zope 3') >>> cc2 = Concept('Zope 3')
>>> concepts['cc2'] = cc2 >>> concepts['cc2'] = cc2
>>> cc2.title >>> cc2.title
u'Zope 3' 'Zope 3'
Now we want to relate the second concept to the first one. Now we want to relate the second concept to the first one.
@ -73,11 +73,11 @@ ConceptRelation):
We can now ask our concepts for their related child and parent concepts: We can now ask our concepts for their related child and parent concepts:
>>> [getName(c) for c in cc1.getChildren()] >>> [getName(c) for c in cc1.getChildren()]
[u'cc2'] ['cc2']
>>> len(cc1.getParents()) >>> len(cc1.getParents())
0 0
>>> [getName(p) for p in cc2.getParents()] >>> [getName(p) for p in cc2.getParents()]
[u'cc1'] ['cc1']
>>> len(cc2.getChildren()) >>> len(cc2.getChildren())
0 0
@ -90,24 +90,24 @@ a special predicate 'hasType'.
>>> typeObject = concepts['type'] >>> typeObject = concepts['type']
>>> typeObject.setConceptType(typeObject) >>> typeObject.setConceptType(typeObject)
>>> typeObject.getConceptType().title >>> typeObject.getConceptType().title
u'Type' 'Type'
>>> concepts['unknown'] = Concept(u'Unknown Type') >>> concepts['unknown'] = Concept('Unknown Type')
>>> unknown = concepts['unknown'] >>> unknown = concepts['unknown']
>>> unknown.setConceptType(typeObject) >>> unknown.setConceptType(typeObject)
>>> unknown.getConceptType().title >>> unknown.getConceptType().title
u'Type' 'Type'
>>> cc1.setConceptType(unknown) >>> cc1.setConceptType(unknown)
>>> cc1.getConceptType().title >>> cc1.getConceptType().title
u'Unknown Type' 'Unknown Type'
>>> concepts['topic'] = Concept(u'Topic') >>> concepts['topic'] = Concept('Topic')
>>> topic = concepts['topic'] >>> topic = concepts['topic']
>>> topic.setConceptType(typeObject) >>> topic.setConceptType(typeObject)
>>> cc1.setConceptType(topic) >>> cc1.setConceptType(topic)
>>> cc1.getConceptType().title >>> cc1.getConceptType().title
u'Topic' 'Topic'
We get a list of types using the ConceptTypeSourceList. We get a list of types using the ConceptTypeSourceList.
In order for the type machinery to work we first have to provide a In order for the type machinery to work we first have to provide a
@ -124,7 +124,7 @@ type manager.
>>> from loops.concept import ConceptTypeSourceList >>> from loops.concept import ConceptTypeSourceList
>>> types = ConceptTypeSourceList(cc1) >>> types = ConceptTypeSourceList(cc1)
>>> sorted(t.title for t in types) >>> sorted(t.title for t in types)
[u'Customer', u'Domain', u'Predicate', u'Topic', u'Type', u'Unknown Type'] ['Customer', 'Domain', 'Predicate', 'Topic', 'Type', 'Unknown Type']
Using a PredicateSourceList we can retrieve a list of the available Using a PredicateSourceList we can retrieve a list of the available
predicates. predicates.
@ -136,7 +136,7 @@ Note that the 'hasType' predicate is suppressed from this list as the
corresponding relation is only assigned via the conceptType attribute: corresponding relation is only assigned via the conceptType attribute:
>>> sorted(t.title for t in predicates) >>> sorted(t.title for t in predicates)
[u'subobject'] ['subobject']
Concept Views Concept Views
------------- -------------
@ -146,7 +146,7 @@ Concept Views
>>> children = list(view.children()) >>> children = list(view.children())
>>> [c.title for c in children] >>> [c.title for c in children]
[u'Zope 3'] ['Zope 3']
The token attribute provided with the items returned by the children() and The token attribute provided with the items returned by the children() and
parents() methods identifies identifies not only the item itself but parents() methods identifies identifies not only the item itself but
@ -154,19 +154,19 @@ also the relationship to the context object using a combination
of URIs to item and the predicate of the relationship: of URIs to item and the predicate of the relationship:
>>> [c.token for c in children] >>> [c.token for c in children]
[u'.loops/concepts/cc2:.loops/concepts/standard'] ['.loops/concepts/cc2:.loops/concepts/standard']
There is also a concept configuration view that allows updating the There is also a concept configuration view that allows updating the
underlying context object: underlying context object:
>>> cc3 = Concept(u'loops for Zope 3') >>> cc3 = Concept('loops for Zope 3')
>>> concepts['cc3'] = cc3 >>> concepts['cc3'] = cc3
>>> view = ConceptConfigureView(cc1, >>> view = ConceptConfigureView(cc1,
... TestRequest(action='assign', tokens=['.loops/concepts/cc3'])) ... TestRequest(action='assign', tokens=['.loops/concepts/cc3']))
>>> view.update() >>> view.update()
True True
>>> sorted(c.title for c in cc1.getChildren()) >>> sorted(c.title for c in cc1.getChildren())
[u'Zope 3', u'loops for Zope 3'] ['Zope 3', 'loops for Zope 3']
>>> input = {'action': 'remove', 'qualifier': 'children', >>> input = {'action': 'remove', 'qualifier': 'children',
... 'form.button.submit': 'Remove Chiildren', ... 'form.button.submit': 'Remove Chiildren',
@ -175,18 +175,18 @@ underlying context object:
>>> view.update() >>> view.update()
True True
>>> sorted(c.title for c in cc1.getChildren()) >>> sorted(c.title for c in cc1.getChildren())
[u'loops for Zope 3'] ['loops for Zope 3']
We can also create a new concept and assign it. We can also create a new concept and assign it.
>>> params = {'action': 'create', 'create.name': 'cc4', >>> params = {'action': 'create', 'create.name': 'cc4',
... 'create.title': u'New concept', ... 'create.title': 'New concept',
... 'create.type': '.loops/concepts/topic'} ... 'create.type': '.loops/concepts/topic'}
>>> view = ConceptConfigureView(cc1, TestRequest(**params)) >>> view = ConceptConfigureView(cc1, TestRequest(**params))
>>> view.update() >>> view.update()
True True
>>> sorted(c.title for c in cc1.getChildren()) >>> sorted(c.title for c in cc1.getChildren())
[u'New concept', u'loops for Zope 3'] ['New concept', 'loops for Zope 3']
The concept configuration view provides methods for displaying concept The concept configuration view provides methods for displaying concept
types and predicates. types and predicates.
@ -198,15 +198,15 @@ types and predicates.
>>> component.provideAdapter(LoopsTerms, (IIterableSource, IBrowserRequest), ITerms) >>> component.provideAdapter(LoopsTerms, (IIterableSource, IBrowserRequest), ITerms)
>>> sorted((t.title, t.token) for t in view.conceptTypes()) >>> sorted((t.title, t.token) for t in view.conceptTypes())
[(u'Customer', '.loops/concepts/customer'), [('Customer', '.loops/concepts/customer'),
(u'Domain', '.loops/concepts/domain'), ('Domain', '.loops/concepts/domain'),
(u'Predicate', '.loops/concepts/predicate'), ('Predicate', '.loops/concepts/predicate'),
(u'Topic', '.loops/concepts/topic'), ('Topic', '.loops/concepts/topic'),
(u'Type', '.loops/concepts/type'), ('Type', '.loops/concepts/type'),
(u'Unknown Type', '.loops/concepts/unknown')] ('Unknown Type', '.loops/concepts/unknown')]
>>> sorted((t.title, t.token) for t in view.predicates()) >>> sorted((t.title, t.token) for t in view.predicates())
[(u'subobject', '.loops/concepts/standard')] [('subobject', '.loops/concepts/standard')]
Index attributes adapter Index attributes adapter
------------------------ ------------------------
@ -214,10 +214,10 @@ Index attributes adapter
>>> from loops.concept import IndexAttributes >>> from loops.concept import IndexAttributes
>>> idx = IndexAttributes(cc2) >>> idx = IndexAttributes(cc2)
>>> idx.text() >>> idx.text()
u'cc2 Zope 3' 'cc2 Zope 3'
>>> idx.title() >>> idx.title()
u'cc2 Zope 3' 'cc2 Zope 3'
Resources and what they have to do with Concepts Resources and what they have to do with Concepts
@ -233,20 +233,20 @@ A common type of resource is a document:
>>> from loops.interfaces import IDocument >>> from loops.interfaces import IDocument
>>> from loops.resource import Document >>> from loops.resource import Document
>>> doc1 = Document(u'Zope Info') >>> doc1 = Document('Zope Info')
>>> resources['doc1'] = doc1 >>> resources['doc1'] = doc1
>>> doc1.title >>> doc1.title
u'Zope Info' 'Zope Info'
>>> doc1.data >>> doc1.data
u'' ''
>>> doc1.contentType >>> doc1.contentType
u'' ''
We can also directly use Resource objects; these behave like files. We can also directly use Resource objects; these behave like files.
In fact, by using resource types we can explicitly assign a resource In fact, by using resource types we can explicitly assign a resource
the 'file' type, but we will use this feature later: the 'file' type, but we will use this feature later:
>>> img = Resource(u'A png Image') >>> img = Resource('A png Image')
For testing we use some simple files from the tests directory: For testing we use some simple files from the tests directory:
@ -261,7 +261,7 @@ For testing we use some simple files from the tests directory:
>>> img.contentType >>> img.contentType
'image/png' 'image/png'
>>> pdf = Resource(u'A pdf File') >>> pdf = Resource('A pdf File')
>>> pdf.data = open(os.path.join(path, 'test.pdf')).read() >>> pdf.data = open(os.path.join(path, 'test.pdf')).read()
>>> pdf.getSize() >>> pdf.getSize()
25862 25862
@ -287,7 +287,7 @@ from concepts to resources:
... 'tokens': ['.loops/resources/doc1:.loops/concepts/standard']} ... 'tokens': ['.loops/resources/doc1:.loops/concepts/standard']}
>>> view = ConceptConfigureView(cc1, TestRequest(form=form)) >>> view = ConceptConfigureView(cc1, TestRequest(form=form))
>>> [getName(r.context) for r in view.resources()] >>> [getName(r.context) for r in view.resources()]
[u'doc1'] ['doc1']
>>> view.update() >>> view.update()
True True
>>> len(cc1.getResources()) >>> len(cc1.getResources())
@ -316,10 +316,10 @@ Index attributes adapter
>>> component.provideAdapter(FileAdapter, provides=IFile) >>> component.provideAdapter(FileAdapter, provides=IFile)
>>> idx = IndexAttributes(doc1) >>> idx = IndexAttributes(doc1)
>>> idx.text() >>> idx.text()
u'' ''
>>> idx.title() >>> idx.title()
u'doc1 Zope Info' 'doc1 Zope Info'
Views/Nodes: Menus, Menu Items, Listings, Pages, etc Views/Nodes: Menus, Menu Items, Listings, Pages, etc
@ -343,14 +343,14 @@ The view manager has already been created during setup.
The view space is typically built up with nodes; a node may be a top-level The view space is typically built up with nodes; a node may be a top-level
menu that may contain other nodes as menu or content items: menu that may contain other nodes as menu or content items:
>>> m1 = views['m1'] = Node(u'Menu') >>> m1 = views['m1'] = Node('Menu')
>>> m11 = m1['m11'] = Node(u'Zope') >>> m11 = m1['m11'] = Node('Zope')
>>> m111 = m11['m111'] = Node(u'Zope in General') >>> m111 = m11['m111'] = Node('Zope in General')
>>> m112 = m11['m112'] = Node(u'Zope 3') >>> m112 = m11['m112'] = Node('Zope 3')
>>> m112.title >>> m112.title
u'Zope 3' 'Zope 3'
>>> m112.description >>> m112.description
u'' ''
There are a few convienence methods for accessing parent and child nodes: There are a few convienence methods for accessing parent and child nodes:
@ -359,7 +359,7 @@ There are a few convienence methods for accessing parent and child nodes:
>>> m11.getParentNode() is m1 >>> m11.getParentNode() is m1
True True
>>> [getName(child) for child in m11.getChildNodes()] >>> [getName(child) for child in m11.getChildNodes()]
[u'm111', u'm112'] ['m111', 'm112']
What is returned by these may be controlled by the nodeType attribute: What is returned by these may be controlled by the nodeType attribute:
@ -493,14 +493,14 @@ view; these views we have to provide as multi-adapters:
>>> len(tt) >>> len(tt)
9 9
>>> sorted((t.token, t.title) for t in view.targetTypes())[1] >>> sorted((t.token, t.title) for t in view.targetTypes())[1]
('.loops/concepts/domain', u'Domain') ('.loops/concepts/domain', 'Domain')
>>> view.update() >>> view.update()
True True
>>> sorted(resources.keys()) >>> sorted(resources.keys())
[u'd001.txt', u'd002.txt', u'd003.txt', u'doc1', u'm1.m11.m111'] ['d001.txt', 'd002.txt', 'd003.txt', 'doc1', 'm1.m11.m111']
>>> view.target.title, view.target.token >>> view.target.title, view.target.token
('New Resource', u'.loops/resources/m1.m11.m111') ('New Resource', '.loops/resources/m1.m11.m111')
A node object provides the targetSchema of its target: A node object provides the targetSchema of its target:
@ -537,28 +537,28 @@ view for rendering.)
>>> component.provideAdapter(LoopsType) >>> component.provideAdapter(LoopsType)
>>> view = NodeView(m112, TestRequest()) >>> view = NodeView(m112, TestRequest())
>>> view.renderTarget() >>> view.renderTarget()
u'<pre></pre>' '<pre></pre>'
>>> doc1.data = u'Test data\n\nAnother paragraph' >>> doc1.data = 'Test data\n\nAnother paragraph'
>>> view.renderTarget() >>> view.renderTarget()
u'<pre>Test data\n\nAnother paragraph</pre>' '<pre>Test data\n\nAnother paragraph</pre>'
>>> doc1.contentType = 'text/restructured' >>> doc1.contentType = 'text/restructured'
>>> doc1.data = u'Test data\n\nAnother `paragraph <para>`_' >>> doc1.data = 'Test data\n\nAnother `paragraph <para>`_'
>>> from loops.wiki.base import wikiLinksActive >>> from loops.wiki.base import wikiLinksActive
>>> wikiLinksActive(loopsRoot) >>> wikiLinksActive(loopsRoot)
False False
>>> view.renderTarget() >>> view.renderTarget()
u'<p>Test data</p>\n<p>Another <a class="reference external" href="para">paragraph</a></p>\n' '<p>Test data</p>\n<p>Another <a class="reference external" href="para">paragraph</a></p>\n'
u'<p>Test data</p>\n<p>Another <a class="reference create" '<p>Test data</p>\n<p>Another <a class="reference create"
href="http://127.0.0.1/loops/wiki/create.html?linkid=0000001">?paragraph</a></p>\n' href="http://127.0.0.1/loops/wiki/create.html?linkid=0000001">?paragraph</a></p>\n'
>>> #links = loopsRoot.getRecordManager()['links'] >>> #links = loopsRoot.getRecordManager()['links']
>>> #links['0000001'] >>> #links['0000001']
<Link ['42', 1, '', '... ...', u'para', None]: {}> <Link ['42', 1, '', '... ...', 'para', None]: {}>
If the target object is removed from its container all references If the target object is removed from its container all references
to it are removed as well. (To make this work we have to handle to it are removed as well. (To make this work we have to handle
@ -632,7 +632,7 @@ Let's add some more nodes and reorder them:
>>> m114 = Node() >>> m114 = Node()
>>> m11['m114'] = m114 >>> m11['m114'] = m114
>>> m11.keys() >>> m11.keys()
[u'm111', u'm112', u'm113', u'm114'] ['m111', 'm112', 'm113', 'm114']
A special management view provides methods for moving objects down, up, A special management view provides methods for moving objects down, up,
to the bottom, and to the top. to the bottom, and to the top.
@ -641,10 +641,10 @@ to the bottom, and to the top.
>>> view = OrderedContainerView(m11, TestRequest()) >>> view = OrderedContainerView(m11, TestRequest())
>>> view.move_bottom(('m113',)) >>> view.move_bottom(('m113',))
>>> m11.keys() >>> m11.keys()
[u'm111', u'm112', u'm114', u'm113'] ['m111', 'm112', 'm114', 'm113']
>>> view.move_up(('m114',), 1) >>> view.move_up(('m114',), 1)
>>> m11.keys() >>> m11.keys()
[u'm111', u'm114', u'm112', u'm113'] ['m111', 'm114', 'm112', 'm113']
Breadcrumbs Breadcrumbs
@ -661,9 +661,9 @@ Breadcrumbs
>>> view = NodeView(m114, request) >>> view = NodeView(m114, request)
>>> request.annotations.setdefault('loops.view', {})['nodeView'] = view >>> request.annotations.setdefault('loops.view', {})['nodeView'] = view
>>> view.breadcrumbs() >>> view.breadcrumbs()
[{'url': 'http://127.0.0.1/loops/views/m1', 'label': u'Menu'}, [{'url': 'http://127.0.0.1/loops/views/m1', 'label': 'Menu'},
{'url': 'http://127.0.0.1/loops/views/m1/m11', 'label': u'Zope'}, {'url': 'http://127.0.0.1/loops/views/m1/m11', 'label': 'Zope'},
{'url': 'http://127.0.0.1/loops/views/m1/m11/m114', 'label': u''}] {'url': 'http://127.0.0.1/loops/views/m1/m11/m114', 'label': ''}]
End-user Forms and Special Views End-user Forms and Special Views
@ -705,8 +705,8 @@ been created during setup.
>>> custType = TypeConcept(customer) >>> custType = TypeConcept(customer)
>>> custType.options >>> custType.options
[] []
>>> cust1 = concepts['cust1'] = Concept(u'Zope Corporation') >>> cust1 = concepts['cust1'] = Concept('Zope Corporation')
>>> cust2 = concepts['cust2'] = Concept(u'cyberconcepts') >>> cust2 = concepts['cust2'] = Concept('cyberconcepts')
>>> for c in (cust1, cust2): c.conceptType = customer >>> for c in (cust1, cust2): c.conceptType = customer
>>> custType.options = ('qualifier:assign',) >>> custType.options = ('qualifier:assign',)
>>> ConceptType(cust1).qualifiers >>> ConceptType(cust1).qualifiers
@ -714,7 +714,7 @@ been created during setup.
>>> form = CreateObjectForm(m112, TestRequest()) >>> form = CreateObjectForm(m112, TestRequest())
>>> form.presetTypesForAssignment >>> form.presetTypesForAssignment
[{'token': 'loops:concept:customer', 'title': u'Customer'}] [{'token': 'loops:concept:customer', 'title': 'Customer'}]
If the node's target is a type concept we don't get any assignments because If the node's target is a type concept we don't get any assignments because
it does not make much sense to assign resources or other concepts as it does not make much sense to assign resources or other concepts as
@ -736,18 +736,18 @@ on data provided in this form:
>>> note_tc = concepts['note'] >>> note_tc = concepts['note']
>>> component.provideAdapter(NameChooser) >>> component.provideAdapter(NameChooser)
>>> request = TestRequest(form={'title': u'Test Note', >>> request = TestRequest(form={'title': 'Test Note',
... 'form.type': u'.loops/concepts/note', ... 'form.type': '.loops/concepts/note',
... 'contentType': u'text/restructured', ... 'contentType': 'text/restructured',
... 'linkUrl': u'http://'}) ... 'linkUrl': 'http://'})
>>> view = NodeView(m112, request) >>> view = NodeView(m112, request)
>>> cont = CreateObject(view, request) >>> cont = CreateObject(view, request)
>>> cont.update() >>> cont.update()
False False
>>> sorted(resources.keys()) >>> sorted(resources.keys())
[...u'test_note'...] [...'test_note'...]
>>> resources['test_note'].title >>> resources['test_note'].title
u'Test Note' 'Test Note'
If there is a concept selected in the combo box we assign this to the newly If there is a concept selected in the combo box we assign this to the newly
created object: created object:
@ -755,8 +755,8 @@ created object:
>>> from loops import util >>> from loops import util
>>> topicUid = util.getUidForObject(topic) >>> topicUid = util.getUidForObject(topic)
>>> predicateUid = util.getUidForObject(concepts.getDefaultPredicate()) >>> predicateUid = util.getUidForObject(concepts.getDefaultPredicate())
>>> request = TestRequest(form={'title': u'Test Note', >>> request = TestRequest(form={'title': 'Test Note',
... 'form.type': u'.loops/concepts/note', ... 'form.type': '.loops/concepts/note',
... 'form.assignments.selected': ... 'form.assignments.selected':
... [':'.join((topicUid, predicateUid))]}) ... [':'.join((topicUid, predicateUid))]})
>>> view = NodeView(m112, request) >>> view = NodeView(m112, request)
@ -764,22 +764,22 @@ created object:
>>> cont.update() >>> cont.update()
False False
>>> sorted(resources.keys()) >>> sorted(resources.keys())
[...u'test_note-2'...] [...'test_note-2'...]
>>> note = resources['test_note-2'] >>> note = resources['test_note-2']
>>> sorted(t.__name__ for t in note.getConcepts()) >>> sorted(t.__name__ for t in note.getConcepts())
[u'note', u'topic'] ['note', 'topic']
When creating an object its name may be automatically generated using the title When creating an object its name may be automatically generated using the title
of the object. Let's make sure that the name chooser also handles special of the object. Let's make sure that the name chooser also handles special
and possibly critcal cases: and possibly critcal cases:
>>> nc = NameChooser(resources) >>> nc = NameChooser(resources)
>>> nc.chooseName(u'', Resource(u'abc: (cde)')) >>> nc.chooseName('', Resource('abc: (cde)'))
u'abc__cde' 'abc__cde'
>>> nc.chooseName(u'', Resource(u'\xdcml\xe4ut')) >>> nc.chooseName('', Resource('\xdcml\xe4ut'))
u'uemlaeut' 'uemlaeut'
>>> nc.chooseName(u'', Resource(u'A very very loooooong title')) >>> nc.chooseName('', Resource('A very very loooooong title'))
u'a_title' 'a_title'
Editing an Object Editing an Object
----------------- -----------------
@ -804,22 +804,22 @@ The new technique uses the ``fields`` and ``data`` attributes...
linkText textline False None linkText textline False None
>>> view.data >>> view.data
{'linkUrl': u'http://', 'contentType': u'text/restructured', 'data': u'', {'linkUrl': 'http://', 'contentType': 'text/restructured', 'data': '',
'linkText': u'', 'title': u'Test Note'} 'linkText': '', 'title': 'Test Note'}
The object is changed via a FormController adapter created for The object is changed via a FormController adapter created for
a NodeView. a NodeView.
>>> form = dict( >>> form = dict(
... title=u'Test Note - changed', ... title='Test Note - changed',
... contentType=u'text/plain',) ... contentType='text/plain',)
>>> request = TestRequest(form=form) >>> request = TestRequest(form=form)
>>> view = NodeView(m112, request) >>> view = NodeView(m112, request)
>>> cont = EditObject(view, request) >>> cont = EditObject(view, request)
>>> cont.update() >>> cont.update()
False False
>>> resources['test_note'].title >>> resources['test_note'].title
u'Test Note - changed' 'Test Note - changed'
Virtual Targets Virtual Targets
--------------- ---------------
@ -951,7 +951,7 @@ To be done...
>>> obj = resources['test_note'] >>> obj = resources['test_note']
>>> cxObj = cached(obj) >>> cxObj = cached(obj)
>>> [p.object.title for p in cxObj.getAllParents()] >>> [p.object.title for p in cxObj.getAllParents()]
[u'Note', u'Type'] ['Note', 'Type']
Security Security

View file

@ -1,23 +1,6 @@
# # loops.external.element
# 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
#
""" """ Basic implementation of the elements used for the intermediate format for export
Basic implementation of the elements used for the intermediate format for export
and import of loops objects. and import of loops objects.
""" """
@ -25,7 +8,7 @@ import os
from zope import component from zope import component
from zope.cachedescriptors.property import Lazy from zope.cachedescriptors.property import Lazy
from zope.dottedname.resolve import resolve from zope.dottedname.resolve import resolve
from zope.interface import Interface, implements from zope.interface import Interface, implementer
from zope.traversing.api import getName, traverse from zope.traversing.api import getName, traverse
from cybertools.composer.interfaces import IInstance from cybertools.composer.interfaces import IInstance
@ -41,10 +24,9 @@ from loops.predicate import adaptedRelation
from loops.view import Node from loops.view import Node
@implementer(IElement)
class Element(dict): class Element(dict):
implements(IElement)
elementType = '' elementType = ''
posArgs = () posArgs = ()
object = None object = None

View file

@ -25,7 +25,7 @@ from zope.security.management import setSecurityPolicy
from zope.securitypolicy.zopepolicy import ZopeSecurityPolicy from zope.securitypolicy.zopepolicy import ZopeSecurityPolicy
from zope.securitypolicy.principalrole import AnnotationPrincipalRoleManager from zope.securitypolicy.principalrole import AnnotationPrincipalRoleManager
from zope.securitypolicy.rolepermission import AnnotationRolePermissionManager from zope.securitypolicy.rolepermission import AnnotationRolePermissionManager
from zope.session.interfaces import IClientIdManager, ISessionDataContainer from zope.session.interfaces import IClientId, IClientIdManager, ISessionDataContainer
from zope.session import session from zope.session import session
from cybertools.browser.controller import Controller from cybertools.browser.controller import Controller
@ -37,6 +37,7 @@ from cybertools.composer.schema.field import FieldInstance, \
from cybertools.composer.schema.field import FileUploadFieldInstance from cybertools.composer.schema.field import FileUploadFieldInstance
from cybertools.composer.schema.grid.field import RecordsFieldInstance from cybertools.composer.schema.grid.field import RecordsFieldInstance
from cybertools.composer.schema.instance import Instance, Editor from cybertools.composer.schema.instance import Instance, Editor
from cybertools.meta.interfaces import IOptions
from cybertools.relation.tests import IntIdsStub from cybertools.relation.tests import IntIdsStub
from cybertools.relation.registry import RelationRegistry, IIndexableRelation from cybertools.relation.registry import RelationRegistry, IIndexableRelation
from cybertools.relation.interfaces import IRelation, IRelationRegistry from cybertools.relation.interfaces import IRelation, IRelationRegistry
@ -123,7 +124,7 @@ class TestSite(object):
component.provideAdapter(AnnotationPrincipalRoleManager, (ILoopsObject,)) component.provideAdapter(AnnotationPrincipalRoleManager, (ILoopsObject,))
component.provideAdapter(AnnotationRolePermissionManager, (ILoopsObject,)) component.provideAdapter(AnnotationRolePermissionManager, (ILoopsObject,))
component.provideUtility(principalRegistry, IAuthentication) component.provideUtility(principalRegistry, IAuthentication)
component.provideAdapter(session.ClientId) component.provideAdapter(session.ClientId, provides=IClientId)
component.provideAdapter(session.Session) component.provideAdapter(session.Session)
component.provideUtility(session.RAMSessionDataContainer(), component.provideUtility(session.RAMSessionDataContainer(),
ISessionDataContainer) ISessionDataContainer)
@ -153,11 +154,11 @@ class TestSite(object):
component.provideAdapter(BaseSecuritySetter) component.provideAdapter(BaseSecuritySetter)
component.provideAdapter(ConceptSecuritySetter) component.provideAdapter(ConceptSecuritySetter)
component.provideAdapter(ResourceSecuritySetter) component.provideAdapter(ResourceSecuritySetter)
component.provideAdapter(LoopsOptions) component.provideAdapter(LoopsOptions, provides=IOptions)
component.provideAdapter(PredicateOptions) component.provideAdapter(PredicateOptions, provides=IOptions)
component.provideAdapter(QueryOptions) component.provideAdapter(QueryOptions, provides=IOptions)
component.provideAdapter(TypeOptions) component.provideAdapter(TypeOptions, provides=IOptions)
component.provideUtility(GlobalOptions()) component.provideUtility(GlobalOptions(), IOptions)
component.provideAdapter(VersionableResource) component.provideAdapter(VersionableResource)
component.provideAdapter(Instance) component.provideAdapter(Instance)

View file

@ -1,29 +1,12 @@
# # loops.versioning.versionable
# Copyright (c) 2014 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
#
""" """ Utilities for managing version informations.
Utilities for managing version informations.
""" """
from BTrees.OOBTree import OOBTree from BTrees.OOBTree import OOBTree
from zope import component from zope import component
from zope.component import adapts from zope.component import adapts
from zope.interface import implements, Attribute from zope.interface import implementer, Attribute
from zope.cachedescriptors.property import Lazy from zope.cachedescriptors.property import Lazy
from zope.schema.interfaces import IField from zope.schema.interfaces import IField
from zope.traversing.api import getName, getParent from zope.traversing.api import getName, getParent
@ -41,11 +24,11 @@ _not_found = object()
attrPattern = '__version_%s__' attrPattern = '__version_%s__'
@implementer(IVersionable)
class VersionableResource(object): class VersionableResource(object):
""" An adapter that enables a resource to store version information. """ An adapter that enables a resource to store version information.
""" """
implements(IVersionable)
adapts(IResource) adapts(IResource)
def __init__(self, context): def __init__(self, context):