Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Z
zope-container
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Boxiang Sun
zope-container
Commits
00f6a5c3
Commit
00f6a5c3
authored
Jan 28, 2009
by
Wolfgang Schnerring
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
remove browser subpackage
parent
f1f6cc98
Changes
21
Show whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
0 additions
and
3054 deletions
+0
-3054
src/zope/container/browser/__init__.py
src/zope/container/browser/__init__.py
+0
-2
src/zope/container/browser/add.pt
src/zope/container/browser/add.pt
+0
-58
src/zope/container/browser/adding.py
src/zope/container/browser/adding.py
+0
-211
src/zope/container/browser/commontasks.pt
src/zope/container/browser/commontasks.pt
+0
-41
src/zope/container/browser/configure.zcml
src/zope/container/browser/configure.zcml
+0
-20
src/zope/container/browser/contents.pt
src/zope/container/browser/contents.pt
+0
-193
src/zope/container/browser/contents.py
src/zope/container/browser/contents.py
+0
-464
src/zope/container/browser/find.pt
src/zope/container/browser/find.pt
+0
-22
src/zope/container/browser/find.py
src/zope/container/browser/find.py
+0
-42
src/zope/container/browser/index.pt
src/zope/container/browser/index.pt
+0
-66
src/zope/container/browser/meta.zcml
src/zope/container/browser/meta.zcml
+0
-16
src/zope/container/browser/metaconfigure.py
src/zope/container/browser/metaconfigure.py
+0
-88
src/zope/container/browser/tests/__init__.py
src/zope/container/browser/tests/__init__.py
+0
-2
src/zope/container/browser/tests/configure.zcml
src/zope/container/browser/tests/configure.zcml
+0
-16
src/zope/container/browser/tests/index.txt
src/zope/container/browser/tests/index.txt
+0
-18
src/zope/container/browser/tests/test_adding.py
src/zope/container/browser/tests/test_adding.py
+0
-586
src/zope/container/browser/tests/test_contents.py
src/zope/container/browser/tests/test_contents.py
+0
-380
src/zope/container/browser/tests/test_contents_functional.py
src/zope/container/browser/tests/test_contents_functional.py
+0
-375
src/zope/container/browser/tests/test_directive.py
src/zope/container/browser/tests/test_directive.py
+0
-294
src/zope/container/ftesting.zcml
src/zope/container/ftesting.zcml
+0
-57
src/zope/container/tests/test_view_permissions.py
src/zope/container/tests/test_view_permissions.py
+0
-103
No files found.
src/zope/container/browser/__init__.py
deleted
100644 → 0
View file @
f1f6cc98
#
# This file is necessary to make this directory a package.
src/zope/container/browser/add.pt
deleted
100644 → 0
View file @
f1f6cc98
<html
metal:use-macro=
"context/@@standard_macros/addingdialog"
i18n:domain=
"zope"
>
<body>
<div
metal:fill-slot=
"body"
>
<form
method=
"post"
action=
"action.html"
>
<table
class=
"TypeListing"
cellpadding=
"3"
>
<tal:block
define=
"title view/title | nothing"
>
<caption
tal:condition=
"title"
tal:content=
"title"
i18n:translate=
""
>
Inserted title
</caption>
<caption
tal:condition=
"not:title"
i18n:translate=
""
>
Add Content
</caption>
</tal:block>
<tbody
tal:define=
"infos view/addingInfo"
>
<tr
tal:repeat=
"info infos"
>
<td
class=
"Selector"
>
<input
type=
"radio"
name=
"type_name"
tal:attributes=
"value info/action;
id info/action;
checked python:len(infos)==1"
/>
</td>
<td
class=
"TypeName"
>
<label
style=
"font-weight: bold;"
tal:attributes=
"for info/action"
>
<span
tal:replace=
"info/title"
i18n:translate=
""
>
Folder
</span>
</label>
<div
class=
"TypeDescription"
tal:content=
"info/description"
i18n:translate=
""
>
Folders are generic containers for content, including other
folders.
</div>
</td>
</tr>
<tr>
<td><br
/></td>
<td><input
type=
"text"
name=
"id"
tal:condition=
"view/nameAllowed"
tal:attributes=
"value request/id | nothing"
/>
<input
type=
"submit"
name=
"add"
value=
" Add "
i18n:attributes=
"value add-button"
/>
</td>
</tr>
</tbody>
</table>
</form>
</div>
</body>
</html>
src/zope/container/browser/adding.py
deleted
100644 → 0
View file @
f1f6cc98
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Adding View
The Adding View is used to add new objects to a container. It is sort of a
factory screen.
$Id$
"""
__docformat__
=
'restructuredtext'
from
zope.app.container.constraints
import
checkFactory
from
zope.app.container.constraints
import
checkObject
from
zope.app.container.i18n
import
ZopeMessageFactory
as
_
from
zope.app.container.interfaces
import
IAdding
from
zope.app.container.interfaces
import
IContainerNamesContainer
from
zope.app.container.interfaces
import
INameChooser
from
zope.app.pagetemplate.viewpagetemplatefile
import
ViewPageTemplateFile
from
zope.app.publisher.browser.menu
import
getMenu
from
zope.component
import
getMultiAdapter
from
zope.component
import
getUtility
from
zope.component
import
queryAdapter
from
zope.component
import
queryMultiAdapter
from
zope.component
import
queryUtility
from
zope.component.interfaces
import
IFactory
from
zope.event
import
notify
from
zope.exceptions.interfaces
import
UserError
from
zope.i18n.interfaces.locales
import
ICollator
from
zope.i18n.locales.fallbackcollator
import
FallbackCollator
from
zope.interface
import
implements
from
zope.lifecycleevent
import
ObjectCreatedEvent
from
zope.location
import
LocationProxy
from
zope.publisher.browser
import
BrowserView
from
zope.publisher.interfaces
import
IPublishTraverse
from
zope.security.proxy
import
removeSecurityProxy
from
zope.traversing.browser.absoluteurl
import
absoluteURL
import
zope.security.checker
class
Adding
(
BrowserView
):
implements
(
IAdding
,
IPublishTraverse
)
def
add
(
self
,
content
):
"""See zope.app.container.interfaces.IAdding
"""
container
=
self
.
context
name
=
self
.
contentName
chooser
=
INameChooser
(
container
)
# check precondition
checkObject
(
container
,
name
,
content
)
if
IContainerNamesContainer
.
providedBy
(
container
):
# The container picks its own names.
# We need to ask it to pick one.
name
=
chooser
.
chooseName
(
self
.
contentName
or
''
,
content
)
else
:
request
=
self
.
request
name
=
request
.
get
(
'add_input_name'
,
name
)
if
name
is
None
:
name
=
chooser
.
chooseName
(
self
.
contentName
or
''
,
content
)
elif
name
==
''
:
name
=
chooser
.
chooseName
(
''
,
content
)
chooser
.
checkName
(
name
,
content
)
container
[
name
]
=
content
self
.
contentName
=
name
# Set the added object Name
return
container
[
name
]
contentName
=
None
# usually set by Adding traverser
def
nextURL
(
self
):
"""See zope.app.container.interfaces.IAdding"""
return
absoluteURL
(
self
.
context
,
self
.
request
)
+
'/@@contents.html'
# set in BrowserView.__init__
request
=
None
context
=
None
def
publishTraverse
(
self
,
request
,
name
):
"""See zope.publisher.interfaces.IPublishTraverse"""
if
'='
in
name
:
view_name
,
content_name
=
name
.
split
(
"="
,
1
)
self
.
contentName
=
content_name
if
view_name
.
startswith
(
'@@'
):
view_name
=
view_name
[
2
:]
return
getMultiAdapter
((
self
,
request
),
name
=
view_name
)
if
name
.
startswith
(
'@@'
):
view_name
=
name
[
2
:]
else
:
view_name
=
name
view
=
queryMultiAdapter
((
self
,
request
),
name
=
view_name
)
if
view
is
not
None
:
return
view
factory
=
queryUtility
(
IFactory
,
name
)
if
factory
is
None
:
return
super
(
Adding
,
self
).
publishTraverse
(
request
,
name
)
return
factory
def
action
(
self
,
type_name
=
''
,
id
=
''
):
if
not
type_name
:
raise
UserError
(
_
(
u"You must select the type of object to add."
))
if
type_name
.
startswith
(
'@@'
):
type_name
=
type_name
[
2
:]
if
'/'
in
type_name
:
view_name
=
type_name
.
split
(
'/'
,
1
)[
0
]
else
:
view_name
=
type_name
if
queryMultiAdapter
((
self
,
self
.
request
),
name
=
view_name
)
is
not
None
:
url
=
"%s/%s=%s"
%
(
absoluteURL
(
self
,
self
.
request
),
type_name
,
id
)
self
.
request
.
response
.
redirect
(
url
)
return
if
not
self
.
contentName
:
self
.
contentName
=
id
# TODO: If the factory wrapped by LocationProxy is already a Proxy,
# then ProxyFactory does not do the right thing and the
# original's checker info gets lost. No factory that was
# registered via ZCML and was used via addMenuItem worked
# here. (SR)
factory
=
getUtility
(
IFactory
,
type_name
)
if
not
type
(
factory
)
is
zope
.
security
.
checker
.
Proxy
:
factory
=
LocationProxy
(
factory
,
self
,
type_name
)
factory
=
zope
.
security
.
checker
.
ProxyFactory
(
factory
)
content
=
factory
()
# Can't store security proxies.
# Note that it is important to do this here, rather than
# in add, otherwise, someone might be able to trick add
# into unproxying an existing object,
content
=
removeSecurityProxy
(
content
)
notify
(
ObjectCreatedEvent
(
content
))
self
.
add
(
content
)
self
.
request
.
response
.
redirect
(
self
.
nextURL
())
def
nameAllowed
(
self
):
"""Return whether names can be input by the user."""
return
not
IContainerNamesContainer
.
providedBy
(
self
.
context
)
menu_id
=
None
index
=
ViewPageTemplateFile
(
"add.pt"
)
def
addingInfo
(
self
):
"""Return menu data.
This is sorted by title.
"""
container
=
self
.
context
result
=
[]
for
menu_id
in
(
self
.
menu_id
,
'zope.app.container.add'
):
if
not
menu_id
:
continue
for
item
in
getMenu
(
menu_id
,
self
,
self
.
request
):
extra
=
item
.
get
(
'extra'
)
if
extra
:
factory
=
extra
.
get
(
'factory'
)
if
factory
:
factory
=
getUtility
(
IFactory
,
factory
)
if
not
checkFactory
(
container
,
None
,
factory
):
continue
elif
item
[
'extra'
][
'factory'
]
!=
item
[
'action'
]:
item
[
'has_custom_add_view'
]
=
True
# translate here to have a localized sorting
item
[
'title'
]
=
zope
.
i18n
.
translate
(
item
[
'title'
],
context
=
self
.
request
)
result
.
append
(
item
)
# sort the adding info with a collator instead of a basic unicode sort
collator
=
queryAdapter
(
self
.
request
.
locale
,
ICollator
)
if
collator
is
None
:
collator
=
FallbackCollator
(
self
.
request
.
locale
)
result
.
sort
(
key
=
lambda
x
:
collator
.
key
(
x
[
'title'
]))
return
result
def
isSingleMenuItem
(
self
):
"Return whether there is single menu item or not."
return
len
(
self
.
addingInfo
())
==
1
def
hasCustomAddView
(
self
):
"This should be called only if there is `singleMenuItem` else return 0"
if
self
.
isSingleMenuItem
():
menu_item
=
self
.
addingInfo
()[
0
]
if
'has_custom_add_view'
in
menu_item
:
return
True
return
False
src/zope/container/browser/commontasks.pt
deleted
100644 → 0
View file @
f1f6cc98
<tal:block define="addingInfo context/@@+/addingInfo|nothing"
condition="addingInfo">
<tal:block repeat="info addingInfo"
define="namesRequired context/@@+/nameAllowed">
<div tal:define="oddrow repeat/info/odd;
namesRequired context/@@+/nameAllowed;
has_custom_add_view python:'has_custom_add_view' in info"
tal:attributes="class python:oddrow and 'content even' or 'content odd'"
class="even">
<a href="#"
tal:define="baseurl python:request.getURL(1)"
tal:condition="python: not info['action'].startswith('../')
and namesRequired and not has_custom_add_view"
tal:attributes="
href string:${baseurl}/@@contents.html?type_name=${info/action};
class info/selected"
tal:content="info/title">Folder
</a>
<a href="#"
tal:define="baseurl python:request.getURL(1)"
tal:condition="python: not info['action'].startswith('../')
and (has_custom_add_view or not namesRequired)"
tal:attributes="
href string:${baseurl}/@@+/action.html?type_name=${info/action};
class info/selected"
tal:content="info/title">Folder
</a>
<a href="#"
tal:define="baseurl python:request.getURL(1)"
tal:condition="python: info['action'].startswith('../')"
tal:attributes="
href python: info['action'][3:];
class info/selected"
tal:content="info/title">Folder
</a>
</div>
</tal:block>
</tal:block>
src/zope/container/browser/configure.zcml
deleted
100644 → 0
View file @
f1f6cc98
<zope:configure
xmlns:zope="http://namespaces.zope.org/zope"
xmlns="http://namespaces.zope.org/browser">
<page
for="zope.app.container.interfaces.IReadContainer"
name="find.html"
permission="zope.ManageContent"
class="zope.app.container.browser.find.Find"
template="find.pt"
menu="zmi_actions" title="Find" />
<page
for="zope.app.container.interfaces.IWriteContainer"
permission="zope.ManageContent"
name="commonTasks"
class="zope.app.container.browser.contents.Contents"
template="commontasks.pt" />
</zope:configure>
src/zope/container/browser/contents.pt
deleted
100644 → 0
View file @
f1f6cc98
<html
metal:use-macro=
"context/@@standard_macros/view"
i18n:domain=
"zope"
>
<body>
<div
metal:fill-slot=
"body"
>
<div
metal:define-macro=
"contents"
>
<form
name=
"containerContentsForm"
method=
"post"
action=
"."
tal:attributes=
"action request/URL"
tal:define=
"container_contents view/listContentInfo"
>
<input
type=
"hidden"
name=
"type_name"
value=
""
tal:attributes=
"value request/type_name"
tal:condition=
"request/type_name|nothing"
/>
<input
type=
"hidden"
name=
"retitle_id"
value=
""
tal:attributes=
"value request/retitle_id"
tal:condition=
"request/retitle_id|nothing"
/>
<div
class=
"page_error"
tal:condition=
"view/error"
tal:content=
"view/error"
i18n:translate=
""
>
Error message
</div>
<table
id=
"sortable"
class=
"listing"
summary=
"Content listing"
i18n:attributes=
"summary"
>
<thead>
<tr>
<th><input
type=
"checkbox"
onchange=
"updateCheckboxes(this, 'slaveBox');"
/></th>
<th
i18n:translate=
""
>
Name
</th>
<th
i18n:translate=
""
>
Title
</th>
<th
i18n:translate=
""
>
Size
</th>
<th
i18n:translate=
""
>
Created
</th>
<th
i18n:translate=
""
>
Modified
</th>
</tr>
</thead>
<tbody>
<metal:block
tal:condition=
"view/hasAdding"
>
<tr
tal:define=
"names_required context/@@+/nameAllowed"
tal:condition=
"python:names_required and request.has_key('type_name')"
>
<td></td>
<td><input
name=
"new_value"
id=
"focusid"
value=
""
/></td>
<td></td>
<td></td>
<td></td>
</tr>
</metal:block>
<metal:block
tal:define=
"supportsRename view/supportsRename"
tal:repeat=
"item container_contents"
>
<tr
tal:define=
"oddrow repeat/item/odd; url item/url;
id_quoted item/id/url:quote"
tal:attributes=
"class python:oddrow and 'even' or 'odd'"
>
<td>
<input
type=
"checkbox"
class=
"noborder slaveBox"
name=
"ids:list"
id=
"#"
value=
"#"
tal:attributes=
"value item/id;
id item/cb_id;
checked request/ids_checked|nothing;"
/>
</td>
<td><a
href=
"#"
tal:attributes=
"href
string:${url}/@@SelectedManagementView.html"
tal:content=
"structure item/icon|default"
>
</a
><span
tal:condition=
"item/rename"
><input
name=
"new_value:list"
tal:attributes=
"value item/id"
/><input
type=
"hidden"
name=
"rename_ids:list"
value=
""
tal:attributes=
"value item/rename"
/></span
><span
tal:condition=
"not:item/rename"
>
<a
href=
"#"
tal:attributes=
"href
string:${url}/@@SelectedManagementView.html"
tal:content=
"item/id"
>
foo
</a
><a
href=
"#"
tal:attributes=
"href
string:${request/URL}?rename_ids:list=${id_quoted}"
tal:condition=
"supportsRename"
>
</a
></span
></td>
<td>
<input
name=
"new_value"
id=
"focusid"
tal:attributes=
"value item/title|nothing"
tal:condition=
"item/retitle"
/>
<a
href=
"#"
tal:attributes=
"href
string:${request/URL}?retitle_id=${id_quoted}"
tal:condition=
"item/retitleable"
tal:content=
"item/title|default"
i18n:translate=
""
>
</a>
<span
tal:condition=
"item/plaintitle"
tal:content=
"item/title|default"
i18n:translate=
""
>
</span>
</td>
<td><span
tal:content=
"item/size/sizeForDisplay|nothing"
i18n:translate=
""
>
</span></td>
<td><span
tal:define=
"created item/created|default"
tal:content=
"created"
i18n:translate=
""
>
</span></td>
<td><span
tal:define=
"modified item/modified|default"
tal:content=
"modified"
i18n:translate=
""
>
</span></td>
</tr>
</metal:block>
</tbody>
</table>
<tal:block
tal:condition=
"view/normalButtons"
>
<input
type=
"submit"
name=
"container_rename_button"
value=
"Rename"
i18n:attributes=
"value container-rename-button"
tal:condition=
"view/supportsRename"
/>
<input
type=
"submit"
name=
"container_cut_button"
value=
"Cut"
i18n:attributes=
"value container-cut-button"
tal:condition=
"view/supportsCut"
/>
<input
type=
"submit"
name=
"container_copy_button"
value=
"Copy"
i18n:attributes=
"value container-copy-button"
tal:condition=
"view/supportsCopy"
/>
<input
type=
"submit"
name=
"container_paste_button"
value=
"Paste"
tal:condition=
"view/hasClipboardContents"
i18n:attributes=
"value container-paste-button"
/>
<input
type=
"submit"
name=
"container_delete_button"
value=
"Delete"
i18n:attributes=
"value container-delete-button"
tal:condition=
"view/supportsDelete"
i18n:domain=
"zope"
/>
<div
tal:condition=
"view/hasAdding"
tal:omit-tag=
""
>
<div
tal:omit-tag=
""
tal:define=
"adding nocall:context/@@+;
addingInfo adding/addingInfo;
has_custom_add_view adding/hasCustomAddView;
names_required adding/nameAllowed"
tal:condition=
"adding/isSingleMenuItem"
>
<input
type=
"submit"
name=
"container_add_button"
value=
"Add"
i18n:attributes=
"value add-button"
i18n:domain=
"zope"
/>
<input
type=
"text"
name=
"single_new_value"
id=
"focusid"
tal:condition=
"python:names_required and not has_custom_add_view"
i18n:domain=
"zope"
/>
<input
type=
"hidden"
name=
"single_type_name"
value=
""
tal:attributes=
"value python:addingInfo[0]['action']"
/>
</div>
</div>
</tal:block>
<div
tal:condition=
"view/specialButtons"
>
<input
type=
"submit"
value=
"Apply"
i18n:attributes=
"value container-apply-button"
/>
<input
type=
"submit"
name=
"container_cancel_button"
value=
"Cancel"
i18n:attributes=
"value container-cancel-button"
/>
</div>
</form>
<script
type=
"text/javascript"
>
<!--
if
(
document
.
containerContentsForm
.
new_value
)
document
.
containerContentsForm
.
new_value
.
focus
();
//-->
</script>
</div>
</div>
</body>
</html>
src/zope/container/browser/contents.py
deleted
100644 → 0
View file @
f1f6cc98
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""View Class for the Container's Contents view.
$Id$
"""
__docformat__
=
'restructuredtext'
import
urllib
from
zope.component
import
queryMultiAdapter
from
zope.event
import
notify
from
zope.exceptions.interfaces
import
UserError
from
zope.security.interfaces
import
Unauthorized
from
zope.security
import
canWrite
from
zope.size.interfaces
import
ISized
from
zope.traversing.interfaces
import
TraversalError
from
zope.publisher.browser
import
BrowserView
from
zope.dublincore.interfaces
import
IZopeDublinCore
from
zope.dublincore.interfaces
import
IDCDescriptiveProperties
from
zope.copypastemove.interfaces
import
IPrincipalClipboard
from
zope.copypastemove.interfaces
import
IObjectCopier
,
IObjectMover
from
zope.copypastemove.interfaces
import
IContainerItemRenamer
from
zope.annotation.interfaces
import
IAnnotations
from
zope.lifecycleevent
import
ObjectModifiedEvent
,
Attributes
from
zope.traversing.api
import
getName
,
getPath
,
joinPath
,
traverse
from
zope.app.pagetemplate.viewpagetemplatefile
import
ViewPageTemplateFile
from
zope.app.container.i18n
import
ZopeMessageFactory
as
_
from
zope.app.container.browser.adding
import
Adding
from
zope.app.container.interfaces
import
IContainer
,
DuplicateIDError
from
zope.app.container.interfaces
import
IContainerNamesContainer
class
Contents
(
BrowserView
):
__used_for__
=
IContainer
error
=
''
message
=
''
normalButtons
=
False
specialButtons
=
False
supportsRename
=
False
def
listContentInfo
(
self
):
request
=
self
.
request
if
"container_cancel_button"
in
request
:
if
"type_name"
in
request
:
del
request
.
form
[
'type_name'
]
if
"rename_ids"
in
request
and
"new_value"
in
request
:
del
request
.
form
[
'rename_ids'
]
if
"retitle_id"
in
request
and
"new_value"
in
request
:
del
request
.
form
[
'retitle_id'
]
return
self
.
_normalListContentsInfo
()
elif
"container_rename_button"
in
request
and
not
request
.
get
(
"ids"
):
self
.
error
=
_
(
"You didn't specify any ids to rename."
)
elif
"container_add_button"
in
request
:
if
"single_type_name"
in
request
\
and
"single_new_value"
in
request
:
request
.
form
[
'type_name'
]
=
request
[
'single_type_name'
]
request
.
form
[
'new_value'
]
=
request
[
'single_new_value'
]
self
.
addObject
()
elif
'single_type_name'
in
request
\
and
'single_new_value'
not
in
request
:
request
.
form
[
'type_name'
]
=
request
[
'single_type_name'
]
request
.
form
[
'new_value'
]
=
""
self
.
addObject
()
elif
"type_name"
in
request
and
"new_value"
in
request
:
self
.
addObject
()
elif
"rename_ids"
in
request
and
"new_value"
in
request
:
self
.
renameObjects
()
elif
"retitle_id"
in
request
and
"new_value"
in
request
:
self
.
changeTitle
()
elif
"container_cut_button"
in
request
:
self
.
cutObjects
()
elif
"container_copy_button"
in
request
:
self
.
copyObjects
()
elif
"container_paste_button"
in
request
:
self
.
pasteObjects
()
elif
"container_delete_button"
in
request
:
self
.
removeObjects
()
else
:
return
self
.
_normalListContentsInfo
()
if
self
.
error
:
return
self
.
_normalListContentsInfo
()
status
=
request
.
response
.
getStatus
()
if
status
not
in
(
302
,
303
):
# Only redirect if nothing else has
request
.
response
.
redirect
(
request
.
URL
)
return
()
def
normalListContentInfo
(
self
):
return
self
.
_normalListContentsInfo
()
def
_normalListContentsInfo
(
self
):
request
=
self
.
request
self
.
specialButtons
=
(
'type_name'
in
request
or
'rename_ids'
in
request
or
(
'container_rename_button'
in
request
and
request
.
get
(
"ids"
))
or
'retitle_id'
in
request
)
self
.
normalButtons
=
not
self
.
specialButtons
info
=
map
(
self
.
_extractContentInfo
,
self
.
context
.
items
())
self
.
supportsCut
=
info
self
.
supportsCopy
=
info
self
.
supportsDelete
=
info
self
.
supportsPaste
=
self
.
pasteable
()
self
.
supportsRename
=
(
self
.
supportsCut
and
not
IContainerNamesContainer
.
providedBy
(
self
.
context
)
)
return
info
def
_extractContentInfo
(
self
,
item
):
request
=
self
.
request
rename_ids
=
{}
if
"container_rename_button"
in
request
:
for
rename_id
in
request
.
get
(
'ids'
,
()):
rename_ids
[
rename_id
]
=
rename_id
elif
"rename_ids"
in
request
:
for
rename_id
in
request
.
get
(
'rename_ids'
,
()):
rename_ids
[
rename_id
]
=
rename_id
retitle_id
=
request
.
get
(
'retitle_id'
)
id
,
obj
=
item
info
=
{}
info
[
'id'
]
=
info
[
'cb_id'
]
=
id
info
[
'object'
]
=
obj
info
[
'url'
]
=
urllib
.
quote
(
id
.
encode
(
'utf-8'
))
info
[
'rename'
]
=
rename_ids
.
get
(
id
)
info
[
'retitle'
]
=
id
==
retitle_id
zmi_icon
=
queryMultiAdapter
((
obj
,
self
.
request
),
name
=
'zmi_icon'
)
if
zmi_icon
is
None
:
info
[
'icon'
]
=
None
else
:
info
[
'icon'
]
=
zmi_icon
()
dc
=
IZopeDublinCore
(
obj
,
None
)
if
dc
is
not
None
:
info
[
'retitleable'
]
=
canWrite
(
dc
,
'title'
)
info
[
'plaintitle'
]
=
not
info
[
'retitleable'
]
title
=
self
.
safe_getattr
(
dc
,
'title'
,
None
)
if
title
:
info
[
'title'
]
=
title
formatter
=
self
.
request
.
locale
.
dates
.
getFormatter
(
'dateTime'
,
'short'
)
created
=
self
.
safe_getattr
(
dc
,
'created'
,
None
)
if
created
is
not
None
:
info
[
'created'
]
=
formatter
.
format
(
created
)
modified
=
self
.
safe_getattr
(
dc
,
'modified'
,
None
)
if
modified
is
not
None
:
info
[
'modified'
]
=
formatter
.
format
(
modified
)
else
:
info
[
'retitleable'
]
=
0
info
[
'plaintitle'
]
=
1
sized_adapter
=
ISized
(
obj
,
None
)
if
sized_adapter
is
not
None
:
info
[
'size'
]
=
sized_adapter
return
info
def
safe_getattr
(
self
,
obj
,
attr
,
default
):
"""Attempts to read the attr, returning default if Unauthorized."""
try
:
return
getattr
(
obj
,
attr
,
default
)
except
Unauthorized
:
return
default
def
renameObjects
(
self
):
"""Given a sequence of tuples of old, new ids we rename"""
request
=
self
.
request
ids
=
request
.
get
(
"rename_ids"
)
newids
=
request
.
get
(
"new_value"
)
renamer
=
IContainerItemRenamer
(
self
.
context
)
for
oldid
,
newid
in
zip
(
ids
,
newids
):
if
newid
!=
oldid
:
renamer
.
renameItem
(
oldid
,
newid
)
def
changeTitle
(
self
):
"""Given a sequence of tuples of old, new ids we rename"""
request
=
self
.
request
id
=
request
.
get
(
"retitle_id"
)
new
=
request
.
get
(
"new_value"
)
item
=
self
.
context
[
id
]
dc
=
IDCDescriptiveProperties
(
item
)
dc
.
title
=
new
notify
(
ObjectModifiedEvent
(
item
,
Attributes
(
IZopeDublinCore
,
'title'
)))
def
hasAdding
(
self
):
"""Returns true if an adding view is available."""
adding
=
queryMultiAdapter
((
self
.
context
,
self
.
request
),
name
=
"+"
)
return
(
adding
is
not
None
)
def
addObject
(
self
):
request
=
self
.
request
if
IContainerNamesContainer
.
providedBy
(
self
.
context
):
new
=
""
else
:
new
=
request
[
"new_value"
]
adding
=
queryMultiAdapter
((
self
.
context
,
self
.
request
),
name
=
"+"
)
if
adding
is
None
:
adding
=
Adding
(
self
.
context
,
request
)
else
:
# Set up context so that the adding can build a url
# if the type name names a view.
# Note that we can't so this for the "adding is None" case
# above, because there is no "+" view.
adding
.
__parent__
=
self
.
context
adding
.
__name__
=
'+'
adding
.
action
(
request
[
'type_name'
],
new
)
def
removeObjects
(
self
):
"""Remove objects specified in a list of object ids"""
request
=
self
.
request
ids
=
request
.
get
(
'ids'
)
if
not
ids
:
self
.
error
=
_
(
"You didn't specify any ids to remove."
)
return
container
=
self
.
context
for
id
in
ids
:
del
container
[
id
]
def
copyObjects
(
self
):
"""Copy objects specified in a list of object ids"""
request
=
self
.
request
ids
=
request
.
get
(
'ids'
)
if
not
ids
:
self
.
error
=
_
(
"You didn't specify any ids to copy."
)
return
container_path
=
getPath
(
self
.
context
)
# For each item, check that it can be copied; if so, save the
# path of the object for later copying when a destination has
# been selected; if not copyable, provide an error message
# explaining that the object can't be copied.
items
=
[]
for
id
in
ids
:
ob
=
self
.
context
[
id
]
copier
=
IObjectCopier
(
ob
)
if
not
copier
.
copyable
():
m
=
{
"name"
:
id
}
title
=
getDCTitle
(
ob
)
if
title
:
m
[
"title"
]
=
title
self
.
error
=
_
(
"Object '${name}' (${title}) cannot be copied"
,
mapping
=
m
)
else
:
self
.
error
=
_
(
"Object '${name}' cannot be copied"
,
mapping
=
m
)
return
items
.
append
(
joinPath
(
container_path
,
id
))
# store the requested operation in the principal annotations:
clipboard
=
getPrincipalClipboard
(
self
.
request
)
clipboard
.
clearContents
()
clipboard
.
addItems
(
'copy'
,
items
)
def
cutObjects
(
self
):
"""move objects specified in a list of object ids"""
request
=
self
.
request
ids
=
request
.
get
(
'ids'
)
if
not
ids
:
self
.
error
=
_
(
"You didn't specify any ids to cut."
)
return
container_path
=
getPath
(
self
.
context
)
# For each item, check that it can be moved; if so, save the
# path of the object for later moving when a destination has
# been selected; if not movable, provide an error message
# explaining that the object can't be moved.
items
=
[]
for
id
in
ids
:
ob
=
self
.
context
[
id
]
mover
=
IObjectMover
(
ob
)
if
not
mover
.
moveable
():
m
=
{
"name"
:
id
}
title
=
getDCTitle
(
ob
)
if
title
:
m
[
"title"
]
=
title
self
.
error
=
_
(
"Object '${name}' (${title}) cannot be moved"
,
mapping
=
m
)
else
:
self
.
error
=
_
(
"Object '${name}' cannot be moved"
,
mapping
=
m
)
return
items
.
append
(
joinPath
(
container_path
,
id
))
# store the requested operation in the principal annotations:
clipboard
=
getPrincipalClipboard
(
self
.
request
)
clipboard
.
clearContents
()
clipboard
.
addItems
(
'cut'
,
items
)
def
pasteable
(
self
):
"""Decide if there is anything to paste
"""
target
=
self
.
context
clipboard
=
getPrincipalClipboard
(
self
.
request
)
items
=
clipboard
.
getContents
()
for
item
in
items
:
try
:
obj
=
traverse
(
target
,
item
[
'target'
])
except
TraversalError
:
pass
else
:
if
item
[
'action'
]
==
'cut'
:
mover
=
IObjectMover
(
obj
)
moveableTo
=
self
.
safe_getattr
(
mover
,
'moveableTo'
,
None
)
if
moveableTo
is
None
or
not
moveableTo
(
target
):
return
False
elif
item
[
'action'
]
==
'copy'
:
copier
=
IObjectCopier
(
obj
)
copyableTo
=
self
.
safe_getattr
(
copier
,
'copyableTo'
,
None
)
if
copyableTo
is
None
or
not
copyableTo
(
target
):
return
False
else
:
raise
return
True
def
pasteObjects
(
self
):
"""Paste ojects in the user clipboard to the container
"""
target
=
self
.
context
clipboard
=
getPrincipalClipboard
(
self
.
request
)
items
=
clipboard
.
getContents
()
moved
=
False
not_pasteable_ids
=
[]
for
item
in
items
:
duplicated_id
=
False
try
:
obj
=
traverse
(
target
,
item
[
'target'
])
except
TraversalError
:
pass
else
:
if
item
[
'action'
]
==
'cut'
:
mover
=
IObjectMover
(
obj
)
try
:
mover
.
moveTo
(
target
)
moved
=
True
except
DuplicateIDError
:
duplicated_id
=
True
elif
item
[
'action'
]
==
'copy'
:
copier
=
IObjectCopier
(
obj
)
try
:
copier
.
copyTo
(
target
)
except
DuplicateIDError
:
duplicated_id
=
True
else
:
raise
if
duplicated_id
:
not_pasteable_ids
.
append
(
getName
(
obj
))
if
moved
:
# Clear the clipboard if we do a move, but not if we only do a copy
clipboard
.
clearContents
()
if
not_pasteable_ids
!=
[]:
# Show the ids of objects that can't be pasted because
# their ids are already taken.
# TODO Can't we add a 'copy_of' or something as a prefix
# instead of raising an exception ?
raise
UserError
(
_
(
"The given name(s) %s is / are already being used"
%
(
str
(
not_pasteable_ids
))))
def
hasClipboardContents
(
self
):
"""Interogate the ``PrinicipalAnnotation`` to see if clipboard
contents exist."""
if
not
self
.
supportsPaste
:
return
False
# touch at least one item to in clipboard confirm contents
clipboard
=
getPrincipalClipboard
(
self
.
request
)
items
=
clipboard
.
getContents
()
for
item
in
items
:
try
:
traverse
(
self
.
context
,
item
[
'target'
])
except
TraversalError
:
pass
else
:
return
True
return
False
contents
=
ViewPageTemplateFile
(
'contents.pt'
)
contentsMacros
=
contents
_index
=
ViewPageTemplateFile
(
'index.pt'
)
def
index
(
self
):
if
'index.html'
in
self
.
context
:
self
.
request
.
response
.
redirect
(
'index.html'
)
return
''
return
self
.
_index
()
class
JustContents
(
Contents
):
"""Like Contents, but does't delegate to item named index.html"""
def
index
(
self
):
return
self
.
_index
()
def
getDCTitle
(
ob
):
dc
=
IDCDescriptiveProperties
(
ob
,
None
)
if
dc
is
None
:
return
None
else
:
return
dc
.
title
def
getPrincipalClipboard
(
request
):
"""Return the clipboard based on the request."""
user
=
request
.
principal
annotations
=
IAnnotations
(
user
)
return
IPrincipalClipboard
(
annotations
)
src/zope/container/browser/find.pt
deleted
100644 → 0
View file @
f1f6cc98
<html
metal:use-macro=
"context/@@standard_macros/dialog"
i18n:domain=
"zope"
>
<body>
<div
metal:fill-slot=
"body"
>
<form
action=
"@@find.html"
method=
"get"
>
<input
type=
"text"
name=
"ids"
value=
""
/><br
/>
<input
type=
"submit"
name=
"find_submit"
value=
" Find "
i18n:attributes=
"value find-button"
/>
</form>
<table
tal:condition=
"request/ids|nothing"
>
<tr
tal:repeat=
"item python:view.findByIds(request['ids'])"
>
<td>
<a
href=
""
tal:attributes=
"href item/url"
tal:content=
"item/id"
>
id
</a>
</td>
</tr>
</table>
</div>
</body>
</html>
src/zope/container/browser/find.py
deleted
100644 → 0
View file @
f1f6cc98
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Find View Class
$Id$
"""
__docformat__
=
'restructuredtext'
from
zope.traversing.api
import
getName
from
zope.traversing.browser.absoluteurl
import
absoluteURL
from
zope.publisher.browser
import
BrowserView
from
zope.app.container.find
import
SimpleIdFindFilter
from
zope.app.container.interfaces
import
IFind
# Very simple implementation right now
class
Find
(
BrowserView
):
def
findByIds
(
self
,
ids
):
"""Do a find for the `ids` listed in `ids`, which is a string."""
finder
=
IFind
(
self
.
context
)
ids
=
ids
.
split
()
# if we don't have any ids listed, don't search at all
if
not
ids
:
return
[]
request
=
self
.
request
result
=
[]
for
object
in
finder
.
find
([
SimpleIdFindFilter
(
ids
)]):
url
=
absoluteURL
(
object
,
request
)
result
.
append
({
'id'
:
getName
(
object
),
'url'
:
url
})
return
result
src/zope/container/browser/index.pt
deleted
100644 → 0
View file @
f1f6cc98
<html
metal:use-macro=
"context/@@standard_macros/page"
i18n:domain=
"zope"
>
<head>
<style
metal:fill-slot=
"headers"
type=
"text/css"
>
<!
--
.ContentIcon
{
width
:
20px
;
}
.ContentTitle
{
text-align
:
left
;
}
--
>
</style>
</head>
<body>
<div
metal:fill-slot=
"body"
>
<table
id=
"sortable"
class=
"listing"
summary=
"Content listing"
cellpadding=
"2"
cellspacing=
"0"
i18n:attributes=
"summary"
>
<thead>
<tr>
<th>
</th>
<th
i18n:translate=
""
>
Name
</th>
<th
i18n:translate=
""
>
Title
</th>
<th
i18n:translate=
""
>
Created
</th>
<th
i18n:translate=
""
>
Modified
</th>
</tr>
</thead>
<tbody>
<tr
tal:repeat=
"info view/listContentInfo"
>
<td>
<a
href=
"#"
tal:attributes=
"href info/url"
tal:content=
"structure info/icon|default"
/>
</td>
<td
class=
"ContentTitle"
>
<a
href=
"subfolder_id"
tal:attributes=
"href info/url"
tal:content=
"info/id"
i18n:translate=
""
>
ID here
</a>
</td>
<td><span
tal:content=
"info/title|default"
i18n:translate=
""
>
</span></td>
<td><span
tal:content=
"info/created|default"
i18n:translate=
""
>
</span></td>
<td><span
tal:content=
"info/modified|default"
i18n:translate=
""
>
</span></td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
src/zope/container/browser/meta.zcml
deleted
100644 → 0
View file @
f1f6cc98
<configure
xmlns="http://namespaces.zope.org/zope"
xmlns:meta="http://namespaces.zope.org/meta">
<meta:directives namespace="http://namespaces.zope.org/browser">
<!-- browser cotainer views -->
<meta:directive
name="containerViews"
schema=".metaconfigure.IContainerViews"
handler=".metaconfigure.containerViews"
/>
</meta:directives>
</configure>
\ No newline at end of file
src/zope/container/browser/metaconfigure.py
deleted
100644 → 0
View file @
f1f6cc98
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Container-specific browser ZCML namespace directive handlers
$Id$
"""
__docformat__
=
'restructuredtext'
from
zope.interface
import
Interface
from
zope.configuration.fields
import
GlobalObject
,
GlobalInterface
from
zope.publisher.interfaces.browser
import
IDefaultBrowserLayer
from
zope.schema
import
Id
from
zope.security.zcml
import
Permission
from
zope.app.publisher.browser.viewmeta
import
page
,
view
from
zope.app.container.browser.contents
import
Contents
from
zope.app.container.browser.adding
import
Adding
from
zope.app.container.i18n
import
ZopeMessageFactory
as
_
class
IContainerViews
(
Interface
):
"""Define several container views for an `IContainer` implementation."""
for_
=
GlobalObject
(
title
=
u"The declaration this containerViews are for."
,
description
=
u"""
The containerViews will be available for all objects that
provide this declaration.
"""
,
required
=
True
)
contents
=
Permission
(
title
=
u"The permission needed for content page."
,
required
=
False
)
index
=
Permission
(
title
=
u"The permission needed for index page."
,
required
=
False
)
add
=
Permission
(
title
=
u"The permission needed for add page."
,
required
=
False
)
layer
=
GlobalInterface
(
title
=
_
(
"The layer the view is in."
),
description
=
_
(
"""A skin is composed of layers. It is common to put
skin specific views in a layer named after the skin. If the 'layer'
attribute is not supplied, it defaults to 'default'."""
),
required
=
False
)
def
containerViews
(
_context
,
for_
,
contents
=
None
,
add
=
None
,
index
=
None
,
layer
=
IDefaultBrowserLayer
):
"""Set up container views for a given content type."""
if
for_
is
None
:
raise
ValueError
(
"A for interface must be specified."
)
if
contents
is
not
None
:
from
zope.app.menus
import
zmi_views
page
(
_context
,
name
=
'contents.html'
,
permission
=
contents
,
for_
=
for_
,
layer
=
layer
,
class_
=
Contents
,
attribute
=
'contents'
,
menu
=
zmi_views
,
title
=
_
(
'Contents'
))
if
index
is
not
None
:
page
(
_context
,
name
=
'index.html'
,
permission
=
index
,
for_
=
for_
,
layer
=
layer
,
class_
=
Contents
,
attribute
=
'index'
)
if
add
is
not
None
:
from
zope.app.menus
import
zmi_actions
viewObj
=
view
(
_context
,
name
=
'+'
,
layer
=
layer
,
menu
=
zmi_actions
,
title
=
_
(
'Add'
),
for_
=
for_
,
permission
=
add
,
class_
=
Adding
)
viewObj
.
page
(
_context
,
name
=
'index.html'
,
attribute
=
'index'
)
viewObj
.
page
(
_context
,
name
=
'action.html'
,
attribute
=
'action'
)
viewObj
()
src/zope/container/browser/tests/__init__.py
deleted
100644 → 0
View file @
f1f6cc98
#
# This file is necessary to make this directory a package.
src/zope/container/browser/tests/configure.zcml
deleted
100644 → 0
View file @
f1f6cc98
<configure
xmlns="http://namespaces.zope.org/zope"
xmlns:browser="http://namespaces.zope.org/browser">
<class class=".test_contents_functional.ReadOnlyContainer">
<require
permission="zope.ManageContent"
interface="zope.app.container.interfaces.IReadContainer"
/>
</class>
<browser:containerViews
for="zope.app.container.interfaces.IReadContainer"
contents="zope.ManageContent" />
</configure>
src/zope/container/browser/tests/index.txt
deleted
100644 → 0
View file @
f1f6cc98
The containerViews directive lets us associate some standard forms
for containers with an interface. There's an "index.html" view that
provides a listing of the contained objects without provinding any way
to manage them (though it allows us to visit them by clicking on
links).
We can get this view from the root folder easily::
>>> response = http(r"""
... GET / HTTP/1.1
... """)
And we can check that there isn't a form (where the management
operations would have buttons)::
>>> body = response.getBody().lower()
>>> "<form" in body
False
src/zope/container/browser/tests/test_adding.py
deleted
100644 → 0
View file @
f1f6cc98
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Adding implementation tests
$Id$
"""
import
unittest
import
zope.interface
import
zope.security.checker
from
zope.component.interfaces
import
IFactory
from
zope.component.interfaces
import
ComponentLookupError
from
zope.interface
import
implements
,
Interface
,
directlyProvides
from
zope.publisher.browser
import
TestRequest
from
zope.publisher.interfaces.browser
import
IBrowserRequest
from
zope.publisher.browser
import
BrowserView
from
zope.security.interfaces
import
ForbiddenAttribute
from
zope.testing.doctestunit
import
DocTestSuite
from
zope.exceptions.interfaces
import
UserError
from
zope.traversing.api
import
getParent
from
zope.traversing.browser
import
AbsoluteURL
from
zope.traversing.browser.absoluteurl
import
absoluteURL
from
zope.traversing.browser.interfaces
import
IAbsoluteURL
from
zope.traversing.interfaces
import
IContainmentRoot
from
zope.app.testing
import
ztapi
from
zope.app.testing.placelesssetup
import
PlacelessSetup
,
setUp
,
tearDown
from
zope.app.publisher.interfaces.browser
import
AddMenu
from
zope.app.publisher.interfaces.browser
import
IMenuItemType
,
IBrowserMenu
from
zope.app.publisher.browser.menu
import
BrowserMenuItem
,
BrowserMenu
from
zope.app.container.interfaces
import
IAdding
from
zope.app.container.interfaces
import
IObjectAddedEvent
from
zope.app.container.interfaces
import
IContainerNamesContainer
from
zope.app.container.interfaces
import
INameChooser
from
zope.app.container.interfaces
import
IContainer
from
zope.app.container.contained
import
contained
from
zope.app.container.browser.adding
import
Adding
from
zope.app.container.sample
import
SampleContainer
class
Root
(
object
):
implements
(
IContainmentRoot
)
class
Container
(
SampleContainer
):
pass
class
CreationView
(
BrowserView
):
def
action
(
self
):
return
'been there, done that'
class
Content
(
object
):
pass
class
Factory
(
object
):
implements
(
IFactory
)
title
=
''
description
=
''
def
getInterfaces
(
self
):
return
()
def
__call__
(
self
):
return
Content
()
class
AbsoluteURL
(
BrowserView
):
def
__str__
(
self
):
if
IContainmentRoot
.
providedBy
(
self
.
context
):
return
''
name
=
self
.
context
.
__name__
url
=
absoluteURL
(
getParent
(
self
.
context
),
self
.
request
)
url
+=
'/'
+
name
return
url
__call__
=
__str__
def
defineMenuItem
(
menuItemType
,
for_
,
action
,
title
=
u''
,
extra
=
None
):
newclass
=
type
(
title
,
(
BrowserMenuItem
,),
{
'title'
:
title
,
'action'
:
action
,
'_for'
:
for_
,
'extra'
:
extra
})
zope
.
interface
.
classImplements
(
newclass
,
menuItemType
)
ztapi
.
provideAdapter
((
for_
,
IBrowserRequest
),
menuItemType
,
newclass
,
title
)
def
registerAddMenu
():
ztapi
.
provideUtility
(
IMenuItemType
,
AddMenu
,
'zope.app.container.add'
)
ztapi
.
provideUtility
(
IBrowserMenu
,
BrowserMenu
(
'zope.app.container.add'
,
u''
,
u''
),
'zope.app.container.add'
)
class
Test
(
PlacelessSetup
,
unittest
.
TestCase
):
def
setUp
(
self
):
super
(
Test
,
self
).
setUp
()
def
test
(
self
):
container
=
Container
()
request
=
TestRequest
()
adding
=
Adding
(
container
,
request
)
ztapi
.
browserView
(
IAdding
,
"Thing"
,
CreationView
)
self
.
assertEqual
(
adding
.
contentName
,
None
)
view
=
adding
.
publishTraverse
(
request
,
'Thing=foo'
)
self
.
assertEqual
(
view
.
action
(),
'been there, done that'
)
self
.
assertEqual
(
adding
.
contentName
,
'foo'
)
o
=
object
()
result
=
adding
.
add
(
o
)
# Check the state of the container and result
self
.
assertEqual
(
container
[
"foo"
],
o
)
self
.
assertEqual
(
result
,
o
)
def
testNoNameGiven
(
self
):
container
=
Container
()
request
=
TestRequest
()
adding
=
Adding
(
container
,
request
)
ztapi
.
browserView
(
IAdding
,
"Thing"
,
CreationView
)
self
.
assertEqual
(
adding
.
contentName
,
None
)
view
=
adding
.
publishTraverse
(
request
,
'Thing='
)
self
.
assertEqual
(
adding
.
contentName
,
''
)
def
testAction
(
self
):
# make a private factory
ztapi
.
provideUtility
(
IFactory
,
Factory
(),
'fooprivate'
)
factory
=
Factory
()
factory
.
__Security_checker__
=
zope
.
security
.
checker
.
NamesChecker
(
[
'__call__'
])
ztapi
.
provideUtility
(
IFactory
,
factory
,
'foo'
)
container
=
Container
()
adding
=
Adding
(
container
,
TestRequest
())
adding
.
nextURL
=
lambda
:
'.'
adding
.
nameAllowed
=
lambda
:
True
# we can't use a private factory:
self
.
assertRaises
(
ForbiddenAttribute
,
adding
.
action
,
type_name
=
'fooprivate'
,
id
=
'bar'
)
# typical add - id is provided by user
adding
.
action
(
type_name
=
'foo'
,
id
=
'bar'
)
self
.
assert_
(
'bar'
in
container
)
# missing type_name
self
.
assertRaises
(
UserError
,
adding
.
action
,
id
=
'bar'
)
# missing id
self
.
assertRaises
(
UserError
,
adding
.
action
,
type_name
=
'foo'
)
# bad type_name
self
.
assertRaises
(
ComponentLookupError
,
adding
.
action
,
type_name
=
'***'
,
id
=
'bar'
)
# alternative add - id is provided internally instead of from user
adding
.
nameAllowed
=
lambda
:
False
adding
.
contentName
=
'baz'
adding
.
action
(
type_name
=
'foo'
)
self
.
assert_
(
'baz'
in
container
)
# alternative add w/missing contentName
# Note: Passing is None as object name might be okay, if the container
# is able to hand out ids itself. Let's not require a content
# name to be specified!
# For the container, (or really, the chooser, to choose, we have to
# marke the container as a ContainerNamesContainer
directlyProvides
(
container
,
IContainerNamesContainer
)
adding
.
contentName
=
None
adding
.
action
(
type_name
=
'foo'
)
self
.
assert_
(
'Content'
in
container
)
def
test_action
(
self
):
container
=
Container
()
container
=
contained
(
container
,
Root
(),
"container"
)
request
=
TestRequest
()
adding
=
Adding
(
container
,
request
)
adding
.
__name__
=
'+'
ztapi
.
browserView
(
IAdding
,
"Thing"
,
CreationView
)
ztapi
.
browserView
(
Interface
,
"absolute_url"
,
AbsoluteURL
)
ztapi
.
browserView
(
None
,
''
,
AbsoluteURL
,
providing
=
IAbsoluteURL
)
self
.
assertRaises
(
UserError
,
adding
.
action
,
''
,
'foo'
)
adding
.
action
(
'Thing'
,
'foo'
)
self
.
assertEqual
(
adding
.
request
.
response
.
getHeader
(
'location'
),
'/container/+/Thing=foo'
)
adding
.
action
(
'Thing/screen1'
,
'foo'
)
self
.
assertEqual
(
adding
.
request
.
response
.
getHeader
(
'location'
),
'/container/+/Thing/screen1=foo'
)
def
test_publishTraverse_factory
(
self
):
factory
=
Factory
()
ztapi
.
provideUtility
(
IFactory
,
factory
,
'foo'
)
container
=
Container
()
request
=
TestRequest
()
adding
=
Adding
(
container
,
request
)
self
.
assert_
(
adding
.
publishTraverse
(
request
,
'foo'
)
is
factory
)
def
test_constraint_driven_addingInfo
():
"""
>>> registerAddMenu()
>>> class TestMenu(zope.interface.Interface):
... pass
>>> zope.interface.directlyProvides(TestMenu, IMenuItemType)
>>> ztapi.provideUtility(IMenuItemType, TestMenu, 'TestMenu')
>>> ztapi.provideUtility(IBrowserMenu, BrowserMenu('TestMenu', u'', u''),
... 'TestMenu')
>>> defineMenuItem(TestMenu, IAdding, '', 'item1')
>>> defineMenuItem(TestMenu, IAdding, '', 'Item2')
>>> defineMenuItem(AddMenu, IAdding, '', 'item3', extra={'factory': 'f1'})
>>> defineMenuItem(AddMenu, IAdding, '', 'item4', extra={'factory': 'f2'})
>>> class F1(object):
... pass
>>> class F2(object):
... pass
>>> def pre(container, name, object):
... if not isinstance(object, F1):
... raise zope.interface.Invalid()
>>> def prefactory(container, name, factory):
... if factory._callable is not F1:
... raise zope.interface.Invalid()
>>> pre.factory = prefactory
>>> class IContainer(zope.interface.Interface):
... def __setitem__(name, object):
... pass
... __setitem__.precondition = pre
>>> class Container(object):
... zope.interface.implements(IContainer)
>>> from zope.component.factory import Factory
>>> ztapi.provideUtility(IFactory, Factory(F1), 'f1')
>>> ztapi.provideUtility(IFactory, Factory(F2), 'f2')
>>> from zope.app.container.browser.adding import Adding
>>> adding = Adding(Container(), TestRequest())
>>> items = adding.addingInfo()
>>> len(items)
1
>>> items[0]['title']
u'item3'
>>> adding.menu_id = 'TestMenu'
>>> items = adding.addingInfo()
>>> len(items)
3
>>> items[0]['title']
u'item1'
>>> items[1]['title'] # the collator ordered this one correctly!
u'Item2'
>>> items[2]['title']
u'item3'
"""
def
test_constraint_driven_add
():
"""
>>> from zope.app.container.sample import SampleContainer
>>> from zope.app.container.browser.adding import Adding
>>> class F1(object):
... pass
>>> class F2(object):
... pass
>>> def pre(container, name, object):
... "a mock item constraint "
... if not isinstance(object, F1):
... raise zope.interface.Invalid('not a valid child')
>>> class ITestContainer(zope.interface.Interface):
... def __setitem__(name, object):
... pass
... __setitem__.precondition = pre
>>> class Container(SampleContainer):
... zope.interface.implements(ITestContainer)
>>> adding = Adding(Container(), TestRequest())
>>> c = adding.add(F1())
This test should fail, because the container only
accepts instances of F1
>>> adding.add(F2())
Traceback (most recent call last):
...
Invalid: not a valid child
>>> class ValidContainer(SampleContainer):
... zope.interface.implements(ITestContainer)
>>> def constr(container):
... "a mock container constraint"
... if not isinstance(container, ValidContainer):
... raise zope.interface.Invalid('not a valid container')
... return True
>>> class I2(zope.interface.Interface):
... __parent__ = zope.schema.Field(constraint = constr)
>>> zope.interface.classImplements(F1, I2)
This adding now fails, because the Container is not a valid
parent for F1
>>> c = adding.add(F1())
Traceback (most recent call last):
...
Invalid: not a valid container
>>> adding = Adding(ValidContainer(), TestRequest())
>>> c = adding.add(F1())
"""
def
test_nameAllowed
():
"""
Test for nameAllowed in adding.py
>>> from zope.app.container.browser.adding import Adding
>>> from zope.app.container.interfaces import IContainerNamesContainer
Class implements IContainerNamesContainer
>>> class FakeContainer(object):
... zope.interface.implements(IContainerNamesContainer)
nameAllowed returns False if the class imlements
IContainerNamesContainer
>>> adding = Adding(FakeContainer(),TestRequest())
>>> adding.nameAllowed()
False
Fake class without IContainerNamesContainer
>>> class Fake(object):
... pass
nameAllowed returns True if the class
doesn't imlement IContainerNamesContainer
>>> adding = Adding(Fake(),TestRequest())
>>> adding.nameAllowed()
True
"""
def
test_chooseName
():
"""If user don't enter name, pick one
>>> class MyContainer(object):
... args = {}
... zope.interface.implements(INameChooser, IContainer)
... def chooseName(self, name, object):
... self.args["choose"] = name, object
... return 'pickone'
... def checkName(self, name, object):
... self.args["check"] = name, object
... def __setitem__(self, name, object):
... setattr(self, name, object)
... self.name = name
... def __getitem__(self, key):
... return getattr(self, key)
>>> request = TestRequest()
>>> mycontainer = MyContainer()
>>> adding = Adding(mycontainer, request)
>>> o = object()
>>> add_obj = adding.add(o)
>>> mycontainer.name
'pickone'
>>> add_obj is o
True
Make sure right arguments passed to INameChooser adapter:
>>> name, obj = mycontainer.args["choose"]
>>> name
''
>>> obj is o
True
>>> name, obj = mycontainer.args["check"]
>>> name
'pickone'
>>> obj is o
True
"""
def
test_SingleMenuItem_and_CustomAddView_NonICNC
():
"""
This tests the condition if the content has Custom Add views and
the container contains only a single content object
>>> registerAddMenu()
>>> defineMenuItem(AddMenu, IAdding, '', 'item3', extra={'factory': 'f1'})
>>> class F1(object):
... pass
>>> class F2(object):
... pass
>>> def pre(container, name, object):
... if not isinstance(object, F1):
... raise zope.interface.Invalid()
>>> def prefactory(container, name, factory):
... if factory._callable is not F1:
... raise zope.interface.Invalid()
>>> pre.factory = prefactory
>>> class IContainer(zope.interface.Interface):
... def __setitem__(name, object):
... pass
... __setitem__.precondition = pre
>>> class Container(object):
... zope.interface.implements(IContainer)
>>> from zope.component.factory import Factory
>>> ztapi.provideUtility(IFactory, Factory(F1), 'f1')
>>> ztapi.provideUtility(IFactory, Factory(F2), 'f2')
>>> from zope.app.container.browser.adding import Adding
>>> adding = Adding(Container(), TestRequest())
>>> items = adding.addingInfo()
>>> len(items)
1
isSingleMenuItem returns True if there is only one content class
inside the Container
>>> adding.isSingleMenuItem()
True
hasCustomAddView will return False as the content does not have
a custom Add View
>>> adding.hasCustomAddView()
True
"""
def
test_SingleMenuItem_and_NoCustomAddView_NonICNC
():
"""
This function checks the case where there is a single content object
and there is non custom add view . Also the container does not
implement IContainerNamesContainer
>>> registerAddMenu()
>>> defineMenuItem(AddMenu, None, '', 'item3', extra={'factory': ''})
>>> class F1(object):
... pass
>>> class F2(object):
... pass
>>> def pre(container, name, object):
... if not isinstance(object, F1):
... raise zope.interface.Invalid()
>>> def prefactory(container, name, factory):
... if factory._callable is not F1:
... raise zope.interface.Invalid()
>>> pre.factory = prefactory
>>> class IContainer(zope.interface.Interface):
... def __setitem__(name, object):
... pass
... __setitem__.precondition = pre
>>> class Container(object):
... zope.interface.implements(IContainer)
>>> from zope.component.factory import Factory
>>> ztapi.provideUtility(IFactory, Factory(F1), 'f1')
>>> ztapi.provideUtility(IFactory, Factory(F2), 'f2')
>>> from zope.app.container.browser.adding import Adding
>>> adding = Adding(Container(), TestRequest())
>>> items = adding.addingInfo()
>>> len(items)
1
The isSingleMenuItem will return True if there is one single content
that can be added inside the Container
>>> adding.isSingleMenuItem()
True
hasCustomAddView will return False as the content does not have
a custom Add View
>>> adding.hasCustomAddView()
False
"""
def
test_isSingleMenuItem_with_ICNC
():
"""
This test checks for whether there is a single content that can be added
and the container uses IContainerNamesContaienr
>>> registerAddMenu()
>>> defineMenuItem(AddMenu, None, '', 'item3', extra={'factory': ''})
>>> class F1(object):
... pass
>>> class F2(object):
... pass
>>> def pre(container, name, object):
... if not isinstance(object, F1):
... raise zope.interface.Invalid()
>>> def prefactory(container, name, factory):
... if factory._callable is not F1:
... raise zope.interface.Invalid()
>>> pre.factory = prefactory
>>> class IContainer(zope.interface.Interface):
... def __setitem__(name, object):
... pass
... __setitem__.precondition = pre
>>> class Container(object):
... zope.interface.implements(IContainer, IContainerNamesContainer)
>>> from zope.app.container.browser.adding import Adding
>>> adding = Adding(Container(), TestRequest())
>>> items = adding.addingInfo()
>>> len(items)
1
>>> adding.isSingleMenuItem()
True
>>> adding.hasCustomAddView()
False
"""
def
test_suite
():
return
unittest
.
TestSuite
((
unittest
.
makeSuite
(
Test
),
DocTestSuite
(
setUp
=
setUp
,
tearDown
=
tearDown
),
))
if
__name__
==
'__main__'
:
unittest
.
main
(
defaultTest
=
'test_suite'
)
src/zope/container/browser/tests/test_contents.py
deleted
100644 → 0
View file @
f1f6cc98
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Test Container Contents
$Id$
"""
from
unittest
import
TestCase
,
TestSuite
,
main
,
makeSuite
from
zope.interface
import
Interface
,
implements
from
zope.security
import
checker
from
zope.traversing.api
import
traverse
from
zope.component.eventtesting
import
getEvents
from
zope.annotation.interfaces
import
IAnnotations
from
zope.copypastemove
import
ContainerItemRenamer
from
zope.copypastemove
import
ObjectMover
,
ObjectCopier
from
zope.copypastemove
import
PrincipalClipboard
from
zope.copypastemove.interfaces
import
IContainerItemRenamer
from
zope.copypastemove.interfaces
import
IObjectMover
,
IObjectCopier
from
zope.copypastemove.interfaces
import
IPrincipalClipboard
from
zope.app.component.testing
import
PlacefulSetup
from
zope.app.container.contained
import
contained
from
zope.app.testing
import
ztapi
from
zope.app.container.interfaces
import
IContainer
,
IContained
class
BaseTestContentsBrowserView
(
PlacefulSetup
):
"""Base class for testing browser contents.
Subclasses need to define a method, '_TestView__newContext', that
takes no arguments and that returns a new empty test view context.
Subclasses need to define a method, '_TestView__newView', that
takes a context object and that returns a new test view.
"""
def
setUp
(
self
):
PlacefulSetup
.
setUp
(
self
)
PlacefulSetup
.
buildFolders
(
self
)
ztapi
.
provideAdapter
(
IContained
,
IObjectCopier
,
ObjectCopier
)
ztapi
.
provideAdapter
(
IContained
,
IObjectMover
,
ObjectMover
)
ztapi
.
provideAdapter
(
IContainer
,
IContainerItemRenamer
,
ContainerItemRenamer
)
ztapi
.
provideAdapter
(
IAnnotations
,
IPrincipalClipboard
,
PrincipalClipboard
)
ztapi
.
provideAdapter
(
Principal
,
IAnnotations
,
PrincipalAnnotations
)
def
testInfo
(
self
):
# Do we get the correct information back from ContainerContents?
container
=
self
.
_TestView__newContext
()
subcontainer
=
self
.
_TestView__newContext
()
container
[
'subcontainer'
]
=
subcontainer
document
=
Document
()
container
[
'document'
]
=
document
fc
=
self
.
_TestView__newView
(
container
)
info_list
=
fc
.
listContentInfo
()
self
.
assertEquals
(
len
(
info_list
),
2
)
ids
=
map
(
lambda
x
:
x
[
'id'
],
info_list
)
self
.
assert_
(
'subcontainer'
in
ids
)
objects
=
map
(
lambda
x
:
x
[
'object'
],
info_list
)
self
.
assert_
(
subcontainer
in
objects
)
urls
=
map
(
lambda
x
:
x
[
'url'
],
info_list
)
self
.
assert_
(
'subcontainer'
in
urls
)
self
.
failIf
(
filter
(
None
,
map
(
lambda
x
:
x
[
'icon'
],
info_list
)))
def
testInfoUnicode
(
self
):
# If the id contains non-ASCII characters, url has to be quoted
container
=
self
.
_TestView__newContext
()
subcontainer
=
self
.
_TestView__newContext
()
container
[
u'f
\
xf6
\
xf6
'
]
=
subcontainer
fc
=
self
.
_TestView__newView
(
container
)
info_list
=
fc
.
listContentInfo
()
urls
=
map
(
lambda
x
:
x
[
'url'
],
info_list
)
self
.
assert_
(
'f%C3%B6%C3%B6'
in
urls
)
def
testInfoWDublinCore
(
self
):
container
=
self
.
_TestView__newContext
()
document
=
Document
()
container
[
'document'
]
=
document
from
datetime
import
datetime
from
zope.dublincore.interfaces
import
IZopeDublinCore
class
FauxDCAdapter
(
object
):
implements
(
IZopeDublinCore
)
__Security_checker__
=
checker
.
Checker
(
{
"created"
:
"zope.Public"
,
"modified"
:
"zope.Public"
,
"title"
:
"zope.Public"
,
},
{
"title"
:
"zope.app.dublincore.change"
})
def
__init__
(
self
,
context
):
pass
title
=
'faux title'
size
=
1024
created
=
datetime
(
2001
,
1
,
1
,
1
,
1
,
1
)
modified
=
datetime
(
2002
,
2
,
2
,
2
,
2
,
2
)
ztapi
.
provideAdapter
(
IDocument
,
IZopeDublinCore
,
FauxDCAdapter
)
fc
=
self
.
_TestView__newView
(
container
)
info
=
fc
.
listContentInfo
()[
0
]
self
.
assertEqual
(
info
[
'id'
],
'document'
)
self
.
assertEqual
(
info
[
'url'
],
'document'
)
self
.
assertEqual
(
info
[
'object'
],
document
)
self
.
assertEqual
(
info
[
'title'
],
'faux title'
)
self
.
assertEqual
(
info
[
'created'
],
'01/01/01 01:01'
)
self
.
assertEqual
(
info
[
'modified'
],
'02/02/02 02:02'
)
def
testRemove
(
self
):
container
=
self
.
_TestView__newContext
()
subcontainer
=
self
.
_TestView__newContext
()
container
[
'subcontainer'
]
=
subcontainer
document
=
Document
()
container
[
'document'
]
=
document
document2
=
Document
()
container
[
'document2'
]
=
document2
fc
=
self
.
_TestView__newView
(
container
)
fc
.
request
.
form
.
update
({
'ids'
:
[
'document2'
]})
fc
.
removeObjects
()
info_list
=
fc
.
listContentInfo
()
self
.
assertEquals
(
len
(
info_list
),
2
)
ids
=
map
(
lambda
x
:
x
[
'id'
],
info_list
)
self
.
assert_
(
'subcontainer'
in
ids
)
objects
=
map
(
lambda
x
:
x
[
'object'
],
info_list
)
self
.
assert_
(
subcontainer
in
objects
)
urls
=
map
(
lambda
x
:
x
[
'url'
],
info_list
)
self
.
assert_
(
'subcontainer'
in
urls
)
def
testChangeTitle
(
self
):
container
=
self
.
_TestView__newContext
()
document
=
Document
()
container
[
'document'
]
=
document
from
zope.dublincore.interfaces
import
IDCDescriptiveProperties
class
FauxDCDescriptiveProperties
(
object
):
implements
(
IDCDescriptiveProperties
)
__Security_checker__
=
checker
.
Checker
(
{
"title"
:
"zope.Public"
,
},
{
"title"
:
"zope.app.dublincore.change"
})
def
__init__
(
self
,
context
):
self
.
context
=
context
def
setTitle
(
self
,
title
):
self
.
context
.
title
=
title
def
getTitle
(
self
):
return
self
.
context
.
title
title
=
property
(
getTitle
,
setTitle
)
ztapi
.
provideAdapter
(
IDocument
,
IDCDescriptiveProperties
,
FauxDCDescriptiveProperties
)
fc
=
self
.
_TestView__newView
(
container
)
dc
=
IDCDescriptiveProperties
(
document
)
fc
.
request
.
form
.
update
({
'retitle_id'
:
'document'
,
'new_value'
:
'new'
})
fc
.
changeTitle
()
events
=
getEvents
()
self
.
assertEquals
(
dc
.
title
,
'new'
)
self
.
failIf
(
'title'
not
in
events
[
-
1
].
descriptions
[
0
].
attributes
)
class
IDocument
(
Interface
):
pass
class
Document
(
object
):
implements
(
IDocument
)
class
Principal
(
object
):
id
=
'bob'
class
PrincipalAnnotations
(
dict
):
implements
(
IAnnotations
)
data
=
{}
def
__new__
(
class_
,
context
):
try
:
annotations
=
class_
.
data
[
context
.
id
]
except
KeyError
:
annotations
=
dict
.
__new__
(
class_
)
class_
.
data
[
context
.
id
]
=
annotations
return
annotations
def
__init__
(
self
,
context
):
pass
def
__repr__
(
self
):
return
"<%s.PrincipalAnnotations object>"
%
__name__
class
TestCutCopyPaste
(
PlacefulSetup
,
TestCase
):
def
setUp
(
self
):
PlacefulSetup
.
setUp
(
self
)
PlacefulSetup
.
buildFolders
(
self
)
ztapi
.
provideAdapter
(
IContained
,
IObjectCopier
,
ObjectCopier
)
ztapi
.
provideAdapter
(
IContained
,
IObjectMover
,
ObjectMover
)
ztapi
.
provideAdapter
(
IContainer
,
IContainerItemRenamer
,
ContainerItemRenamer
)
ztapi
.
provideAdapter
(
IAnnotations
,
IPrincipalClipboard
,
PrincipalClipboard
)
ztapi
.
provideAdapter
(
Principal
,
IAnnotations
,
PrincipalAnnotations
)
def
testRename
(
self
):
container
=
traverse
(
self
.
rootFolder
,
'folder1'
)
fc
=
self
.
_TestView__newView
(
container
)
ids
=
[
'document1'
,
'document2'
]
for
id
in
ids
:
document
=
Document
()
container
[
id
]
=
document
fc
.
request
.
form
.
update
({
'rename_ids'
:
ids
,
'new_value'
:
[
'document1_1'
,
'document2_2'
]
})
fc
.
renameObjects
()
self
.
failIf
(
'document1_1'
not
in
container
)
self
.
failIf
(
'document1'
in
container
)
def
testCopyPaste
(
self
):
container
=
traverse
(
self
.
rootFolder
,
'folder1'
)
fc
=
self
.
_TestView__newView
(
container
)
ids
=
[
'document1'
,
'document2'
]
for
id
in
ids
:
document
=
Document
()
container
[
id
]
=
document
fc
.
request
.
form
[
'ids'
]
=
ids
fc
.
copyObjects
()
fc
.
pasteObjects
()
self
.
failIf
(
'document1'
not
in
container
)
self
.
failIf
(
'document2'
not
in
container
)
self
.
failIf
(
'document1-2'
not
in
container
)
self
.
failIf
(
'document2-2'
not
in
container
)
def
testCopyFolder
(
self
):
container
=
traverse
(
self
.
rootFolder
,
'folder1'
)
fc
=
self
.
_TestView__newView
(
container
)
ids
=
[
'folder1_1'
]
fc
.
request
.
form
[
'ids'
]
=
ids
fc
.
copyObjects
()
fc
.
pasteObjects
()
self
.
failIf
(
'folder1_1'
not
in
container
)
self
.
failIf
(
'folder1_1-2'
not
in
container
)
def
testCopyFolder2
(
self
):
container
=
traverse
(
self
.
rootFolder
,
'/folder1/folder1_1'
)
fc
=
self
.
_TestView__newView
(
container
)
ids
=
[
'folder1_1_1'
]
fc
.
request
.
form
[
'ids'
]
=
ids
fc
.
copyObjects
()
fc
.
pasteObjects
()
self
.
failIf
(
'folder1_1_1'
not
in
container
)
self
.
failIf
(
'folder1_1_1-2'
not
in
container
)
def
testCopyFolder3
(
self
):
container
=
traverse
(
self
.
rootFolder
,
'/folder1/folder1_1'
)
target
=
traverse
(
self
.
rootFolder
,
'/folder2/folder2_1'
)
fc
=
self
.
_TestView__newView
(
container
)
tg
=
self
.
_TestView__newView
(
target
)
ids
=
[
'folder1_1_1'
]
fc
.
request
.
form
[
'ids'
]
=
ids
fc
.
copyObjects
()
tg
.
pasteObjects
()
self
.
failIf
(
'folder1_1_1'
not
in
container
)
self
.
failIf
(
'folder1_1_1'
not
in
target
)
def
testCutPaste
(
self
):
container
=
traverse
(
self
.
rootFolder
,
'folder1'
)
fc
=
self
.
_TestView__newView
(
container
)
ids
=
[
'document1'
,
'document2'
]
for
id
in
ids
:
document
=
Document
()
container
[
id
]
=
document
fc
.
request
.
form
[
'ids'
]
=
ids
fc
.
cutObjects
()
fc
.
pasteObjects
()
self
.
failIf
(
'document1'
not
in
container
)
self
.
failIf
(
'document2'
not
in
container
)
def
testCutFolder
(
self
):
container
=
traverse
(
self
.
rootFolder
,
'folder1'
)
fc
=
self
.
_TestView__newView
(
container
)
ids
=
[
'folder1_1'
]
fc
.
request
.
form
[
'ids'
]
=
ids
fc
.
cutObjects
()
fc
.
pasteObjects
()
self
.
failIf
(
'folder1_1'
not
in
container
)
def
testCutFolder2
(
self
):
container
=
traverse
(
self
.
rootFolder
,
'/folder1/folder1_1'
)
fc
=
self
.
_TestView__newView
(
container
)
ids
=
[
'folder1_1_1'
]
fc
.
request
.
form
[
'ids'
]
=
ids
fc
.
cutObjects
()
fc
.
pasteObjects
()
self
.
failIf
(
'folder1_1_1'
not
in
container
)
def
testCutFolder3
(
self
):
container
=
traverse
(
self
.
rootFolder
,
'/folder1/folder1_1'
)
target
=
traverse
(
self
.
rootFolder
,
'/folder2/folder2_1'
)
fc
=
self
.
_TestView__newView
(
container
)
tg
=
self
.
_TestView__newView
(
target
)
ids
=
[
'folder1_1_1'
]
fc
.
request
.
form
[
'ids'
]
=
ids
fc
.
cutObjects
()
tg
.
pasteObjects
()
self
.
failIf
(
'folder1_1_1'
in
container
)
self
.
failIf
(
'folder1_1_1'
not
in
target
)
def
_TestView__newView
(
self
,
container
):
from
zope.app.container.browser.contents
import
Contents
from
zope.publisher.browser
import
TestRequest
request
=
TestRequest
()
request
.
setPrincipal
(
Principal
())
return
Contents
(
container
,
request
)
class
Test
(
BaseTestContentsBrowserView
,
TestCase
):
def
_TestView__newContext
(
self
):
from
zope.app.container.sample
import
SampleContainer
from
zope.app.folder
import
rootFolder
root
=
rootFolder
()
container
=
SampleContainer
()
return
contained
(
container
,
root
,
'sample'
)
def
_TestView__newView
(
self
,
container
):
from
zope.app.container.browser.contents
import
Contents
from
zope.publisher.browser
import
TestRequest
request
=
TestRequest
()
request
.
setPrincipal
(
Principal
())
return
Contents
(
container
,
request
)
def
test_suite
():
return
TestSuite
((
makeSuite
(
Test
),
makeSuite
(
TestCutCopyPaste
),
))
if
__name__
==
'__main__'
:
main
(
defaultTest
=
'test_suite'
)
src/zope/container/browser/tests/test_contents_functional.py
deleted
100644 → 0
View file @
f1f6cc98
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Functional tests for the Container's 'Contents' view
$Id$
"""
import
unittest
from
persistent
import
Persistent
import
transaction
from
zope
import
copypastemove
from
zope.interface
import
implements
,
Interface
from
zope.annotation.interfaces
import
IAttributeAnnotatable
from
zope.dublincore.interfaces
import
IZopeDublinCore
from
zope.app.container.interfaces
import
IReadContainer
,
IContained
from
zope.app.testing
import
ztapi
from
zope.app.testing.functional
import
BrowserTestCase
from
zope.app.testing.functional
import
FunctionalDocFileSuite
from
zope.app.container.testing
import
AppContainerLayer
class
IImmovable
(
Interface
):
"""Marker interface for immovable objects."""
class
IUncopyable
(
Interface
):
"""Marker interface for uncopyable objects."""
class
File
(
Persistent
):
implements
(
IAttributeAnnotatable
)
class
ImmovableFile
(
File
):
implements
(
IImmovable
)
class
UncopyableFile
(
File
):
implements
(
IUncopyable
)
class
ObjectNonCopier
(
copypastemove
.
ObjectCopier
):
def
copyable
(
self
):
return
False
class
ObjectNonMover
(
copypastemove
.
ObjectMover
):
def
moveable
(
self
):
return
False
class
ReadOnlyContainer
(
Persistent
):
implements
(
IReadContainer
,
IContained
)
__parent__
=
__name__
=
None
def
__init__
(
self
):
self
.
data
=
{}
def
keys
(
self
):
return
self
.
data
.
keys
()
def
__getitem__
(
self
,
key
):
return
self
.
data
[
key
]
def
get
(
self
,
key
,
default
=
None
):
return
self
.
data
.
get
(
key
,
default
)
def
__iter__
(
self
):
return
iter
(
self
.
data
)
def
values
(
self
):
return
self
.
data
.
values
()
def
__len__
(
self
):
return
len
(
self
.
data
)
def
items
(
self
):
return
self
.
data
.
items
()
def
__contains__
(
self
,
key
):
return
key
in
self
.
data
def
has_key
(
self
,
key
):
return
self
.
data
.
has_key
(
key
)
class
Test
(
BrowserTestCase
):
def
test_inplace_add
(
self
):
root
=
self
.
getRootFolder
()
self
.
assert_
(
'foo'
not
in
root
)
response
=
self
.
publish
(
'/@@contents.html'
,
basic
=
'mgr:mgrpw'
,
form
=
{
'type_name'
:
u'zope.app.content.File'
})
body
=
' '
.
join
(
response
.
getBody
().
split
())
self
.
assert_
(
body
.
find
(
'type="hidden" name="type_name"'
)
>=
0
)
self
.
assert_
(
body
.
find
(
'input name="new_value"'
)
>=
0
)
self
.
assert_
(
body
.
find
(
'type="submit" name="container_cancel_button"'
)
>=
0
)
self
.
assert_
(
body
.
find
(
'type="submit" name="container_rename_button"'
)
<
0
)
response
=
self
.
publish
(
'/@@contents.html'
,
basic
=
'mgr:mgrpw'
,
form
=
{
'type_name'
:
u'zope.app.content.File'
,
'new_value'
:
'foo'
})
self
.
assertEqual
(
response
.
getStatus
(),
302
)
self
.
assertEqual
(
response
.
getHeader
(
'Location'
),
'http://localhost/@@contents.html'
)
root
.
_p_jar
.
sync
()
self
.
assert_
(
'foo'
in
root
)
def
test_inplace_rename_multiple
(
self
):
root
=
self
.
getRootFolder
()
root
[
'foo'
]
=
File
()
self
.
assert_
(
'foo'
in
root
)
transaction
.
commit
()
# Check that we don't change mode if there are no items selected
response
=
self
.
publish
(
'/@@contents.html'
,
basic
=
'mgr:mgrpw'
,
form
=
{
'container_rename_button'
:
u''
})
body
=
' '
.
join
(
response
.
getBody
().
split
())
self
.
assert_
(
body
.
find
(
'input name="new_value:list"'
)
<
0
)
self
.
assert_
(
body
.
find
(
'type="submit" name="container_cancel_button"'
)
<
0
)
self
.
assert_
(
body
.
find
(
'type="submit" name="container_rename_button"'
)
>=
0
)
self
.
assert_
(
body
.
find
(
'div class="page_error"'
)
>=
0
)
# Check normal multiple select
response
=
self
.
publish
(
'/@@contents.html'
,
basic
=
'mgr:mgrpw'
,
form
=
{
'container_rename_button'
:
u''
,
'ids'
:
[
'foo'
]})
body
=
' '
.
join
(
response
.
getBody
().
split
())
self
.
assert_
(
body
.
find
(
'input name="new_value:list"'
)
>=
0
)
self
.
assert_
(
body
.
find
(
'type="submit" name="container_cancel_button"'
)
>=
0
)
self
.
assert_
(
body
.
find
(
'type="submit" name="container_rename_button"'
)
<
0
)
response
=
self
.
publish
(
'/@@contents.html'
,
basic
=
'mgr:mgrpw'
,
form
=
{
'rename_ids'
:
[
'foo'
],
'new_value'
:
[
'bar'
]})
self
.
assertEqual
(
response
.
getStatus
(),
302
)
self
.
assertEqual
(
response
.
getHeader
(
'Location'
),
'http://localhost/@@contents.html'
)
root
.
_p_jar
.
sync
()
self
.
assert_
(
'foo'
not
in
root
)
self
.
assert_
(
'bar'
in
root
)
def
test_inplace_rename_single
(
self
):
root
=
self
.
getRootFolder
()
root
[
'foo'
]
=
File
()
self
.
assert_
(
'foo'
in
root
)
transaction
.
commit
()
response
=
self
.
publish
(
'/@@contents.html'
,
basic
=
'mgr:mgrpw'
,
form
=
{
'rename_ids'
:
[
'foo'
]})
body
=
' '
.
join
(
response
.
getBody
().
split
())
self
.
assert_
(
body
.
find
(
'input name="new_value:list"'
)
>=
0
)
self
.
assert_
(
body
.
find
(
'type="submit" name="container_cancel_button"'
)
>=
0
)
self
.
assert_
(
body
.
find
(
'type="submit" name="container_rename_button"'
)
<
0
)
response
=
self
.
publish
(
'/@@contents.html'
,
basic
=
'mgr:mgrpw'
,
form
=
{
'rename_ids'
:
[
'foo'
],
'new_value'
:
[
'bar'
]})
self
.
assertEqual
(
response
.
getStatus
(),
302
)
self
.
assertEqual
(
response
.
getHeader
(
'Location'
),
'http://localhost/@@contents.html'
)
root
.
_p_jar
.
sync
()
self
.
assert_
(
'foo'
not
in
root
)
self
.
assert_
(
'bar'
in
root
)
def
test_inplace_change_title
(
self
):
root
=
self
.
getRootFolder
()
root
[
'foo'
]
=
File
()
transaction
.
commit
()
self
.
assert_
(
'foo'
in
root
)
dc
=
IZopeDublinCore
(
root
[
'foo'
])
self
.
assert_
(
dc
.
title
==
''
)
response
=
self
.
publish
(
'/@@contents.html'
,
basic
=
'mgr:mgrpw'
,
form
=
{
'retitle_id'
:
u'foo'
})
body
=
' '
.
join
(
response
.
getBody
().
split
())
self
.
assert_
(
body
.
find
(
'type="hidden" name="retitle_id"'
)
>=
0
)
self
.
assert_
(
body
.
find
(
'input name="new_value"'
)
>=
0
)
self
.
assert_
(
body
.
find
(
'type="submit" name="container_cancel_button"'
)
>=
0
)
self
.
assert_
(
body
.
find
(
'type="submit" name="container_rename_button"'
)
<
0
)
response
=
self
.
publish
(
'/@@contents.html'
,
basic
=
'mgr:mgrpw'
,
form
=
{
'retitle_id'
:
u'foo'
,
'new_value'
:
u'test title'
})
self
.
assertEqual
(
response
.
getStatus
(),
302
)
self
.
assertEqual
(
response
.
getHeader
(
'Location'
),
'http://localhost/@@contents.html'
)
root
.
_p_jar
.
sync
()
self
.
assert_
(
'foo'
in
root
)
dc
=
IZopeDublinCore
(
root
[
'foo'
])
self
.
assert_
(
dc
.
title
==
'test title'
)
def
test_pasteable_for_deleted_clipboard_item
(
self
):
"""Tests Paste button visibility when copied item is deleted."""
root
=
self
.
getRootFolder
()
root
[
'foo'
]
=
File
()
# item to be copied/deleted
root
[
'bar'
]
=
File
()
# ensures that there's always an item in
# the collection view
transaction
.
commit
()
# confirm foo in contents, Copy button visible, Paste not visible
response
=
self
.
publish
(
'/@@contents.html'
,
basic
=
'mgr:mgrpw'
)
self
.
assertEqual
(
response
.
getStatus
(),
200
)
self
.
assert_
(
response
.
getBody
().
find
(
'<a href="foo/@@SelectedManagementView.html">foo</a>'
)
!=
-
1
)
self
.
assert_
(
response
.
getBody
().
find
(
'<input type="submit" name="container_copy_button"'
)
!=
-
1
)
self
.
assert_
(
response
.
getBody
().
find
(
'<input type="submit" name="container_paste_button"'
)
==
-
1
)
# copy foo - confirm Paste visible
response
=
self
.
publish
(
'/@@contents.html'
,
basic
=
'mgr:mgrpw'
,
form
=
{
'ids'
:
(
'foo'
,),
'container_copy_button'
:
''
})
self
.
assertEqual
(
response
.
getStatus
(),
302
)
self
.
assertEqual
(
response
.
getHeader
(
'Location'
),
'http://localhost/@@contents.html'
)
response
=
self
.
publish
(
'/@@contents.html'
,
basic
=
'mgr:mgrpw'
)
self
.
assertEqual
(
response
.
getStatus
(),
200
)
self
.
assert_
(
response
.
getBody
().
find
(
'<input type="submit" name="container_paste_button"'
)
!=
-
1
)
# delete foo -> nothing valid to paste -> Paste should not be visible
del
root
[
'foo'
]
transaction
.
commit
()
response
=
self
.
publish
(
'/@@contents.html'
,
basic
=
'mgr:mgrpw'
)
self
.
assertEqual
(
response
.
getStatus
(),
200
)
self
.
assert_
(
response
.
getBody
().
find
(
'<input type="submit" name="container_paste_button"'
)
==
-
1
)
def
test_paste_for_deleted_clipboard_item
(
self
):
"""Tests paste operation when one of two copied items is deleted."""
root
=
self
.
getRootFolder
()
root
[
'foo'
]
=
File
()
root
[
'bar'
]
=
File
()
transaction
.
commit
()
# confirm foo/bar in contents, Copy button visible, Paste not visible
response
=
self
.
publish
(
'/@@contents.html'
,
basic
=
'mgr:mgrpw'
)
self
.
assertEqual
(
response
.
getStatus
(),
200
)
self
.
assert_
(
response
.
getBody
().
find
(
'<a href="foo/@@SelectedManagementView.html">foo</a>'
)
!=
-
1
)
self
.
assert_
(
response
.
getBody
().
find
(
'<a href="bar/@@SelectedManagementView.html">bar</a>'
)
!=
-
1
)
self
.
assert_
(
response
.
getBody
().
find
(
'<input type="submit" name="container_copy_button"'
)
!=
-
1
)
self
.
assert_
(
response
.
getBody
().
find
(
'<input type="submit" name="container_paste_button"'
)
==
-
1
)
# copy foo and bar - confirm Paste visible
response
=
self
.
publish
(
'/@@contents.html'
,
basic
=
'mgr:mgrpw'
,
form
=
{
'ids'
:
(
'foo'
,
'bar'
),
'container_copy_button'
:
''
})
self
.
assertEqual
(
response
.
getStatus
(),
302
)
self
.
assertEqual
(
response
.
getHeader
(
'Location'
),
'http://localhost/@@contents.html'
)
response
=
self
.
publish
(
'/@@contents.html'
,
basic
=
'mgr:mgrpw'
)
self
.
assertEqual
(
response
.
getStatus
(),
200
)
self
.
assert_
(
response
.
getBody
().
find
(
'<input type="submit" name="container_paste_button"'
)
!=
-
1
)
# delete only foo -> bar still available -> Paste should be visible
del
root
[
'foo'
]
transaction
.
commit
()
response
=
self
.
publish
(
'/@@contents.html'
,
basic
=
'mgr:mgrpw'
)
self
.
assertEqual
(
response
.
getStatus
(),
200
)
self
.
assert_
(
response
.
getBody
().
find
(
'<input type="submit" name="container_paste_button"'
)
!=
-
1
)
# paste clipboard contents - only bar should be copied
response
=
self
.
publish
(
'/@@contents.html'
,
basic
=
'mgr:mgrpw'
,
form
=
{
'container_paste_button'
:
''
})
self
.
assertEqual
(
response
.
getStatus
(),
302
)
self
.
assertEqual
(
response
.
getHeader
(
'Location'
),
'http://localhost/@@contents.html'
)
response
=
self
.
publish
(
'/@@contents.html'
,
basic
=
'mgr:mgrpw'
)
self
.
assertEqual
(
response
.
getStatus
(),
200
)
root
.
_p_jar
.
sync
()
self
.
assertEqual
(
tuple
(
root
.
keys
()),
(
'bar'
,
'bar-2'
))
def
test_readonly_display
(
self
):
root
=
self
.
getRootFolder
()
root
[
'foo'
]
=
ReadOnlyContainer
()
transaction
.
commit
()
response
=
self
.
publish
(
'/foo/@@contents.html'
,
basic
=
'mgr:mgrpw'
)
self
.
assertEqual
(
response
.
getStatus
(),
200
)
def
test_uncopyable_object
(
self
):
ztapi
.
provideAdapter
(
IUncopyable
,
copypastemove
.
interfaces
.
IObjectCopier
,
ObjectNonCopier
)
root
=
self
.
getRootFolder
()
root
[
'uncopyable'
]
=
UncopyableFile
()
transaction
.
commit
()
response
=
self
.
publish
(
'/@@contents.html'
,
basic
=
'mgr:mgrpw'
,
form
=
{
'ids'
:
[
u'uncopyable'
],
'container_copy_button'
:
u'Copy'
})
self
.
assertEqual
(
response
.
getStatus
(),
200
)
body
=
response
.
getBody
()
self
.
assert_
(
"cannot be copied"
in
body
)
def
test_unmoveable_object
(
self
):
ztapi
.
provideAdapter
(
IImmovable
,
copypastemove
.
interfaces
.
IObjectMover
,
ObjectNonMover
)
root
=
self
.
getRootFolder
()
root
[
'immovable'
]
=
ImmovableFile
()
transaction
.
commit
()
response
=
self
.
publish
(
'/@@contents.html'
,
basic
=
'mgr:mgrpw'
,
form
=
{
'ids'
:
[
u'immovable'
],
'container_cut_button'
:
u'Cut'
})
self
.
assertEqual
(
response
.
getStatus
(),
200
)
body
=
response
.
getBody
()
self
.
assert_
(
"cannot be moved"
in
body
)
def
test_copy_then_delete_with_unicode_name
(
self
):
"""Tests unicode on object copied then deleted (#238579)."""
# create a file with an accentuated unicode name
root
=
self
.
getRootFolder
()
root
[
u'voil
\
xe0
'
]
=
File
()
transaction
.
commit
()
# copy the object
response
=
self
.
publish
(
'/@@contents.html'
,
basic
=
'mgr:mgrpw'
,
form
=
{
'ids'
:
(
u'voil
\
xe0
'
,),
'container_copy_button'
:
''
})
self
.
assertEqual
(
response
.
getStatus
(),
302
)
self
.
assertEqual
(
response
.
getHeader
(
'Location'
),
'http://localhost/@@contents.html'
)
response
=
self
.
publish
(
'/@@contents.html'
,
basic
=
'mgr:mgrpw'
)
self
.
assertEqual
(
response
.
getStatus
(),
200
)
# delete the object
del
root
[
u'voil
\
xe0
'
]
transaction
.
commit
()
response
=
self
.
publish
(
'/@@contents.html'
,
basic
=
'mgr:mgrpw'
)
self
.
assertEqual
(
response
.
getStatus
(),
200
)
def
test_suite
():
suite
=
unittest
.
TestSuite
()
Test
.
layer
=
AppContainerLayer
suite
.
addTest
(
unittest
.
makeSuite
(
Test
))
index
=
FunctionalDocFileSuite
(
"index.txt"
)
index
.
layer
=
AppContainerLayer
suite
.
addTest
(
index
)
return
suite
if
__name__
==
'__main__'
:
unittest
.
main
(
defaultTest
=
'test_suite'
)
src/zope/container/browser/tests/test_directive.py
deleted
100644 → 0
View file @
f1f6cc98
##############################################################################
#
# Copyright (c) 2003 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""'containerView' directive test
$Id$
"""
import
re
import
pprint
import
cStringIO
import
unittest
from
zope.interface
import
Interface
from
zope.publisher.interfaces.browser
import
IBrowserRequest
from
zope.testing.doctestunit
import
DocTestSuite
from
zope.app.container.browser.metaconfigure
import
containerViews
atre
=
re
.
compile
(
' at [0-9a-fA-Fx]+'
)
class
Context
(
object
):
actions
=
()
info
=
''
def
action
(
self
,
discriminator
,
callable
,
args
):
self
.
actions
+=
((
discriminator
,
callable
,
args
),
)
self
.
info
=
'info'
def
__repr__
(
self
):
stream
=
cStringIO
.
StringIO
()
pprinter
=
pprint
.
PrettyPrinter
(
stream
=
stream
,
width
=
60
)
pprinter
.
pprint
(
self
.
actions
)
r
=
stream
.
getvalue
()
return
(
''
.
join
(
atre
.
split
(
r
))).
strip
()
class
I
(
Interface
):
pass
class
ITestLayer
(
IBrowserRequest
):
pass
def
test_containerViews
():
"""
>>> from zope.app.publisher.browser.menumeta import menus
>>> from zope.interface.interface import InterfaceClass
>>> zmi_views = InterfaceClass('zmi_views', __module__='zope.app.menus')
>>> menus.zmi_views = zmi_views
>>> zmi_actions = InterfaceClass('zmi_actions', __module__='zope.app.menus')
>>> menus.zmi_actions = zmi_actions
>>> context = Context()
>>> containerViews(context, for_=I, contents='zope.ManageContent',
... add='zope.ManageContent', index='zope.View')
>>> context
((('adapter',
(<InterfaceClass zope.app.container.browser.tests.test_directive.I>,
<InterfaceClass zope.publisher.interfaces.browser.IDefaultBrowserLayer>),
<InterfaceClass zope.app.menus.zmi_views>,
u'Contents'),
<function handler>,
('registerAdapter',
<zope.app.publisher.browser.menumeta.MenuItemFactory object>,
(<InterfaceClass zope.app.container.browser.tests.test_directive.I>,
<InterfaceClass zope.publisher.interfaces.browser.IDefaultBrowserLayer>),
<InterfaceClass zope.app.menus.zmi_views>,
u'Contents',
'')),
(None,
<function provideInterface>,
('', <InterfaceClass zope.app.menus.zmi_views>)),
(None,
<function provideInterface>,
('',
<InterfaceClass zope.app.container.browser.tests.test_directive.I>)),
(None,
<function provideInterface>,
('',
<InterfaceClass zope.publisher.interfaces.browser.IDefaultBrowserLayer>)),
(None,
<function provideInterface>,
('',
<InterfaceClass zope.app.container.browser.tests.test_directive.I>)),
(('view',
<InterfaceClass zope.app.container.browser.tests.test_directive.I>,
'contents.html',
<InterfaceClass zope.publisher.interfaces.browser.IBrowserRequest>,
<InterfaceClass zope.publisher.interfaces.browser.IDefaultBrowserLayer>),
<function handler>,
('registerAdapter',
<class 'zope.app.publisher.browser.viewmeta.Contents'>,
(<InterfaceClass zope.app.container.browser.tests.test_directive.I>,
<InterfaceClass zope.publisher.interfaces.browser.IDefaultBrowserLayer>),
<InterfaceClass zope.interface.Interface>,
'contents.html',
'info')),
(None,
<function provideInterface>,
('',
<InterfaceClass zope.app.container.browser.tests.test_directive.I>)),
(('view',
<InterfaceClass zope.app.container.browser.tests.test_directive.I>,
'index.html',
<InterfaceClass zope.publisher.interfaces.browser.IBrowserRequest>,
<InterfaceClass zope.publisher.interfaces.browser.IDefaultBrowserLayer>),
<function handler>,
('registerAdapter',
<class 'zope.app.publisher.browser.viewmeta.Contents'>,
(<InterfaceClass zope.app.container.browser.tests.test_directive.I>,
<InterfaceClass zope.publisher.interfaces.browser.IDefaultBrowserLayer>),
<InterfaceClass zope.interface.Interface>,
'index.html',
'info')),
(('adapter',
(<InterfaceClass zope.app.container.browser.tests.test_directive.I>,
<InterfaceClass zope.publisher.interfaces.browser.IDefaultBrowserLayer>),
<InterfaceClass zope.app.menus.zmi_actions>,
u'Add'),
<function handler>,
('registerAdapter',
<zope.app.publisher.browser.menumeta.MenuItemFactory object>,
(<InterfaceClass zope.app.container.browser.tests.test_directive.I>,
<InterfaceClass zope.publisher.interfaces.browser.IDefaultBrowserLayer>),
<InterfaceClass zope.app.menus.zmi_actions>,
u'Add',
'info')),
(None,
<function provideInterface>,
('', <InterfaceClass zope.app.menus.zmi_actions>)),
(None,
<function provideInterface>,
('',
<InterfaceClass zope.app.container.browser.tests.test_directive.I>)),
(None,
<function provideInterface>,
('',
<InterfaceClass zope.publisher.interfaces.browser.IDefaultBrowserLayer>)),
(None,
<function provideInterface>,
('',
<InterfaceClass zope.app.container.browser.tests.test_directive.I>)),
(None,
<function provideInterface>,
('', <InterfaceClass zope.interface.Interface>)),
(('view',
(<InterfaceClass zope.app.container.browser.tests.test_directive.I>,
<InterfaceClass zope.publisher.interfaces.browser.IDefaultBrowserLayer>),
'+',
<InterfaceClass zope.interface.Interface>),
<function handler>,
('registerAdapter',
<class 'zope.app.publisher.browser.viewmeta.+'>,
(<InterfaceClass zope.app.container.browser.tests.test_directive.I>,
<InterfaceClass zope.publisher.interfaces.browser.IDefaultBrowserLayer>),
<InterfaceClass zope.interface.Interface>,
'+',
'info')))
"""
def
test_containerViews_layer
():
"""
>>> from zope.app.publisher.browser.menumeta import menus
>>> from zope.interface.interface import InterfaceClass
>>> zmi_views = InterfaceClass('zmi_views', __module__='zope.app.menus')
>>> menus.zmi_views = zmi_views
>>> zmi_actions = InterfaceClass('zmi_actions', __module__='zope.app.menus')
>>> menus.zmi_actions = zmi_actions
>>> context = Context()
>>> containerViews(context, for_=I, contents='zope.ManageContent',
... add='zope.ManageContent', index='zope.View', layer=ITestLayer)
>>> context
((('adapter',
(<InterfaceClass zope.app.container.browser.tests.test_directive.I>,
<InterfaceClass zope.app.container.browser.tests.test_directive.ITestLayer>),
<InterfaceClass zope.app.menus.zmi_views>,
u'Contents'),
<function handler>,
('registerAdapter',
<zope.app.publisher.browser.menumeta.MenuItemFactory object>,
(<InterfaceClass zope.app.container.browser.tests.test_directive.I>,
<InterfaceClass zope.app.container.browser.tests.test_directive.ITestLayer>),
<InterfaceClass zope.app.menus.zmi_views>,
u'Contents',
'')),
(None,
<function provideInterface>,
('', <InterfaceClass zope.app.menus.zmi_views>)),
(None,
<function provideInterface>,
('',
<InterfaceClass zope.app.container.browser.tests.test_directive.I>)),
(None,
<function provideInterface>,
('',
<InterfaceClass zope.app.container.browser.tests.test_directive.ITestLayer>)),
(None,
<function provideInterface>,
('',
<InterfaceClass zope.app.container.browser.tests.test_directive.I>)),
(('view',
<InterfaceClass zope.app.container.browser.tests.test_directive.I>,
'contents.html',
<InterfaceClass zope.publisher.interfaces.browser.IBrowserRequest>,
<InterfaceClass zope.app.container.browser.tests.test_directive.ITestLayer>),
<function handler>,
('registerAdapter',
<class 'zope.app.publisher.browser.viewmeta.Contents'>,
(<InterfaceClass zope.app.container.browser.tests.test_directive.I>,
<InterfaceClass zope.app.container.browser.tests.test_directive.ITestLayer>),
<InterfaceClass zope.interface.Interface>,
'contents.html',
'info')),
(None,
<function provideInterface>,
('',
<InterfaceClass zope.app.container.browser.tests.test_directive.I>)),
(('view',
<InterfaceClass zope.app.container.browser.tests.test_directive.I>,
'index.html',
<InterfaceClass zope.publisher.interfaces.browser.IBrowserRequest>,
<InterfaceClass zope.app.container.browser.tests.test_directive.ITestLayer>),
<function handler>,
('registerAdapter',
<class 'zope.app.publisher.browser.viewmeta.Contents'>,
(<InterfaceClass zope.app.container.browser.tests.test_directive.I>,
<InterfaceClass zope.app.container.browser.tests.test_directive.ITestLayer>),
<InterfaceClass zope.interface.Interface>,
'index.html',
'info')),
(('adapter',
(<InterfaceClass zope.app.container.browser.tests.test_directive.I>,
<InterfaceClass zope.app.container.browser.tests.test_directive.ITestLayer>),
<InterfaceClass zope.app.menus.zmi_actions>,
u'Add'),
<function handler>,
('registerAdapter',
<zope.app.publisher.browser.menumeta.MenuItemFactory object>,
(<InterfaceClass zope.app.container.browser.tests.test_directive.I>,
<InterfaceClass zope.app.container.browser.tests.test_directive.ITestLayer>),
<InterfaceClass zope.app.menus.zmi_actions>,
u'Add',
'info')),
(None,
<function provideInterface>,
('', <InterfaceClass zope.app.menus.zmi_actions>)),
(None,
<function provideInterface>,
('',
<InterfaceClass zope.app.container.browser.tests.test_directive.I>)),
(None,
<function provideInterface>,
('',
<InterfaceClass zope.app.container.browser.tests.test_directive.ITestLayer>)),
(None,
<function provideInterface>,
('',
<InterfaceClass zope.app.container.browser.tests.test_directive.I>)),
(None,
<function provideInterface>,
('', <InterfaceClass zope.interface.Interface>)),
(('view',
(<InterfaceClass zope.app.container.browser.tests.test_directive.I>,
<InterfaceClass zope.app.container.browser.tests.test_directive.ITestLayer>),
'+',
<InterfaceClass zope.interface.Interface>),
<function handler>,
('registerAdapter',
<class 'zope.app.publisher.browser.viewmeta.+'>,
(<InterfaceClass zope.app.container.browser.tests.test_directive.I>,
<InterfaceClass zope.app.container.browser.tests.test_directive.ITestLayer>),
<InterfaceClass zope.interface.Interface>,
'+',
'info')))
"""
def
test_suite
():
return
unittest
.
TestSuite
((
DocTestSuite
(),
))
if
__name__
==
'__main__'
:
unittest
.
main
()
src/zope/container/ftesting.zcml
deleted
100644 → 0
View file @
f1f6cc98
<configure
xmlns="http://namespaces.zope.org/zope"
i18n_domain="zope"
package="zope.app.container"
>
<!-- This file is the equivalent of site.zcml and it is -->
<!-- used for functional testing setup -->
<include package="zope.app.zcmlfiles" />
<include package="zope.app.container.browser.tests" />
<include package="zope.app.file"/>
<include package="zope.app.authentication" />
<include package="zope.app.securitypolicy" file="meta.zcml" />
<include package="zope.app.securitypolicy.tests" file="functional.zcml" />
<include package="zope.app.securitypolicy" />
<securityPolicy
component="zope.securitypolicy.zopepolicy.ZopeSecurityPolicy" />
<role id="zope.Anonymous" title="Everybody"
description="All users have this role implicitly" />
<role id="zope.Manager" title="Site Manager" />
<!-- Replace the following directive if you don't want public access -->
<grant permission="zope.View"
role="zope.Anonymous" />
<grant permission="zope.app.dublincore.view"
role="zope.Anonymous" />
<grantAll role="zope.Manager" />
<!-- Principals -->
<unauthenticatedPrincipal
id="zope.anybody"
title="Unauthenticated User" />
<!-- Principal that tests generally run as -->
<principal
id="zope.mgr"
title="Manager"
login="mgr"
password="mgrpw" />
<!-- Bootstrap principal used to make local grant to the principal above -->
<principal
id="zope.globalmgr"
title="Manager"
login="globalmgr"
password="globalmgrpw" />
<grant role="zope.Manager" principal="zope.globalmgr" />
</configure>
src/zope/container/tests/test_view_permissions.py
deleted
100644 → 0
View file @
f1f6cc98
##############################################################################
#
# Copyright (c) 2004 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Container View Permissions Tests
$Id$
"""
import
unittest
import
transaction
from
zope.security.interfaces
import
Unauthorized
from
zope.app.testing.functional
import
BrowserTestCase
from
zope.app.file
import
File
from
zope.dublincore.interfaces
import
IZopeDublinCore
from
zope.securitypolicy.interfaces
import
IRolePermissionManager
from
zope.app.container.testing
import
AppContainerLayer
class
Tests
(
BrowserTestCase
):
def
test_default_view_permissions
(
self
):
"""Tests the default view permissions.
See zope/app/securitypolicy/configure.zcml for the grants of
zope.View and zope.app.dublincore.view to zope.Anonymous. These
ensure that, by default, anonymous users can view container contents.
"""
# add an item that can be viewed from the root folder
file
=
File
()
self
.
getRootFolder
()[
'file'
]
=
file
IZopeDublinCore
(
file
).
title
=
u'My File'
transaction
.
commit
()
response
=
self
.
publish
(
'/'
)
self
.
assertEquals
(
response
.
getStatus
(),
200
)
body
=
response
.
getBody
()
# confirm we can see the file name
self
.
assert_
(
body
.
find
(
'<a href="file">file</a>'
)
!=
-
1
)
# confirm we can see the metadata title
self
.
assert_
(
body
.
find
(
'<td><span>My File</span></td>'
)
!=
-
1
)
def
test_deny_view
(
self
):
"""Tests the denial of view permissions to anonymous.
This test uses the ZMI interface to deny anonymous zope.View permission
to the root folder.
"""
# deny zope.View to zope.Anonymous
prm
=
IRolePermissionManager
(
self
.
getRootFolder
())
prm
.
denyPermissionToRole
(
'zope.View'
,
'zope.Anonymous'
)
transaction
.
commit
()
# confirm Unauthorized when viewing root folder
self
.
assertRaises
(
Unauthorized
,
self
.
publish
,
'/'
)
def
test_deny_dublincore_view
(
self
):
"""Tests the denial of dublincore view permissions to anonymous.
Users who can view a folder contents page but cannot view dublin core
should still be able to see the folder items' names, but not their
title, modified, and created info.
"""
# add an item that can be viewed from the root folder
file
=
File
()
self
.
getRootFolder
()[
'file'
]
=
file
IZopeDublinCore
(
file
).
title
=
u'My File'
# deny zope.app.dublincore.view to zope.Anonymous
prm
=
IRolePermissionManager
(
self
.
getRootFolder
())
prm
.
denyPermissionToRole
(
'zope.app.dublincore.view'
,
'zope.Anonymous'
)
transaction
.
commit
()
response
=
self
.
publish
(
'/'
)
self
.
assertEquals
(
response
.
getStatus
(),
200
)
body
=
response
.
getBody
()
# confirm we can see the file name
self
.
assert_
(
body
.
find
(
'<a href="file">file</a>'
)
!=
-
1
)
# confirm we *cannot* see the metadata title
self
.
assert_
(
body
.
find
(
'My File'
)
==
-
1
)
def
test_suite
():
suite
=
unittest
.
TestSuite
()
Tests
.
layer
=
AppContainerLayer
suite
.
addTest
(
unittest
.
makeSuite
(
Tests
))
return
suite
if
__name__
==
'__main__'
:
unittest
.
main
(
defaultTest
=
'test_suite'
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment