Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Z
Zope
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
Kirill Smelkov
Zope
Commits
efe61189
Commit
efe61189
authored
Aug 07, 2016
by
Hanno Schlichting
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
flake8 ZPublisher/Testing
parent
2e9d01ea
Changes
43
Show whitespace changes
Inline
Side-by-side
Showing
43 changed files
with
1240 additions
and
2009 deletions
+1240
-2009
src/Testing/README.txt
src/Testing/README.txt
+0
-35
src/Testing/ZODButil.py
src/Testing/ZODButil.py
+2
-0
src/Testing/ZopeTestCase/functional.py
src/Testing/ZopeTestCase/functional.py
+7
-7
src/Testing/ZopeTestCase/zopedoctest/functional.py
src/Testing/ZopeTestCase/zopedoctest/functional.py
+25
-16
src/Testing/common.py
src/Testing/common.py
+0
-35
src/Testing/custom_zodb.py
src/Testing/custom_zodb.py
+4
-5
src/Testing/dispatcher.py
src/Testing/dispatcher.py
+0
-188
src/Testing/makerequest.py
src/Testing/makerequest.py
+8
-9
src/Testing/tests/__init__.py
src/Testing/tests/__init__.py
+0
-1
src/Testing/tests/test_makerequest.py
src/Testing/tests/test_makerequest.py
+2
-6
src/Testing/tests/test_testbrowser.py
src/Testing/tests/test_testbrowser.py
+5
-2
src/ZPublisher/BaseRequest.py
src/ZPublisher/BaseRequest.py
+232
-201
src/ZPublisher/BaseResponse.py
src/ZPublisher/BaseResponse.py
+10
-11
src/ZPublisher/BeforeTraverse.py
src/ZPublisher/BeforeTraverse.py
+9
-11
src/ZPublisher/Client.py
src/ZPublisher/Client.py
+0
-564
src/ZPublisher/Converters.py
src/ZPublisher/Converters.py
+91
-63
src/ZPublisher/HTTPRangeSupport.py
src/ZPublisher/HTTPRangeSupport.py
+25
-14
src/ZPublisher/HTTPResponse.py
src/ZPublisher/HTTPResponse.py
+73
-82
src/ZPublisher/Iterators.py
src/ZPublisher/Iterators.py
+4
-3
src/ZPublisher/Publish.py
src/ZPublisher/Publish.py
+112
-85
src/ZPublisher/Request.py
src/ZPublisher/Request.py
+8
-3
src/ZPublisher/Response.py
src/ZPublisher/Response.py
+8
-3
src/ZPublisher/__init__.py
src/ZPublisher/__init__.py
+2
-14
src/ZPublisher/interfaces.py
src/ZPublisher/interfaces.py
+11
-6
src/ZPublisher/mapply.py
src/ZPublisher/mapply.py
+33
-24
src/ZPublisher/maybe_lock.py
src/ZPublisher/maybe_lock.py
+1
-6
src/ZPublisher/pubevents.py
src/ZPublisher/pubevents.py
+14
-6
src/ZPublisher/tests/__init__.py
src/ZPublisher/tests/__init__.py
+0
-1
src/ZPublisher/tests/generate_conflicts.py
src/ZPublisher/tests/generate_conflicts.py
+0
-90
src/ZPublisher/tests/testBaseRequest.py
src/ZPublisher/tests/testBaseRequest.py
+56
-50
src/ZPublisher/tests/testBeforeTraverse.py
src/ZPublisher/tests/testBeforeTraverse.py
+25
-22
src/ZPublisher/tests/testHTTPRangeSupport.py
src/ZPublisher/tests/testHTTPRangeSupport.py
+20
-28
src/ZPublisher/tests/testHTTPRequest.py
src/ZPublisher/tests/testHTTPRequest.py
+198
-180
src/ZPublisher/tests/testHTTPResponse.py
src/ZPublisher/tests/testHTTPResponse.py
+69
-78
src/ZPublisher/tests/testIterators.py
src/ZPublisher/tests/testIterators.py
+2
-5
src/ZPublisher/tests/testPostTraversal.py
src/ZPublisher/tests/testPostTraversal.py
+41
-35
src/ZPublisher/tests/testPublish.py
src/ZPublisher/tests/testPublish.py
+14
-7
src/ZPublisher/tests/test_Converters.py
src/ZPublisher/tests/test_Converters.py
+2
-27
src/ZPublisher/tests/test_exception_handling.py
src/ZPublisher/tests/test_exception_handling.py
+8
-5
src/ZPublisher/tests/test_mapply.py
src/ZPublisher/tests/test_mapply.py
+12
-11
src/ZPublisher/tests/test_xmlrpc.py
src/ZPublisher/tests/test_xmlrpc.py
+11
-7
src/ZPublisher/tests/testpubevents.py
src/ZPublisher/tests/testpubevents.py
+73
-48
src/ZPublisher/xmlrpc.py
src/ZPublisher/xmlrpc.py
+23
-15
No files found.
src/Testing/README.txt
deleted
100644 → 0
View file @
2e9d01ea
The Testing package is a set of shared routines for the Zope unit
testing framework. From Zope 2.8 these are more easily accessed
by using the ZopeTestCase package. See ZopeTestCase/doc for more
information.
To use Testing without ZopeTestCase:
1. Make a 'tests' subdirectory.
2. Copy 'framework.py' into 'tests' from any other package's 'tests'.
Once a test suite has been set up, you can add test modules:
1. Create a file with a name matching 'test*.py'.
2. Define one or more subclasses of 'unittest.TestCase'. The unittest
module is imported by the framework.
3. Define methods for the test classes. Each method's name must start
with 'test'. It should test one small case, using a Python
'assert' statement. Here's a minimal example:
class testClass1(unittest.TestCase):
def testAddition(self):
assert 1 + 1 == 2, 'Addition failed!'
4. You can add 'setUp' and 'tearDown' methods that are automatically
called at the start and end of the test suite.
5. Follow the instructions in 'framework.py' about adding lines to the
top and bottom of the file.
Now you can run the test as "python path/to/tests/testName.py", or
simply go to the 'tests' directory and type "python testName.py".
src/Testing/ZODButil.py
View file @
efe61189
...
@@ -3,10 +3,12 @@ from glob import glob
...
@@ -3,10 +3,12 @@ from glob import glob
import
ZODB
import
ZODB
from
ZODB.FileStorage
import
FileStorage
from
ZODB.FileStorage
import
FileStorage
def
makeDB
():
def
makeDB
():
s
=
FileStorage
(
'fs_tmp__%s'
%
os
.
getpid
())
s
=
FileStorage
(
'fs_tmp__%s'
%
os
.
getpid
())
return
ZODB
.
DB
(
s
)
return
ZODB
.
DB
(
s
)
def
cleanDB
():
def
cleanDB
():
for
fn
in
glob
(
'fs_tmp__*'
):
for
fn
in
glob
(
'fs_tmp__*'
):
os
.
remove
(
fn
)
os
.
remove
(
fn
)
src/Testing/ZopeTestCase/functional.py
View file @
efe61189
...
@@ -15,7 +15,9 @@
...
@@ -15,7 +15,9 @@
After Marius Gedminas' functional.py module for Zope3.
After Marius Gedminas' functional.py module for Zope3.
"""
"""
import
sys
,
re
,
base64
import
base64
import
re
import
sys
import
transaction
import
transaction
import
sandbox
import
sandbox
import
interfaces
import
interfaces
...
@@ -58,8 +60,8 @@ class Functional(sandbox.Sandboxed):
...
@@ -58,8 +60,8 @@ class Functional(sandbox.Sandboxed):
'''Publishes the object at 'path' returning a response object.'''
'''Publishes the object at 'path' returning a response object.'''
from
StringIO
import
StringIO
from
StringIO
import
StringIO
from
ZPublisher.
Request
import
Request
from
ZPublisher.
HTTPRequest
import
HTTPRequest
as
Request
from
ZPublisher.
Response
import
Response
from
ZPublisher.
HTTPResponse
import
HTTPResponse
as
Response
from
ZPublisher.Publish
import
publish_module
from
ZPublisher.Publish
import
publish_module
# Commit the sandbox for good measure
# Commit the sandbox for good measure
...
@@ -82,7 +84,7 @@ class Functional(sandbox.Sandboxed):
...
@@ -82,7 +84,7 @@ class Functional(sandbox.Sandboxed):
elif
len
(
p
)
==
2
:
elif
len
(
p
)
==
2
:
[
env
[
'PATH_INFO'
],
env
[
'QUERY_STRING'
]]
=
p
[
env
[
'PATH_INFO'
],
env
[
'QUERY_STRING'
]]
=
p
else
:
else
:
raise
TypeError
,
''
raise
TypeError
(
''
)
if
basic
:
if
basic
:
env
[
'HTTP_AUTHORIZATION'
]
=
"Basic %s"
%
base64
.
encodestring
(
basic
)
env
[
'HTTP_AUTHORIZATION'
]
=
"Basic %s"
%
base64
.
encodestring
(
basic
)
...
@@ -99,8 +101,7 @@ class Functional(sandbox.Sandboxed):
...
@@ -99,8 +101,7 @@ class Functional(sandbox.Sandboxed):
publish_module
(
'Zope2'
,
publish_module
(
'Zope2'
,
debug
=
not
handle_errors
,
debug
=
not
handle_errors
,
request
=
request
,
request
=
request
,
response
=
response
,
response
=
response
)
)
return
ResponseWrapper
(
response
,
outstream
,
path
)
return
ResponseWrapper
(
response
,
outstream
,
path
)
...
@@ -140,4 +141,3 @@ class ResponseWrapper:
...
@@ -140,4 +141,3 @@ class ResponseWrapper:
def
getCookie
(
self
,
name
):
def
getCookie
(
self
,
name
):
'''Returns a response cookie.'''
'''Returns a response cookie.'''
return
self
.
cookies
.
get
(
name
)
return
self
.
cookies
.
get
(
name
)
src/Testing/ZopeTestCase/zopedoctest/functional.py
View file @
efe61189
...
@@ -90,11 +90,14 @@ class DocResponseWrapper(ResponseWrapper):
...
@@ -90,11 +90,14 @@ class DocResponseWrapper(ResponseWrapper):
return
"%s
\
n
"
%
(
self
.
header_output
)
return
"%s
\
n
"
%
(
self
.
header_output
)
basicre
=
re
.
compile
(
'Basic (.+)?:(.+)?$'
)
headerre
=
re
.
compile
(
'(
\
S+): (.+)$
'
)
headerre
=
re
.
compile
(
'(
\
S+): (.+)$
'
)
def split_header(header):
def split_header(header):
return headerre.match(header).group(1, 2)
return headerre.match(header).group(1, 2)
basicre = re.compile('
Basic
(.
+
)
?
:(.
+
)
?$
')
def auth_header(header):
def auth_header(header):
match = basicre.match(header)
match = basicre.match(header)
if match:
if match:
...
@@ -111,6 +114,7 @@ def auth_header(header):
...
@@ -111,6 +114,7 @@ def auth_header(header):
def getRootFolder():
def getRootFolder():
return AppZapper().app()
return AppZapper().app()
def sync():
def sync():
getRootFolder()._p_jar.sync()
getRootFolder()._p_jar.sync()
...
@@ -124,7 +128,7 @@ def http(request_string, handle_errors=True):
...
@@ -124,7 +128,7 @@ def http(request_string, handle_errors=True):
import urllib
import urllib
import rfc822
import rfc822
from cStringIO import StringIO
from cStringIO import StringIO
from ZPublisher.
Response import
Response
from ZPublisher.
HTTPResponse import HTTPResponse as
Response
from ZPublisher.Publish import publish_module
from ZPublisher.Publish import publish_module
# Commit work done by previous python code.
# Commit work done by previous python code.
...
@@ -136,7 +140,7 @@ def http(request_string, handle_errors=True):
...
@@ -136,7 +140,7 @@ def http(request_string, handle_errors=True):
# Split off and parse the command line
# Split off and parse the command line
l = request_string.find('
\
n
')
l = request_string.find('
\
n
')
command_line = request_string[:l].rstrip()
command_line = request_string[:l].rstrip()
request_string = request_string[l
+
1:]
request_string = request_string[l
+
1:]
method, path, protocol = command_line.split()
method, path, protocol = command_line.split()
path = urllib.unquote(path)
path = urllib.unquote(path)
...
@@ -154,7 +158,7 @@ def http(request_string, handle_errors=True):
...
@@ -154,7 +158,7 @@ def http(request_string, handle_errors=True):
elif len(p) == 2:
elif len(p) == 2:
[env['
PATH_INFO
'], env['
QUERY_STRING
']] = p
[env['
PATH_INFO
'], env['
QUERY_STRING
']] = p
else:
else:
raise TypeError
, ''
raise TypeError
('')
header_output = HTTPHeaderOutput(
header_output = HTTPHeaderOutput(
protocol, ('
x
-
content
-
type
-
warning
', '
x
-
powered
-
by
',
protocol, ('
x
-
content
-
type
-
warning
', '
x
-
powered
-
by
',
...
@@ -173,7 +177,7 @@ def http(request_string, handle_errors=True):
...
@@ -173,7 +177,7 @@ def http(request_string, handle_errors=True):
name = '
HTTP_
' + name
name = '
HTTP_
' + name
env[name] = value.rstrip()
env[name] = value.rstrip()
if
env.has_key('
HTTP_AUTHORIZATION
')
:
if
'
HTTP_AUTHORIZATION
' in env
:
env['
HTTP_AUTHORIZATION
'] = auth_header(env['
HTTP_AUTHORIZATION
'])
env['
HTTP_AUTHORIZATION
'] = auth_header(env['
HTTP_AUTHORIZATION
'])
outstream = StringIO()
outstream = StringIO()
...
@@ -183,8 +187,8 @@ def http(request_string, handle_errors=True):
...
@@ -183,8 +187,8 @@ def http(request_string, handle_errors=True):
response=response,
response=response,
stdin=instream,
stdin=instream,
environ=env,
environ=env,
debug=not handle_errors
,
debug=not handle_errors
)
)
header_output.setResponseStatus(response.getStatus(), response.errmsg)
header_output.setResponseStatus(response.getStatus(), response.errmsg)
header_output.setResponseHeaders(response.headers)
header_output.setResponseHeaders(response.headers)
header_output.headersl.extend(response._cookie_list())
header_output.headersl.extend(response._cookie_list())
...
@@ -246,6 +250,7 @@ class ZopeSuiteFactory:
...
@@ -246,6 +250,7 @@ class ZopeSuiteFactory:
test_instance = test_class()
test_instance = test_class()
kwsetUp = self._kw.get('
setUp
')
kwsetUp = self._kw.get('
setUp
')
def setUp(test):
def setUp(test):
test_instance.setUp()
test_instance.setUp()
test.globs['
test
'] = test
test.globs['
test
'] = test
...
@@ -264,6 +269,7 @@ class ZopeSuiteFactory:
...
@@ -264,6 +269,7 @@ class ZopeSuiteFactory:
self._kw['
setUp
'] = setUp
self._kw['
setUp
'] = setUp
kwtearDown = self._kw.get('
tearDown
')
kwtearDown = self._kw.get('
tearDown
')
def tearDown(test):
def tearDown(test):
if kwtearDown is not None:
if kwtearDown is not None:
kwtearDown(test_instance)
kwtearDown(test_instance)
...
@@ -273,8 +279,8 @@ class ZopeSuiteFactory:
...
@@ -273,8 +279,8 @@ class ZopeSuiteFactory:
def setup_optionflags(self):
def setup_optionflags(self):
if '
optionflags
' not in self._kw:
if '
optionflags
' not in self._kw:
self._kw['
optionflags
'] = (
doctest.ELLIPSIS
self._kw['
optionflags
'] = (
| doctest.NORMALIZE_WHITESPACE)
doctest.ELLIPSIS
| doctest.NORMALIZE_WHITESPACE)
class FunctionalSuiteFactory(ZopeSuiteFactory):
class FunctionalSuiteFactory(ZopeSuiteFactory):
...
@@ -285,7 +291,8 @@ class FunctionalSuiteFactory(ZopeSuiteFactory):
...
@@ -285,7 +291,8 @@ class FunctionalSuiteFactory(ZopeSuiteFactory):
globs['
http
'] = http
globs['
http
'] = http
globs['
getRootFolder
'] = getRootFolder
globs['
getRootFolder
'] = getRootFolder
globs['
sync
'] = sync
globs['
sync
'] = sync
globs['
user_auth
'] = base64.encodestring('
%
s
:
%
s
' % (user_name, user_password))
globs['
user_auth
'] = base64.encodestring(
'
%
s
:
%
s
' % (user_name, user_password))
def setup_test_class(self):
def setup_test_class(self):
test_class = self._kw.get('
test_class
', FunctionalTestCase)
test_class = self._kw.get('
test_class
', FunctionalTestCase)
...
@@ -297,7 +304,7 @@ class FunctionalSuiteFactory(ZopeSuiteFactory):
...
@@ -297,7 +304,7 @@ class FunctionalSuiteFactory(ZopeSuiteFactory):
warnings
.
warn
((
"The test_class you are using doesn't "
warnings
.
warn
((
"The test_class you are using doesn't "
"subclass from ZopeTestCase.Functional. "
"subclass from ZopeTestCase.Functional. "
"Please fix that."
),
UserWarning
,
4
)
"Please fix that."
),
UserWarning
,
4
)
if
not
'Functional'
in
name
:
if
'Functional'
not
in
name
:
name
=
'Functional%s'
%
name
name
=
'Functional%s'
%
name
test_class
=
type
(
name
,
(
Functional
,
test_class
),
{})
test_class
=
type
(
name
,
(
Functional
,
test_class
),
{})
...
@@ -306,24 +313,27 @@ class FunctionalSuiteFactory(ZopeSuiteFactory):
...
@@ -306,24 +313,27 @@ class FunctionalSuiteFactory(ZopeSuiteFactory):
def
setup_optionflags
(
self
):
def
setup_optionflags
(
self
):
if
'optionflags'
not
in
self
.
_kw
:
if
'optionflags'
not
in
self
.
_kw
:
self
.
_kw
[
'optionflags'
]
=
(
doctest
.
ELLIPSIS
self
.
_kw
[
'optionflags'
]
=
(
|
doctest
.
REPORT_NDIFF
doctest
.
ELLIPSIS
|
doctest
.
REPORT_NDIFF
|
|
doctest
.
NORMALIZE_WHITESPACE
)
doctest
.
NORMALIZE_WHITESPACE
)
def
ZopeDocTestSuite
(
module
=
None
,
**
kw
):
def
ZopeDocTestSuite
(
module
=
None
,
**
kw
):
module
=
doctest
.
_normalize_module
(
module
)
module
=
doctest
.
_normalize_module
(
module
)
return
ZopeSuiteFactory
(
module
,
**
kw
).
doctestsuite
()
return
ZopeSuiteFactory
(
module
,
**
kw
).
doctestsuite
()
def
ZopeDocFileSuite
(
*
paths
,
**
kw
):
def
ZopeDocFileSuite
(
*
paths
,
**
kw
):
if
kw
.
get
(
'module_relative'
,
True
):
if
kw
.
get
(
'module_relative'
,
True
):
kw
[
'package'
]
=
doctest
.
_normalize_module
(
kw
.
get
(
'package'
))
kw
[
'package'
]
=
doctest
.
_normalize_module
(
kw
.
get
(
'package'
))
return
ZopeSuiteFactory
(
*
paths
,
**
kw
).
docfilesuite
()
return
ZopeSuiteFactory
(
*
paths
,
**
kw
).
docfilesuite
()
def
FunctionalDocTestSuite
(
module
=
None
,
**
kw
):
def
FunctionalDocTestSuite
(
module
=
None
,
**
kw
):
module
=
doctest
.
_normalize_module
(
module
)
module
=
doctest
.
_normalize_module
(
module
)
return
FunctionalSuiteFactory
(
module
,
**
kw
).
doctestsuite
()
return
FunctionalSuiteFactory
(
module
,
**
kw
).
doctestsuite
()
def
FunctionalDocFileSuite
(
*
paths
,
**
kw
):
def
FunctionalDocFileSuite
(
*
paths
,
**
kw
):
if
kw
.
get
(
'module_relative'
,
True
):
if
kw
.
get
(
'module_relative'
,
True
):
kw
[
'package'
]
=
doctest
.
_normalize_module
(
kw
.
get
(
'package'
))
kw
[
'package'
]
=
doctest
.
_normalize_module
(
kw
.
get
(
'package'
))
...
@@ -335,5 +345,4 @@ __all__ = [
...
@@ -335,5 +345,4 @@ __all__ = [
'ZopeDocFileSuite'
,
'ZopeDocFileSuite'
,
'FunctionalDocTestSuite'
,
'FunctionalDocTestSuite'
,
'FunctionalDocFileSuite'
,
'FunctionalDocFileSuite'
,
]
]
src/Testing/common.py
deleted
100644 → 0
View file @
2e9d01ea
# Default test runner
import
unittest
TestRunner
=
unittest
.
TextTestRunner
def
debug
():
test_suite
().
debug
()
def
pdebug
():
import
pdb
pdb
.
run
(
'debug()'
)
def
test_suite
():
# The default test suite includes every subclass of TestCase in
# the module, with 'test' as the test method prefix.
ClassType
=
type
(
unittest
.
TestCase
)
tests
=
[]
for
v
in
globals
().
values
():
if
isinstance
(
v
,
ClassType
)
and
issubclass
(
v
,
unittest
.
TestCase
):
tests
.
append
(
unittest
.
makeSuite
(
v
))
if
len
(
tests
)
>
1
:
return
unittest
.
TestSuite
(
tests
)
if
len
(
tests
)
==
1
:
return
tests
[
0
]
return
class
Dummy
:
'''Utility class for quick & dirty instances'''
def
__init__
(
self
,
**
kw
):
self
.
__dict__
.
update
(
kw
)
def
__str__
(
self
):
return
'Dummy(%s)'
%
`self.__dict__`
__repr__
=
__str__
src/Testing/custom_zodb.py
View file @
efe61189
import
os
import
os
import
logging
import
logging
import
ZODB
LOG
=
logging
.
getLogger
(
'Testing'
)
LOG
=
logging
.
getLogger
(
'Testing'
)
def
getStorage
():
def
getStorage
():
""" Return a storage instance for running ZopeTestCase based
""" Return a storage instance for running ZopeTestCase based
tests. By default a DemoStorage is used. Setting
tests. By default a DemoStorage is used. Setting
...
@@ -15,14 +14,14 @@ def getStorage():
...
@@ -15,14 +14,14 @@ def getStorage():
get
=
os
.
environ
.
get
get
=
os
.
environ
.
get
if
os
.
environ
.
has_key
(
'TEST_ZEO_HOST'
)
and
os
.
environ
.
has_key
(
'TEST_ZEO_PORT'
)
:
if
'TEST_ZEO_HOST'
in
os
.
environ
and
'TEST_ZEO_PORT'
in
os
.
environ
:
from
ZEO.ClientStorage
import
ClientStorage
from
ZEO.ClientStorage
import
ClientStorage
zeo_host
=
get
(
'TEST_ZEO_HOST'
)
zeo_host
=
get
(
'TEST_ZEO_HOST'
)
zeo_port
=
int
(
get
(
'TEST_ZEO_PORT'
))
zeo_port
=
int
(
get
(
'TEST_ZEO_PORT'
))
LOG
.
info
(
'Using ZEO server (%s:%d)'
%
(
zeo_host
,
zeo_port
))
LOG
.
info
(
'Using ZEO server (%s:%d)'
%
(
zeo_host
,
zeo_port
))
return
ClientStorage
((
zeo_host
,
zeo_port
))
return
ClientStorage
((
zeo_host
,
zeo_port
))
elif
os
.
environ
.
has_key
(
'TEST_FILESTORAGE'
)
:
elif
'TEST_FILESTORAGE'
in
os
.
environ
:
import
ZODB.FileStorage
import
ZODB.FileStorage
datafs
=
get
(
'TEST_FILESTORAGE'
)
datafs
=
get
(
'TEST_FILESTORAGE'
)
LOG
.
info
(
'Using Filestorage at (%s)'
%
datafs
)
LOG
.
info
(
'Using Filestorage at (%s)'
%
datafs
)
...
...
src/Testing/dispatcher.py
deleted
100644 → 0
View file @
2e9d01ea
##############################################################################
#
# Copyright (c) 2002 Zope Foundation and Contributors.
#
# 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
#
##############################################################################
# Dispatcher for usage inside Zope test environment
# Andreas Jung, andreas@digicool.com 03/24/2001
import
os
,
sys
,
re
,
string
import
threading
,
time
,
commands
,
profile
class
Dispatcher
:
"""
a multi-purpose thread dispatcher
"""
def
__init__
(
self
,
func
=
''
):
self
.
fp
=
sys
.
stderr
self
.
f_startup
=
[]
self
.
f_teardown
=
[]
self
.
lastlog
=
""
self
.
lock
=
threading
.
Lock
()
self
.
func
=
func
self
.
profiling
=
0
self
.
doc
=
getattr
(
self
,
self
.
func
).
__doc__
def
setlog
(
self
,
fp
):
self
.
fp
=
fp
def
log
(
self
,
s
):
if
s
==
self
.
lastlog
:
return
self
.
fp
.
write
(
s
)
self
.
fp
.
flush
()
self
.
lastlog
=
s
def
logn
(
self
,
s
):
if
s
==
self
.
lastlog
:
return
self
.
fp
.
write
(
s
+
'
\
n
'
)
self
.
fp
.
flush
()
self
.
lastlog
=
s
def
profiling_on
():
self
.
profiling
=
1
def
profiling_off
():
self
.
profiling
=
0
def
dispatcher
(
self
,
name
=
''
,
*
params
):
""" dispatcher for threads
The dispatcher expects one or several tupels:
(functionname, number of threads to start , args, keyword args)
"""
self
.
mem_usage
=
[
-
1
]
mem_watcher
=
threading
.
Thread
(
None
,
self
.
mem_watcher
,
name
=
'memwatcher'
)
mem_watcher
.
start
()
self
.
start_test
=
time
.
time
()
self
.
name
=
name
self
.
th_data
=
{}
self
.
runtime
=
{}
self
.
_threads
=
[]
s2s
=
self
.
s2s
for
func
,
numthreads
,
args
,
kw
in
params
:
f
=
getattr
(
self
,
func
)
for
i
in
range
(
0
,
numthreads
):
kw
[
't_func'
]
=
func
th
=
threading
.
Thread
(
None
,
self
.
worker
,
name
=
"TH_%s_%03d"
%
(
func
,
i
)
,
args
=
args
,
kwargs
=
kw
)
self
.
_threads
.
append
(
th
)
for
th
in
self
.
_threads
:
th
.
start
()
while
threading
.
activeCount
()
>
1
:
time
.
sleep
(
1
)
self
.
logn
(
'ID: %s '
%
self
.
name
)
self
.
logn
(
'FUNC: %s '
%
self
.
func
)
self
.
logn
(
'DOC: %s '
%
self
.
doc
)
self
.
logn
(
'Args: %s'
%
params
)
for
th
in
self
.
_threads
:
self
.
logn
(
'%-30s ........................ %9.3f sec'
%
(
th
.
getName
(),
self
.
runtime
[
th
.
getName
()])
)
for
k
,
v
in
self
.
th_data
[
th
.
getName
()].
items
():
self
.
logn
(
'%-30s %-15s = %s'
%
(
' '
,
k
,
v
)
)
self
.
logn
(
""
)
self
.
logn
(
'Complete running time: %9.3f sec'
%
(
time
.
time
()
-
self
.
start_test
)
)
if
len
(
self
.
mem_usage
)
>
1
:
self
.
mem_usage
.
remove
(
-
1
)
self
.
logn
(
"Memory: start: %s, end: %s, low: %s, high: %s"
%
\
(
s2s
(
self
.
mem_usage
[
0
]),
s2s
(
self
.
mem_usage
[
-
1
]),
s2s
(
min
(
self
.
mem_usage
)),
s2s
(
max
(
self
.
mem_usage
))))
self
.
logn
(
''
)
def
worker
(
self
,
*
args
,
**
kw
):
for
func
in
self
.
f_startup
:
f
=
getattr
(
self
,
func
)()
t_func
=
getattr
(
self
,
kw
[
't_func'
])
del
kw
[
't_func'
]
ts
=
time
.
time
()
apply
(
t_func
,
args
,
kw
)
te
=
time
.
time
()
for
func
in
self
.
f_teardown
:
getattr
(
self
,
func
)()
def
th_setup
(
self
):
""" initalize thread with some environment data """
env
=
{
'start'
:
time
.
time
()
}
return
env
def
th_teardown
(
self
,
env
,
**
kw
):
""" famous last actions of thread """
self
.
lock
.
acquire
()
self
.
th_data
[
threading
.
currentThread
().
getName
()
]
=
kw
self
.
runtime
[
threading
.
currentThread
().
getName
()
]
=
time
.
time
()
-
env
[
'start'
]
self
.
lock
.
release
()
def
getmem
(
self
):
""" try to determine the current memory usage """
if
not
sys
.
platform
in
[
'linux2'
]:
return
None
cmd
=
'/bin/ps --no-headers -o pid,vsize --pid %s'
%
os
.
getpid
()
outp
=
commands
.
getoutput
(
cmd
)
pid
,
vsize
=
filter
(
lambda
x
:
x
!=
""
,
string
.
split
(
outp
,
" "
)
)
data
=
open
(
"/proc/%d/statm"
%
os
.
getpid
()).
read
()
fields
=
re
.
split
(
" "
,
data
)
mem
=
string
.
atoi
(
fields
[
0
])
*
4096
return
mem
def
mem_watcher
(
self
):
""" thread for watching memory usage """
running
=
1
while
running
==
1
:
self
.
mem_usage
.
append
(
self
.
getmem
()
)
time
.
sleep
(
1
)
if
threading
.
activeCount
()
==
2
:
running
=
0
def
register_startup
(
self
,
func
):
self
.
f_startup
.
append
(
func
)
def
register_teardown
(
self
,
func
):
self
.
f_teardown
.
append
(
func
)
def
s2s
(
self
,
n
):
import
math
if
n
<
1024.0
:
return
"%8.3lf Bytes"
%
n
if
n
<
1024.0
*
1024.0
:
return
"%8.3lf KB"
%
(
1.0
*
n
/
1024.0
)
if
n
<
1024.0
*
1024.0
*
1024.0
:
return
"%8.3lf MB"
%
(
1.0
*
n
/
1024.0
/
1024.0
)
else
:
return
n
if
__name__
==
"__main__"
:
d
=
Dispatcher
()
print
d
.
getmem
()
pass
src/Testing/makerequest.py
View file @
efe61189
...
@@ -15,12 +15,12 @@ Facilitates unit tests which requires an acquirable REQUEST from
...
@@ -15,12 +15,12 @@ Facilitates unit tests which requires an acquirable REQUEST from
ZODB objects
ZODB objects
"""
"""
import
os
from
sys
import
stdin
,
stdout
from
sys
import
stdin
,
stdout
from
ZPublisher.HTTPRequest
import
HTTPRequest
from
ZPublisher.HTTPRequest
import
HTTPRequest
from
ZPublisher.HTTPResponse
import
HTTPResponse
from
ZPublisher.HTTPResponse
import
HTTPResponse
from
ZPublisher.BaseRequest
import
RequestContainer
from
ZPublisher.BaseRequest
import
RequestContainer
def
makerequest
(
app
,
stdout
=
stdout
,
environ
=
None
):
def
makerequest
(
app
,
stdout
=
stdout
,
environ
=
None
):
"""
"""
Adds an HTTPRequest at app.REQUEST, and returns
Adds an HTTPRequest at app.REQUEST, and returns
...
@@ -57,10 +57,9 @@ def makerequest(app, stdout=stdout, environ=None):
...
@@ -57,10 +57,9 @@ def makerequest(app, stdout=stdout, environ=None):
req
.
_steps
=
[
'noobject'
]
# Fake a published object.
req
.
_steps
=
[
'noobject'
]
# Fake a published object.
req
[
'ACTUAL_URL'
]
=
req
.
get
(
'URL'
)
# Zope 2.7.4
req
[
'ACTUAL_URL'
]
=
req
.
get
(
'URL'
)
# Zope 2.7.4
# set Zope3-style default skin so that the request is usable for
# Set default skin so that the request is usable for view look-ups.
# Zope3-style view look-ups.
from
zope.publisher.browser
import
setDefaultSkin
from
zope.publisher.browser
import
setDefaultSkin
setDefaultSkin
(
req
)
setDefaultSkin
(
req
)
requestcontainer
=
RequestContainer
(
REQUEST
=
req
)
requestcontainer
=
RequestContainer
(
REQUEST
=
req
)
return
app
.
__of__
(
requestcontainer
)
return
app
.
__of__
(
requestcontainer
)
src/Testing/tests/__init__.py
View file @
efe61189
#
src/Testing/tests/test_makerequest.py
View file @
efe61189
...
@@ -19,6 +19,7 @@ from Acquisition import Implicit
...
@@ -19,6 +19,7 @@ from Acquisition import Implicit
from
Testing.makerequest
import
makerequest
from
Testing.makerequest
import
makerequest
from
OFS.SimpleItem
import
SimpleItem
from
OFS.SimpleItem
import
SimpleItem
class
MakerequestTests
(
unittest
.
TestCase
):
class
MakerequestTests
(
unittest
.
TestCase
):
def
test_makerequest
(
self
):
def
test_makerequest
(
self
):
...
@@ -57,8 +58,3 @@ class MakerequestTests(unittest.TestCase):
...
@@ -57,8 +58,3 @@ class MakerequestTests(unittest.TestCase):
environ
=
{
'foofoo'
:
'barbar'
}
environ
=
{
'foofoo'
:
'barbar'
}
item
=
makerequest
(
SimpleItem
(),
environ
=
environ
)
item
=
makerequest
(
SimpleItem
(),
environ
=
environ
)
self
.
assertEqual
(
item
.
REQUEST
.
environ
[
'foofoo'
],
'barbar'
)
self
.
assertEqual
(
item
.
REQUEST
.
environ
[
'foofoo'
],
'barbar'
)
def
test_suite
():
suite
=
unittest
.
TestSuite
()
suite
.
addTest
(
unittest
.
makeSuite
(
MakerequestTests
))
return
suite
src/Testing/tests/test_testbrowser.py
View file @
efe61189
...
@@ -18,6 +18,7 @@ import unittest
...
@@ -18,6 +18,7 @@ import unittest
from
Testing.ZopeTestCase
import
FunctionalDocTestSuite
from
Testing.ZopeTestCase
import
FunctionalDocTestSuite
from
OFS.SimpleItem
import
Item
from
OFS.SimpleItem
import
Item
class
CookieStub
(
Item
):
class
CookieStub
(
Item
):
"""This is a cookie stub."""
"""This is a cookie stub."""
...
@@ -25,6 +26,7 @@ class CookieStub(Item):
...
@@ -25,6 +26,7 @@ class CookieStub(Item):
REQUEST
.
RESPONSE
.
setCookie
(
'evil'
,
'cookie'
)
REQUEST
.
RESPONSE
.
setCookie
(
'evil'
,
'cookie'
)
return
'Stub'
return
'Stub'
def
doctest_cookies
():
def
doctest_cookies
():
"""
"""
We want to make sure that our testbrowser correctly understands
We want to make sure that our testbrowser correctly understands
...
@@ -52,6 +54,7 @@ def doctest_cookies():
...
@@ -52,6 +54,7 @@ def doctest_cookies():
True
True
"""
"""
def
doctest_camel_case_headers
():
def
doctest_camel_case_headers
():
"""Make sure that the headers come out in camel case.
"""Make sure that the headers come out in camel case.
...
...
src/ZPublisher/BaseRequest.py
View file @
efe61189
...
@@ -14,11 +14,13 @@
...
@@ -14,11 +14,13 @@
"""
"""
from
urllib
import
quote
as
urllib_quote
from
urllib
import
quote
as
urllib_quote
import
types
import
xmlrpc
import
xmlrpc
from
AccessControl.ZopeSecurityPolicy
import
getRoles
from
Acquisition
import
aq_base
from
Acquisition
import
aq_base
from
Acquisition.interfaces
import
IAcquirer
from
Acquisition.interfaces
import
IAcquirer
from
ZPublisher.interfaces
import
UseTraversalDefault
from
ExtensionClass
import
Base
from
zExceptions
import
Forbidden
from
zExceptions
import
Forbidden
from
zExceptions
import
NotFound
from
zExceptions
import
NotFound
from
zope.component
import
queryMultiAdapter
from
zope.component
import
queryMultiAdapter
...
@@ -34,6 +36,10 @@ from zope.publisher.interfaces.browser import IBrowserPublisher
...
@@ -34,6 +36,10 @@ from zope.publisher.interfaces.browser import IBrowserPublisher
from
zope.traversing.namespace
import
namespaceLookup
from
zope.traversing.namespace
import
namespaceLookup
from
zope.traversing.namespace
import
nsParse
from
zope.traversing.namespace
import
nsParse
from
ZPublisher.Converters
import
type_converters
from
ZPublisher.interfaces
import
UseTraversalDefault
_marker
=
[]
UNSPECIFIED_ROLES
=
''
UNSPECIFIED_ROLES
=
''
...
@@ -41,28 +47,17 @@ def quote(text):
...
@@ -41,28 +47,17 @@ def quote(text):
# quote url path segments, but leave + and @ intact
# quote url path segments, but leave + and @ intact
return
urllib_quote
(
text
,
'/+@'
)
return
urllib_quote
(
text
,
'/+@'
)
try
:
from
ExtensionClass
import
Base
class
RequestContainer
(
Base
):
from
ZPublisher.Converters
import
type_converters
__roles__
=
None
class
RequestContainer
(
Base
):
__roles__
=
None
def
__init__
(
self
,
**
kw
):
def
__init__
(
self
,
**
kw
):
for
k
,
v
in
kw
.
items
(
):
for
k
,
v
in
kw
.
items
():
self
.
__dict__
[
k
]
=
v
self
.
__dict__
[
k
]
=
v
def
manage_property_types
(
self
):
def
manage_property_types
(
self
):
return
type_converters
.
keys
()
return
type_converters
.
keys
()
except
ImportError
:
class
RequestContainer
:
__roles__
=
None
def
__init__
(
self
,
**
kw
):
for
k
,
v
in
kw
.
items
():
self
.
__dict__
[
k
]
=
v
try
:
from
AccessControl.ZopeSecurityPolicy
import
getRoles
except
ImportError
:
def
getRoles
(
container
,
name
,
value
,
default
):
return
getattr
(
value
,
'__roles__'
,
default
)
class
DefaultPublishTraverse
(
object
):
class
DefaultPublishTraverse
(
object
):
...
@@ -74,35 +69,39 @@ class DefaultPublishTraverse(object):
...
@@ -74,35 +69,39 @@ class DefaultPublishTraverse(object):
def
publishTraverse
(
self
,
request
,
name
):
def
publishTraverse
(
self
,
request
,
name
):
object
=
self
.
context
object
=
self
.
context
URL
=
request
[
'URL'
]
URL
=
request
[
'URL'
]
if
name
[:
1
]
==
'_'
:
if
name
[:
1
]
==
'_'
:
raise
Forbidden
(
"Object name begins with an underscore at: %s"
%
URL
)
raise
Forbidden
(
"Object name begins with an underscore at: %s"
%
URL
)
subobject
=
UseTraversalDefault
# indicator
subobject
=
UseTraversalDefault
# indicator
try
:
try
:
if
hasattr
(
object
,
'__bobo_traverse__'
):
if
hasattr
(
object
,
'__bobo_traverse__'
):
try
:
try
:
subobject
=
object
.
__bobo_traverse__
(
request
,
name
)
subobject
=
object
.
__bobo_traverse__
(
request
,
name
)
if
type
(
subobject
)
is
type
(()
)
and
len
(
subobject
)
>
1
:
if
isinstance
(
subobject
,
tuple
)
and
len
(
subobject
)
>
1
:
# Add additional parents into the path
# Add additional parents into the path
# XXX There are no tests for this:
# XXX There are no tests for this:
request
[
'PARENTS'
][
-
1
:]
=
list
(
subobject
[:
-
1
])
request
[
'PARENTS'
][
-
1
:]
=
list
(
subobject
[:
-
1
])
object
,
subobject
=
subobject
[
-
2
:]
object
,
subobject
=
subobject
[
-
2
:]
except
(
AttributeError
,
KeyError
,
NotFound
)
,
e
:
except
(
AttributeError
,
KeyError
,
NotFound
)
as
e
:
# Try to find a view
# Try to find a view
subobject
=
queryMultiAdapter
((
object
,
request
),
Interface
,
name
)
subobject
=
queryMultiAdapter
(
(
object
,
request
),
Interface
,
name
)
if
subobject
is
not
None
:
if
subobject
is
not
None
:
# OFS.Application.__bobo_traverse__ calls
# OFS.Application.__bobo_traverse__ calls
# REQUEST.RESPONSE.notFoundError which sets the HTTP
# REQUEST.RESPONSE.notFoundError which sets the HTTP
# status code to 404
# status code to 404
request
.
response
.
setStatus
(
200
)
request
.
response
.
setStatus
(
200
)
# We don't need to do the docstring security check
# We don't need to do the docstring security check
# for views, so lets skip it and return the object here.
# for views, so lets skip it and
# return the object here.
if
IAcquirer
.
providedBy
(
subobject
):
if
IAcquirer
.
providedBy
(
subobject
):
subobject
=
subobject
.
__of__
(
object
)
subobject
=
subobject
.
__of__
(
object
)
return
subobject
return
subobject
# No view found. Reraise the error raised by __bobo_traverse__
# No view found. Reraise the error
# raised by __bobo_traverse__
raise
e
raise
e
except
UseTraversalDefault
:
except
UseTraversalDefault
:
pass
pass
...
@@ -123,9 +122,9 @@ class DefaultPublishTraverse(object):
...
@@ -123,9 +122,9 @@ class DefaultPublishTraverse(object):
# And lastly, of there is no view, try acquired attributes, but
# And lastly, of there is no view, try acquired attributes, but
# only if there is no __bobo_traverse__:
# only if there is no __bobo_traverse__:
try
:
try
:
subobject
=
getattr
(
object
,
name
)
subobject
=
getattr
(
object
,
name
)
# Again, clear any error status created by
__bobo_traverse__
# Again, clear any error status created by
# because we actually found something:
#
__bobo_traverse__
because we actually found something:
request
.
response
.
setStatus
(
200
)
request
.
response
.
setStatus
(
200
)
except
AttributeError
:
except
AttributeError
:
pass
pass
...
@@ -143,21 +142,15 @@ class DefaultPublishTraverse(object):
...
@@ -143,21 +142,15 @@ class DefaultPublishTraverse(object):
doc
=
getattr
(
subobject
,
'__doc__'
,
None
)
doc
=
getattr
(
subobject
,
'__doc__'
,
None
)
if
not
doc
:
if
not
doc
:
raise
Forbidden
(
raise
Forbidden
(
"The object at %s has an empty or missing "
\
"The object at %s has an empty or missing "
"docstring. Objects must have a docstring to be "
\
"docstring. Objects must have a docstring to be "
"published."
%
URL
"published."
%
URL
)
)
# Hack for security: in Python 2.2.2, most built-in types
# Check that built-in types aren't publishable.
# gained docstrings that they didn't have before. That caused
# certain mutable types (dicts, lists) to become publishable
# when they shouldn't be. The following check makes sure that
# the right thing happens in both 2.2.2+ and earlier versions.
if
not
typeCheck
(
subobject
):
if
not
typeCheck
(
subobject
):
raise
Forbidden
(
raise
Forbidden
(
"The object at %s is not publishable."
%
URL
"The object at %s is not publishable."
%
URL
)
)
return
subobject
return
subobject
...
@@ -175,7 +168,6 @@ class DefaultPublishTraverse(object):
...
@@ -175,7 +168,6 @@ class DefaultPublishTraverse(object):
return
self
.
context
,
()
return
self
.
context
,
()
_marker
=
[]
class
BaseRequest
:
class
BaseRequest
:
"""Provide basic ZPublisher request management
"""Provide basic ZPublisher request management
...
@@ -196,25 +188,27 @@ class BaseRequest:
...
@@ -196,25 +188,27 @@ class BaseRequest:
# acquisition of REQUEST is disallowed, which penalizes access
# acquisition of REQUEST is disallowed, which penalizes access
# in DTML with tags.
# in DTML with tags.
__roles__
=
None
__roles__
=
None
_file
=
None
_file
=
None
common
=
{}
# Common request data
common
=
{}
# Common request data
_auth
=
None
_auth
=
None
_held
=
()
_held
=
()
# Allow (reluctantly) access to unprotected attributes
# Allow (reluctantly) access to unprotected attributes
__allow_access_to_unprotected_subobjects__
=
1
__allow_access_to_unprotected_subobjects__
=
1
def
__init__
(
self
,
other
=
None
,
**
kw
):
def
__init__
(
self
,
other
=
None
,
**
kw
):
"""The constructor is not allowed to raise errors
"""The constructor is not allowed to raise errors
"""
"""
self
.
__doc__
=
None
# Make BaseRequest objects unpublishable
self
.
__doc__
=
None
# Make BaseRequest objects unpublishable
if
other
is
None
:
other
=
kw
if
other
is
None
:
else
:
other
.
update
(
kw
)
other
=
kw
self
.
other
=
other
else
:
other
.
update
(
kw
)
self
.
other
=
other
def
clear
(
self
):
def
clear
(
self
):
self
.
other
.
clear
()
self
.
other
.
clear
()
self
.
_held
=
None
self
.
_held
=
None
def
close
(
self
):
def
close
(
self
):
try
:
try
:
...
@@ -231,15 +225,15 @@ class BaseRequest:
...
@@ -231,15 +225,15 @@ class BaseRequest:
def
__len__
(
self
):
def
__len__
(
self
):
return
1
return
1
def
__setitem__
(
self
,
key
,
value
):
def
__setitem__
(
self
,
key
,
value
):
"""Set application variables
"""Set application variables
This method is used to set a variable in the requests "other"
This method is used to set a variable in the requests "other"
category.
category.
"""
"""
self
.
other
[
key
]
=
value
self
.
other
[
key
]
=
value
set
=
__setitem__
set
=
__setitem__
def
get
(
self
,
key
,
default
=
None
):
def
get
(
self
,
key
,
default
=
None
):
"""Get a variable value
"""Get a variable value
...
@@ -250,24 +244,27 @@ class BaseRequest:
...
@@ -250,24 +244,27 @@ class BaseRequest:
other variables, form data, and then cookies.
other variables, form data, and then cookies.
"""
"""
if
key
==
'REQUEST'
:
return
self
if
key
==
'REQUEST'
:
return
self
v
=
self
.
other
.
get
(
key
,
_marker
)
v
=
self
.
other
.
get
(
key
,
_marker
)
if
v
is
not
_marker
:
return
v
if
v
is
not
_marker
:
v
=
self
.
common
.
get
(
key
,
default
)
return
v
if
v
is
not
_marker
:
return
v
v
=
self
.
common
.
get
(
key
,
default
)
if
v
is
not
_marker
:
return
v
if
key
==
'BODY'
and
self
.
_file
is
not
None
:
if
key
==
'BODY'
and
self
.
_file
is
not
None
:
p
=
self
.
_file
.
tell
()
p
=
self
.
_file
.
tell
()
self
.
_file
.
seek
(
0
)
self
.
_file
.
seek
(
0
)
v
=
self
.
_file
.
read
()
v
=
self
.
_file
.
read
()
self
.
_file
.
seek
(
p
)
self
.
_file
.
seek
(
p
)
self
.
other
[
key
]
=
v
self
.
other
[
key
]
=
v
return
v
return
v
if
key
==
'BODYFILE'
and
self
.
_file
is
not
None
:
if
key
==
'BODYFILE'
and
self
.
_file
is
not
None
:
v
=
self
.
_file
v
=
self
.
_file
self
.
other
[
key
]
=
v
self
.
other
[
key
]
=
v
return
v
return
v
return
default
return
default
...
@@ -275,7 +272,7 @@ class BaseRequest:
...
@@ -275,7 +272,7 @@ class BaseRequest:
def
__getitem__
(
self
,
key
,
default
=
_marker
):
def
__getitem__
(
self
,
key
,
default
=
_marker
):
v
=
self
.
get
(
key
,
default
)
v
=
self
.
get
(
key
,
default
)
if
v
is
_marker
:
if
v
is
_marker
:
raise
KeyError
,
key
raise
KeyError
(
key
)
return
v
return
v
def
__bobo_traverse__
(
self
,
name
):
def
__bobo_traverse__
(
self
,
name
):
...
@@ -284,17 +281,17 @@ class BaseRequest:
...
@@ -284,17 +281,17 @@ class BaseRequest:
def
__getattr__
(
self
,
key
,
default
=
_marker
):
def
__getattr__
(
self
,
key
,
default
=
_marker
):
v
=
self
.
get
(
key
,
default
)
v
=
self
.
get
(
key
,
default
)
if
v
is
_marker
:
if
v
is
_marker
:
raise
AttributeError
,
key
raise
AttributeError
(
key
)
return
v
return
v
def
set_lazy
(
self
,
key
,
callable
):
def
set_lazy
(
self
,
key
,
callable
):
pass
# MAYBE, we could do more, but let HTTPRequest do it
pass
# MAYBE, we could do more, but let HTTPRequest do it
def
has_key
(
self
,
key
):
def
has_key
(
self
,
key
):
return
self
.
get
(
key
,
_marker
)
is
not
_marker
return
key
in
self
def
__contains__
(
self
,
key
):
def
__contains__
(
self
,
key
):
return
self
.
has_key
(
key
)
return
self
.
get
(
key
,
_marker
)
is
not
_marker
def
keys
(
self
):
def
keys
(
self
):
keys
=
{}
keys
=
{}
...
@@ -304,16 +301,14 @@ class BaseRequest:
...
@@ -304,16 +301,14 @@ class BaseRequest:
def
items
(
self
):
def
items
(
self
):
result
=
[]
result
=
[]
get
=
self
.
get
for
k
in
self
.
keys
():
for
k
in
self
.
keys
():
result
.
append
((
k
,
get
(
k
)))
result
.
append
((
k
,
self
.
get
(
k
)))
return
result
return
result
def
values
(
self
):
def
values
(
self
):
result
=
[]
result
=
[]
get
=
self
.
get
for
k
in
self
.
keys
():
for
k
in
self
.
keys
():
result
.
append
(
get
(
k
))
result
.
append
(
self
.
get
(
k
))
return
result
return
result
def
__str__
(
self
):
def
__str__
(
self
):
...
@@ -321,7 +316,7 @@ class BaseRequest:
...
@@ -321,7 +316,7 @@ class BaseRequest:
L1
.
sort
()
L1
.
sort
()
return
'
\
n
'
.
join
(
"%s:
\
t
%s"
%
item
for
item
in
L1
)
return
'
\
n
'
.
join
(
"%s:
\
t
%s"
%
item
for
item
in
L1
)
__repr__
=
__str__
__repr__
=
__str__
# Original version: see zope.traversing.publicationtraverse
# Original version: see zope.traversing.publicationtraverse
def
traverseName
(
self
,
ob
,
name
):
def
traverseName
(
self
,
ob
,
name
):
...
@@ -346,8 +341,8 @@ class BaseRequest:
...
@@ -346,8 +341,8 @@ class BaseRequest:
else
:
else
:
adapter
=
queryMultiAdapter
((
ob
,
self
),
IPublishTraverse
)
adapter
=
queryMultiAdapter
((
ob
,
self
),
IPublishTraverse
)
if
adapter
is
None
:
if
adapter
is
None
:
#
#
Zope2 doesn't set up its own adapters in a lot of cases
# Zope2 doesn't set up its own adapters in a lot of cases
#
#
so we will just use a default adapter.
# so we will just use a default adapter.
adapter
=
DefaultPublishTraverse
(
ob
,
self
)
adapter
=
DefaultPublishTraverse
(
ob
,
self
)
ob2
=
adapter
.
publishTraverse
(
self
,
name
)
ob2
=
adapter
.
publishTraverse
(
self
,
name
)
...
@@ -361,59 +356,64 @@ class BaseRequest:
...
@@ -361,59 +356,64 @@ class BaseRequest:
The REQUEST must already have a PARENTS item with at least one
The REQUEST must already have a PARENTS item with at least one
object in it. This is typically the root object.
object in it. This is typically the root object.
"""
"""
request
=
self
request
=
self
request_get
=
request
.
get
request_get
=
request
.
get
if
response
is
None
:
response
=
self
.
response
if
response
is
None
:
response
=
self
.
response
# remember path for later use
# remember path for later use
browser_path
=
path
browser_path
=
path
# Cleanup the path list
# Cleanup the path list
if
path
[:
1
]
==
'/'
:
path
=
path
[
1
:]
if
path
[:
1
]
==
'/'
:
if
path
[
-
1
:]
==
'/'
:
path
=
path
[:
-
1
]
path
=
path
[
1
:]
clean
=
[]
if
path
[
-
1
:]
==
'/'
:
path
=
path
[:
-
1
]
clean
=
[]
for
item
in
path
.
split
(
'/'
):
for
item
in
path
.
split
(
'/'
):
# Make sure that certain things that dont make sense
# Make sure that certain things that dont make sense
# cannot be traversed.
# cannot be traversed.
if
item
in
(
'REQUEST'
,
'aq_self'
,
'aq_base'
):
if
item
in
(
'REQUEST'
,
'aq_self'
,
'aq_base'
):
return
response
.
notFoundError
(
path
)
return
response
.
notFoundError
(
path
)
if
not
item
or
item
==
'.'
:
if
not
item
or
item
==
'.'
:
continue
continue
elif
item
==
'..'
:
elif
item
==
'..'
:
del
clean
[
-
1
]
del
clean
[
-
1
]
else
:
clean
.
append
(
item
)
else
:
path
=
clean
clean
.
append
(
item
)
path
=
clean
# How did this request come in? (HTTP GET, PUT, POST, etc.)
# How did this request come in? (HTTP GET, PUT, POST, etc.)
method
=
request_get
(
'REQUEST_METHOD'
,
'GET'
).
upper
()
method
=
request_get
(
'REQUEST_METHOD'
,
'GET'
).
upper
()
if
method
in
[
"GET"
,
"POST"
,
"PURGE"
]
and
not
isinstance
(
response
,
if
(
method
in
[
"GET"
,
"POST"
,
"PURGE"
]
and
xmlrpc
.
Response
):
not
isinstance
(
response
,
xmlrpc
.
Response
)
):
# Probably a browser
# Probably a browser
no_acquire_flag
=
0
no_acquire_flag
=
0
# index_html is still the default method, only any object can
# index_html is still the default method, only any object can
# override it by implementing its own __browser_default__ method
# override it by implementing its own __browser_default__ method
method
=
'index_html'
method
=
'index_html'
elif
self
.
maybe_webdav_client
:
elif
self
.
maybe_webdav_client
:
# Probably a WebDAV client.
# Probably a WebDAV client.
no_acquire_flag
=
1
no_acquire_flag
=
1
else
:
else
:
no_acquire_flag
=
0
no_acquire_flag
=
0
URL
=
request
[
'URL'
]
URL
=
request
[
'URL'
]
parents
=
request
[
'PARENTS'
]
parents
=
request
[
'PARENTS'
]
object
=
parents
[
-
1
]
object
=
parents
[
-
1
]
del
parents
[:]
del
parents
[:]
self
.
roles
=
getRoles
(
None
,
None
,
object
,
UNSPECIFIED_ROLES
)
self
.
roles
=
getRoles
(
None
,
None
,
object
,
UNSPECIFIED_ROLES
)
# if the top object has a __bobo_traverse__ method, then use it
# if the top object has a __bobo_traverse__ method, then use it
# to possibly traverse to an alternate top-level object.
# to possibly traverse to an alternate top-level object.
if
hasattr
(
object
,
'__bobo_traverse__'
):
if
hasattr
(
object
,
'__bobo_traverse__'
):
try
:
try
:
object
=
object
.
__bobo_traverse__
(
request
)
object
=
object
.
__bobo_traverse__
(
request
)
self
.
roles
=
getRoles
(
None
,
None
,
object
,
UNSPECIFIED_ROLES
)
self
.
roles
=
getRoles
(
None
,
None
,
object
,
UNSPECIFIED_ROLES
)
except
:
pass
except
Exception
:
pass
if
not
path
and
not
method
:
if
not
path
and
not
method
:
return
response
.
forbiddenError
(
self
[
'URL'
])
return
response
.
forbiddenError
(
self
[
'URL'
])
...
@@ -422,10 +422,10 @@ class BaseRequest:
...
@@ -422,10 +422,10 @@ class BaseRequest:
if
hasattr
(
object
,
'__of__'
):
if
hasattr
(
object
,
'__of__'
):
# Try to bind the top-level object to the request
# Try to bind the top-level object to the request
# This is how you get 'self.REQUEST'
# This is how you get 'self.REQUEST'
object
=
object
.
__of__
(
RequestContainer
(
REQUEST
=
request
))
object
=
object
.
__of__
(
RequestContainer
(
REQUEST
=
request
))
parents
.
append
(
object
)
parents
.
append
(
object
)
steps
=
self
.
steps
steps
=
self
.
steps
self
.
_steps
=
_steps
=
map
(
quote
,
steps
)
self
.
_steps
=
_steps
=
map
(
quote
,
steps
)
path
.
reverse
()
path
.
reverse
()
...
@@ -485,7 +485,7 @@ class BaseRequest:
...
@@ -485,7 +485,7 @@ class BaseRequest:
object
,
default_path
=
adapter
.
browserDefault
(
self
)
object
,
default_path
=
adapter
.
browserDefault
(
self
)
if
default_path
:
if
default_path
:
request
.
_hacked_path
=
1
request
.
_hacked_path
=
1
if
len
(
default_path
)
>
1
:
if
len
(
default_path
)
>
1
:
path
=
list
(
default_path
)
path
=
list
(
default_path
)
method
=
path
.
pop
()
method
=
path
.
pop
()
...
@@ -493,19 +493,21 @@ class BaseRequest:
...
@@ -493,19 +493,21 @@ class BaseRequest:
continue
continue
else
:
else
:
entry_name
=
default_path
[
0
]
entry_name
=
default_path
[
0
]
elif
(
method
and
hasattr
(
object
,
method
)
elif
(
method
and
hasattr
(
object
,
method
)
and
and
entry_name
!=
metho
d
entry_name
!=
method
an
d
and
getattr
(
object
,
method
)
is
not
None
):
getattr
(
object
,
method
)
is
not
None
):
request
.
_hacked_path
=
1
request
.
_hacked_path
=
1
entry_name
=
method
entry_name
=
method
method
=
'index_html'
method
=
'index_html'
else
:
else
:
if
hasattr
(
object
,
'__call__'
):
if
hasattr
(
object
,
'__call__'
):
self
.
roles
=
getRoles
(
object
,
'__call__'
,
object
.
__call__
,
self
.
roles
=
getRoles
(
self
.
roles
)
object
,
'__call__'
,
object
.
__call__
,
self
.
roles
)
if
request
.
_hacked_path
:
if
request
.
_hacked_path
:
i
=
URL
.
rfind
(
'/'
)
i
=
URL
.
rfind
(
'/'
)
if
i
>
0
:
response
.
setBase
(
URL
[:
i
])
if
i
>
0
:
response
.
setBase
(
URL
[:
i
])
break
break
step
=
quote
(
entry_name
)
step
=
quote
(
entry_name
)
_steps
.
append
(
step
)
_steps
.
append
(
step
)
...
@@ -513,7 +515,7 @@ class BaseRequest:
...
@@ -513,7 +515,7 @@ class BaseRequest:
try
:
try
:
subobject
=
self
.
traverseName
(
object
,
entry_name
)
subobject
=
self
.
traverseName
(
object
,
entry_name
)
if
(
hasattr
(
object
,
'__bobo_traverse__'
)
or
if
(
hasattr
(
object
,
'__bobo_traverse__'
)
or
hasattr
(
object
,
entry_name
)):
hasattr
(
object
,
entry_name
)):
check_name
=
entry_name
check_name
=
entry_name
else
:
else
:
...
@@ -530,7 +532,7 @@ class BaseRequest:
...
@@ -530,7 +532,7 @@ class BaseRequest:
"Cannot locate object at: %s"
%
URL
)
"Cannot locate object at: %s"
%
URL
)
else
:
else
:
return
response
.
notFoundError
(
URL
)
return
response
.
notFoundError
(
URL
)
except
Forbidden
,
e
:
except
Forbidden
as
e
:
if
self
.
response
.
debug_mode
:
if
self
.
response
.
debug_mode
:
return
response
.
debugError
(
e
.
args
)
return
response
.
debugError
(
e
.
args
)
else
:
else
:
...
@@ -553,11 +555,11 @@ class BaseRequest:
...
@@ -553,11 +555,11 @@ class BaseRequest:
# existing object :(
# existing object :(
if
(
no_acquire_flag
and
if
(
no_acquire_flag
and
hasattr
(
parents
[
1
],
'aq_base'
)
and
hasattr
(
parents
[
1
],
'aq_base'
)
and
not
hasattr
(
parents
[
1
],
'__bobo_traverse__'
)):
not
hasattr
(
parents
[
1
],
'__bobo_traverse__'
)):
base
=
parents
[
1
].
aq_base
base
=
parents
[
1
].
aq_base
if
not
hasattr
(
base
,
entry_name
):
if
not
hasattr
(
base
,
entry_name
):
try
:
try
:
if
not
entry_name
in
base
:
if
entry_name
not
in
base
:
raise
AttributeError
(
entry_name
)
raise
AttributeError
(
entry_name
)
except
TypeError
:
except
TypeError
:
raise
AttributeError
(
entry_name
)
raise
AttributeError
(
entry_name
)
...
@@ -568,74 +570,90 @@ class BaseRequest:
...
@@ -568,74 +570,90 @@ class BaseRequest:
request
[
'PUBLISHED'
]
=
parents
.
pop
(
0
)
request
[
'PUBLISHED'
]
=
parents
.
pop
(
0
)
# Do authorization checks
# Do authorization checks
user
=
groups
=
None
user
=
groups
=
None
i
=
0
i
=
0
if
1
:
# Always perform authentication.
if
1
:
# Always perform authentication.
last_parent_index
=
len
(
parents
)
last_parent_index
=
len
(
parents
)
if
hasattr
(
object
,
'__allow_groups__'
):
if
hasattr
(
object
,
'__allow_groups__'
):
groups
=
object
.
__allow_groups__
groups
=
object
.
__allow_groups__
inext
=
0
inext
=
0
else
:
else
:
inext
=
None
inext
=
None
for
i
in
range
(
last_parent_index
):
for
i
in
range
(
last_parent_index
):
if
hasattr
(
parents
[
i
],
'__allow_groups__'
):
if
hasattr
(
parents
[
i
],
'__allow_groups__'
):
groups
=
parents
[
i
].
__allow_groups__
groups
=
parents
[
i
].
__allow_groups__
inext
=
i
+
1
inext
=
i
+
1
break
break
if
inext
is
not
None
:
if
inext
is
not
None
:
i
=
inext
i
=
inext
if
hasattr
(
groups
,
'validate'
):
v
=
groups
.
validate
if
hasattr
(
groups
,
'validate'
):
else
:
v
=
old_validation
v
=
groups
.
validate
else
:
v
=
old_validation
auth
=
request
.
_auth
auth
=
request
.
_auth
if
v
is
old_validation
and
self
.
roles
is
UNSPECIFIED_ROLES
:
if
v
is
old_validation
and
self
.
roles
is
UNSPECIFIED_ROLES
:
# No roles, so if we have a named group, get roles from
# No roles, so if we have a named group, get roles from
# group keys
# group keys
if
hasattr
(
groups
,
'keys'
):
self
.
roles
=
groups
.
keys
()
if
hasattr
(
groups
,
'keys'
):
self
.
roles
=
groups
.
keys
()
else
:
else
:
try
:
groups
=
groups
()
try
:
except
:
pass
groups
=
groups
()
try
:
self
.
roles
=
groups
.
keys
()
except
Exception
:
except
:
pass
pass
try
:
self
.
roles
=
groups
.
keys
()
except
Exception
:
pass
if
groups
is
None
:
if
groups
is
None
:
# Public group, hack structures to get it to validate
# Public group, hack structures to get it to validate
self
.
roles
=
None
self
.
roles
=
None
auth
=
''
auth
=
''
if
v
is
old_validation
:
if
v
is
old_validation
:
user
=
old_validation
(
groups
,
request
,
auth
,
self
.
roles
)
user
=
old_validation
(
groups
,
request
,
auth
,
self
.
roles
)
elif
self
.
roles
is
UNSPECIFIED_ROLES
:
user
=
v
(
request
,
auth
)
elif
self
.
roles
is
UNSPECIFIED_ROLES
:
else
:
user
=
v
(
request
,
auth
,
self
.
roles
)
user
=
v
(
request
,
auth
)
else
:
user
=
v
(
request
,
auth
,
self
.
roles
)
while
user
is
None
and
i
<
last_parent_index
:
while
user
is
None
and
i
<
last_parent_index
:
parent
=
parents
[
i
]
parent
=
parents
[
i
]
i
=
i
+
1
i
=
i
+
1
if
hasattr
(
parent
,
'__allow_groups__'
):
if
hasattr
(
parent
,
'__allow_groups__'
):
groups
=
parent
.
__allow_groups__
groups
=
parent
.
__allow_groups__
else
:
continue
else
:
if
hasattr
(
groups
,
'validate'
):
v
=
groups
.
validate
continue
else
:
v
=
old_validation
if
hasattr
(
groups
,
'validate'
):
v
=
groups
.
validate
else
:
v
=
old_validation
if
v
is
old_validation
:
if
v
is
old_validation
:
user
=
old_validation
(
groups
,
request
,
auth
,
self
.
roles
)
user
=
old_validation
(
elif
self
.
roles
is
UNSPECIFIED_ROLES
:
user
=
v
(
request
,
auth
)
groups
,
request
,
auth
,
self
.
roles
)
else
:
user
=
v
(
request
,
auth
,
self
.
roles
)
elif
self
.
roles
is
UNSPECIFIED_ROLES
:
user
=
v
(
request
,
auth
)
else
:
user
=
v
(
request
,
auth
,
self
.
roles
)
if
user
is
None
and
self
.
roles
!=
UNSPECIFIED_ROLES
:
if
user
is
None
and
self
.
roles
!=
UNSPECIFIED_ROLES
:
response
.
unauthorized
()
response
.
unauthorized
()
if
user
is
not
None
:
if
user
is
not
None
:
if
validated_hook
is
not
None
:
validated_hook
(
self
,
user
)
if
validated_hook
is
not
None
:
request
[
'AUTHENTICATED_USER'
]
=
user
validated_hook
(
self
,
user
)
request
[
'AUTHENTICATION_PATH'
]
=
'/'
.
join
(
steps
[:
-
i
])
request
[
'AUTHENTICATED_USER'
]
=
user
request
[
'AUTHENTICATION_PATH'
]
=
'/'
.
join
(
steps
[:
-
i
])
# Remove http request method from the URL.
# Remove http request method from the URL.
request
[
'URL'
]
=
URL
request
[
'URL'
]
=
URL
# Run post traversal hooks
# Run post traversal hooks
if
post_traverse
:
if
post_traverse
:
...
@@ -657,19 +675,22 @@ class BaseRequest:
...
@@ -657,19 +675,22 @@ class BaseRequest:
try
:
try
:
pairs
=
self
.
_post_traverse
pairs
=
self
.
_post_traverse
except
AttributeError
:
except
AttributeError
:
raise
RuntimeError
,
(
'post_traverse() may only be called '
raise
RuntimeError
(
'post_traverse() may only be called '
'during publishing traversal.'
)
'during publishing traversal.'
)
else
:
else
:
pairs
.
append
((
f
,
tuple
(
args
)))
pairs
.
append
((
f
,
tuple
(
args
)))
retry_count
=
0
retry_count
=
0
def
supports_retry
(
self
):
return
0
def
supports_retry
(
self
):
return
0
def
_hold
(
self
,
object
):
def
_hold
(
self
,
object
):
"""Hold a reference to an object to delay it's destruction until mine
"""Hold a reference to an object to delay it's destruction until mine
"""
"""
if
self
.
_held
is
not
None
:
if
self
.
_held
is
not
None
:
self
.
_held
=
self
.
_held
+
(
object
,)
self
.
_held
=
self
.
_held
+
(
object
,
)
def
exec_callables
(
callables
):
def
exec_callables
(
callables
):
result
=
None
result
=
None
...
@@ -679,74 +700,84 @@ def exec_callables(callables):
...
@@ -679,74 +700,84 @@ def exec_callables(callables):
if
result
is
not
None
:
if
result
is
not
None
:
return
result
return
result
def
old_validation
(
groups
,
request
,
auth
,
def
old_validation
(
groups
,
request
,
auth
,
roles
=
UNSPECIFIED_ROLES
):
roles
=
UNSPECIFIED_ROLES
):
if
auth
:
if
auth
:
auth
=
request
.
_authUserPW
()
auth
=
request
.
_authUserPW
()
if
auth
:
name
,
password
=
auth
if
auth
:
elif
roles
is
None
:
return
''
name
,
password
=
auth
else
:
return
None
elif
roles
is
None
:
return
''
else
:
return
None
elif
'REMOTE_USER'
in
request
.
environ
:
elif
'REMOTE_USER'
in
request
.
environ
:
name
=
request
.
environ
[
'REMOTE_USER'
]
name
=
request
.
environ
[
'REMOTE_USER'
]
password
=
None
password
=
None
else
:
else
:
if
roles
is
None
:
return
''
if
roles
is
None
:
return
''
return
None
return
None
if
roles
is
None
:
return
name
if
roles
is
None
:
return
name
keys
=
None
keys
=
None
try
:
try
:
keys
=
groups
.
keys
keys
=
groups
.
keys
except
:
except
Exception
:
try
:
try
:
groups
=
groups
()
# Maybe it was a method defining a group
groups
=
groups
()
# Maybe it was a method defining a group
keys
=
groups
.
keys
keys
=
groups
.
keys
except
:
pass
except
Exception
:
pass
if
keys
is
not
None
:
if
keys
is
not
None
:
# OK, we have a named group, so apply the roles to the named
# OK, we have a named group, so apply the roles to the named
# group.
# group.
if
roles
is
UNSPECIFIED_ROLES
:
roles
=
keys
()
if
roles
is
UNSPECIFIED_ROLES
:
g
=
[]
roles
=
keys
()
g
=
[]
for
role
in
roles
:
for
role
in
roles
:
if
role
in
groups
:
g
.
append
(
groups
[
role
])
if
role
in
groups
:
groups
=
g
g
.
append
(
groups
[
role
])
groups
=
g
for
d
in
groups
:
for
d
in
groups
:
if
name
in
d
and
(
d
[
name
]
==
password
or
password
is
None
):
if
name
in
d
and
(
d
[
name
]
==
password
or
password
is
None
):
return
name
return
name
if
keys
is
None
:
if
keys
is
None
:
# Not a named group, so don't go further
# Not a named group, so don't go further
raise
Forbidden
,
(
raise
Forbidden
(
"""<strong>You are not authorized to access this resource"""
)
"""<strong>You are not authorized to access this resource"""
)
return
None
return
None
# This mapping contains the built-in types that gained docstrings
itypes
=
{
# between Python 2.1 and 2.2.2. By specifically checking for these
bool
:
0
,
# types during publishing, we ensure the same publishing rules in
types
.
CodeType
:
0
,
# both versions. The downside is that this needs to be extended as
complex
:
0
,
# new built-in types are added and future Python versions are
dict
:
0
,
# supported.
float
:
0
,
types
.
FrameType
:
0
,
import
types
frozenset
:
0
,
int
:
0
,
itypes
=
{}
list
:
0
,
for
name
in
(
'NoneType'
,
'IntType'
,
'LongType'
,
'FloatType'
,
'StringType'
,
type
(
None
):
0
,
'BufferType'
,
'TupleType'
,
'ListType'
,
'DictType'
,
'XRangeType'
,
set
:
0
,
'SliceType'
,
'EllipsisType'
,
'UnicodeType'
,
'CodeType'
,
slice
:
0
,
'TracebackType'
,
'FrameType'
,
'DictProxyType'
,
'BooleanType'
,
str
:
0
,
'ComplexType'
):
types
.
TracebackType
:
0
,
tuple
:
0
,
}
for
name
in
(
'BufferType'
,
'DictProxyType'
,
'EllipsisType'
,
'LongType'
,
'UnicodeType'
,
'XRangeType'
):
if
hasattr
(
types
,
name
):
if
hasattr
(
types
,
name
):
itypes
[
getattr
(
types
,
name
)]
=
0
itypes
[
getattr
(
types
,
name
)]
=
0
# Python 2.4 no longer maintains the types module.
itypes
[
set
]
=
0
itypes
[
frozenset
]
=
0
def
typeCheck
(
obj
,
deny
=
itypes
):
def
typeCheck
(
obj
,
deny
=
itypes
):
# Return true if its ok to publish the type, false otherwise.
# Return true if its ok to publish the type, false otherwise.
...
...
src/ZPublisher/BaseResponse.py
View file @
efe61189
...
@@ -15,10 +15,9 @@
...
@@ -15,10 +15,9 @@
from
zExceptions
import
Unauthorized
,
Forbidden
,
NotFound
,
BadRequest
from
zExceptions
import
Unauthorized
,
Forbidden
,
NotFound
,
BadRequest
class
BaseResponse
:
class
BaseResponse
:
"""Base Response Class
"""Base Response Class
What should be here?
"""
"""
debug_mode
=
None
debug_mode
=
None
_auth
=
None
_auth
=
None
...
@@ -59,7 +58,7 @@ class BaseResponse:
...
@@ -59,7 +58,7 @@ class BaseResponse:
'Returns the current HTTP status code as an integer. '
'Returns the current HTTP status code as an integer. '
return
self
.
status
return
self
.
status
def
setCookie
(
self
,
name
,
value
,
**
kw
):
def
setCookie
(
self
,
name
,
value
,
**
kw
):
'''
\
'''
\
Set an HTTP cookie on the browser
Set an HTTP cookie on the browser
...
@@ -101,12 +100,12 @@ class BaseResponse:
...
@@ -101,12 +100,12 @@ class BaseResponse:
return
str
(
self
.
body
)
return
str
(
self
.
body
)
def
__repr__
(
self
):
def
__repr__
(
self
):
return
'%s(%
s)'
%
(
self
.
__class__
.
__name__
,
`self.body`
)
return
'%s(%
r)'
%
(
self
.
__class__
.
__name__
,
self
.
body
)
def
flush
(
self
):
def
flush
(
self
):
pass
pass
def
write
(
self
,
data
):
def
write
(
self
,
data
):
"""
\
"""
\
Return data as a stream
Return data as a stream
...
@@ -121,7 +120,7 @@ class BaseResponse:
...
@@ -121,7 +120,7 @@ class BaseResponse:
after beginning stream-oriented output.
after beginning stream-oriented output.
"""
"""
self
.
body
=
self
.
body
+
data
self
.
body
=
self
.
body
+
data
def
exception
(
self
,
fatal
=
0
,
info
=
None
):
def
exception
(
self
,
fatal
=
0
,
info
=
None
):
"""Handle an exception.
"""Handle an exception.
...
@@ -135,23 +134,23 @@ class BaseResponse:
...
@@ -135,23 +134,23 @@ class BaseResponse:
def
notFoundError
(
self
,
v
=
''
):
def
notFoundError
(
self
,
v
=
''
):
"""Generate an error indicating that an object was not found.
"""Generate an error indicating that an object was not found.
"""
"""
raise
NotFound
,
v
raise
NotFound
(
v
)
def
debugError
(
self
,
v
=
''
):
def
debugError
(
self
,
v
=
''
):
"""Raise an error with debigging info and in debugging mode"""
"""Raise an error with debigging info and in debugging mode"""
raise
NotFound
,
"Debugging notice: %s"
%
v
raise
NotFound
(
"Debugging notice: %s"
%
v
)
def
badRequestError
(
self
,
v
=
''
):
def
badRequestError
(
self
,
v
=
''
):
"""Raise an error indicating something wrong with the request"""
"""Raise an error indicating something wrong with the request"""
raise
BadRequest
,
v
raise
BadRequest
(
v
)
def
forbiddenError
(
self
,
v
=
''
):
def
forbiddenError
(
self
,
v
=
''
):
"""Raise an error indicating that the request cannot be done"""
"""Raise an error indicating that the request cannot be done"""
raise
Forbidden
,
v
raise
Forbidden
(
v
)
def
unauthorized
(
self
):
def
unauthorized
(
self
):
"""Raise an eror indicating that the user was not authizated
"""Raise an eror indicating that the user was not authizated
Make sure to generate an appropriate challenge, as appropriate.
Make sure to generate an appropriate challenge, as appropriate.
"""
"""
raise
Unauthorized
raise
Unauthorized
()
src/ZPublisher/BeforeTraverse.py
View file @
efe61189
...
@@ -15,10 +15,9 @@
...
@@ -15,10 +15,9 @@
from
Acquisition
import
aq_base
from
Acquisition
import
aq_base
from
logging
import
getLogger
from
logging
import
getLogger
# Interface
LOG
=
getLogger
(
'ZPublisher'
)
LOG
=
getLogger
(
'ZPublisher'
)
def
registerBeforeTraverse
(
container
,
object
,
app_handle
,
priority
=
99
):
def
registerBeforeTraverse
(
container
,
object
,
app_handle
,
priority
=
99
):
"""Register an object to be called before a container is traversed.
"""Register an object to be called before a container is traversed.
...
@@ -36,6 +35,7 @@ def registerBeforeTraverse(container, object, app_handle, priority=99):
...
@@ -36,6 +35,7 @@ def registerBeforeTraverse(container, object, app_handle, priority=99):
btr
[(
priority
,
app_handle
)]
=
object
btr
[(
priority
,
app_handle
)]
=
object
rewriteBeforeTraverse
(
container
,
btr
)
rewriteBeforeTraverse
(
container
,
btr
)
def
unregisterBeforeTraverse
(
container
,
app_handle
):
def
unregisterBeforeTraverse
(
container
,
app_handle
):
"""Unregister a __before_traverse__ hook object, given its 'app_handle'.
"""Unregister a __before_traverse__ hook object, given its 'app_handle'.
...
@@ -50,6 +50,7 @@ def unregisterBeforeTraverse(container, app_handle):
...
@@ -50,6 +50,7 @@ def unregisterBeforeTraverse(container, app_handle):
rewriteBeforeTraverse
(
container
,
btr
)
rewriteBeforeTraverse
(
container
,
btr
)
return
objects
return
objects
def
queryBeforeTraverse
(
container
,
app_handle
):
def
queryBeforeTraverse
(
container
,
app_handle
):
"""Find __before_traverse__ hook objects, given an 'app_handle'.
"""Find __before_traverse__ hook objects, given an 'app_handle'.
...
@@ -61,7 +62,6 @@ def queryBeforeTraverse(container, app_handle):
...
@@ -61,7 +62,6 @@ def queryBeforeTraverse(container, app_handle):
objects
.
append
((
k
[
0
],
btr
[
k
]))
objects
.
append
((
k
[
0
],
btr
[
k
]))
return
objects
return
objects
# Implementation tools
def
rewriteBeforeTraverse
(
container
,
btr
):
def
rewriteBeforeTraverse
(
container
,
btr
):
"""Rewrite the list of __before_traverse__ hook objects"""
"""Rewrite the list of __before_traverse__ hook objects"""
...
@@ -79,6 +79,7 @@ def rewriteBeforeTraverse(container, btr):
...
@@ -79,6 +79,7 @@ def rewriteBeforeTraverse(container, btr):
for
key
in
keys
:
for
key
in
keys
:
bpth
.
add
(
btr
[
key
])
bpth
.
add
(
btr
[
key
])
class
MultiHook
:
class
MultiHook
:
"""Class used to multiplex hook.
"""Class used to multiplex hook.
...
@@ -102,13 +103,12 @@ class MultiHook:
...
@@ -102,13 +103,12 @@ class MultiHook:
try
:
try
:
cob
(
container
,
request
)
cob
(
container
,
request
)
except
TypeError
:
except
TypeError
:
LOG
.
error
(
'%
s call %s
failed.'
%
(
LOG
.
error
(
'%
r call %r
failed.'
%
(
`self._hookname`
,
`cob`
),
exc_info
=
True
)
self
.
_hookname
,
cob
),
exc_info
=
True
)
def
add
(
self
,
cob
):
def
add
(
self
,
cob
):
self
.
_list
.
append
(
cob
)
self
.
_list
.
append
(
cob
)
# Helper class
class
NameCaller
:
class
NameCaller
:
"""Class used to proxy sibling objects by name.
"""Class used to proxy sibling objects by name.
...
@@ -134,10 +134,8 @@ class NameCaller:
...
@@ -134,10 +134,8 @@ class NameCaller:
# This happens especially, if "meth" is a "CookieCrumber" instance,
# This happens especially, if "meth" is a "CookieCrumber" instance,
# i.e. in a CMF Portal, if a DTMLMethod (or a similar object
# i.e. in a CMF Portal, if a DTMLMethod (or a similar object
# with a fake "func_code" is in the acquisition context
# with a fake "func_code" is in the acquisition context
#args = getattr(getattr(meth, 'func_code', None), 'co_argcount', 2)
args
=
getattr
(
getattr
(
aq_base
(
meth
),
'func_code'
,
None
),
args
=
getattr
(
getattr
(
aq_base
(
meth
),
'func_code'
,
None
),
'co_argcount'
,
'co_argcount'
,
2
)
2
)
try
:
try
:
meth
(
*
(
container
,
request
,
None
)[:
args
])
meth
(
*
(
container
,
request
,
None
)[:
args
])
...
@@ -148,5 +146,5 @@ class NameCaller:
...
@@ -148,5 +146,5 @@ class NameCaller:
# Only catch exceptions that are likely to be logic errors.
# Only catch exceptions that are likely to be logic errors.
# We shouldn't catch Redirects, Unauthorizeds, etc. since
# We shouldn't catch Redirects, Unauthorizeds, etc. since
# the programmer may want to raise them deliberately.
# the programmer may want to raise them deliberately.
LOG
.
error
(
'BeforeTraverse: Error while invoking hook: "%s"'
%
self
.
name
,
LOG
.
error
(
'BeforeTraverse: Error while invoking hook: "%s"'
%
exc_info
=
True
)
self
.
name
,
exc_info
=
True
)
src/ZPublisher/Client.py
deleted
100644 → 0
View file @
2e9d01ea
#!/bin/sh
""":"
exec python $0 ${1+"$@"}
"""
#"
##############################################################################
#
# Copyright (c) 2002 Zope Foundation and Contributors.
#
# 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
#
##############################################################################
"""Bobo call interface
This module provides tools for accessing web objects as if they were
functions or objects with methods. It also provides a simple call function
that allows one to simply make a single web request.
Function -- Function-like objects that return both header and body
data when called.
Object -- Treat a URL as a web object with methods
call -- Simple interface to call a remote function.
The module also provides a command-line interface for calling objects.
"""
import
sys
,
re
,
socket
,
mimetools
from
httplib
import
HTTP
from
os
import
getpid
from
time
import
time
from
random
import
random
from
base64
import
encodestring
from
urllib
import
urlopen
,
quote
from
types
import
FileType
,
ListType
,
DictType
,
TupleType
from
string
import
translate
,
maketrans
from
urlparse
import
urlparse
class
BadReply
(
Exception
):
pass
class
Function
:
username
=
None
password
=
None
method
=
None
timeout
=
60
def
__init__
(
self
,
url
,
arguments
=
(),
method
=
None
,
username
=
None
,
password
=
None
,
timeout
=
None
,
**
headers
):
while
url
[
-
1
:]
==
'/'
:
url
=
url
[:
-
1
]
self
.
url
=
url
self
.
headers
=
headers
if
not
headers
.
has_key
(
'Host'
)
and
not
headers
.
has_key
(
'host'
):
headers
[
'Host'
]
=
urlparse
(
url
)[
1
]
self
.
func_name
=
url
[
url
.
rfind
(
'/'
)
+
1
:]
self
.
__dict__
[
'__name__'
]
=
self
.
func_name
self
.
func_defaults
=
self
.
__defaults__
=
()
self
.
args
=
arguments
if
method
is
not
None
:
self
.
method
=
method
if
username
is
not
None
:
self
.
username
=
username
if
password
is
not
None
:
self
.
password
=
password
if
timeout
is
not
None
:
self
.
timeout
=
timeout
mo
=
urlregex
.
match
(
url
)
if
mo
is
not
None
:
host
,
port
,
rurl
=
mo
.
group
(
1
,
2
,
3
)
if
port
:
port
=
int
(
port
[
1
:])
else
:
port
=
80
self
.
host
=
host
self
.
port
=
port
rurl
=
rurl
or
'/'
self
.
rurl
=
rurl
else
:
raise
ValueError
,
url
def
__call__
(
self
,
*
args
,
**
kw
):
method
=
self
.
method
if
method
==
'PUT'
and
len
(
args
)
==
1
and
not
kw
:
query
=
[
args
[
0
]]
args
=
()
else
:
query
=
[]
for
i
in
range
(
len
(
args
)):
try
:
k
=
self
.
args
[
i
]
if
kw
.
has_key
(
k
):
raise
TypeError
,
'Keyword arg redefined'
kw
[
k
]
=
args
[
i
]
except
IndexError
:
raise
TypeError
,
'Too many arguments'
headers
=
{}
for
k
,
v
in
self
.
headers
.
items
():
headers
[
translate
(
k
,
dashtrans
)]
=
v
method
=
self
.
method
if
headers
.
has_key
(
'Content-Type'
):
content_type
=
headers
[
'Content-Type'
]
if
content_type
==
'multipart/form-data'
:
return
self
.
_mp_call
(
kw
)
else
:
content_type
=
None
if
not
method
or
method
==
'POST'
:
for
v
in
kw
.
values
():
if
hasattr
(
v
,
'read'
):
return
self
.
_mp_call
(
kw
)
can_marshal
=
type2marshal
.
has_key
for
k
,
v
in
kw
.
items
():
t
=
type
(
v
)
if
can_marshal
(
t
):
q
=
type2marshal
[
t
](
k
,
v
)
else
:
q
=
'%s=%s'
%
(
k
,
quote
(
v
))
query
.
append
(
q
)
url
=
self
.
rurl
if
query
:
query
=
'&'
.
join
(
query
)
method
=
method
or
'POST'
if
method
==
'PUT'
:
headers
[
'Content-Length'
]
=
str
(
len
(
query
))
if
method
!=
'POST'
:
url
=
"%s?%s"
%
(
url
,
query
)
query
=
''
elif
not
content_type
:
headers
[
'Content-Type'
]
=
'application/x-www-form-urlencoded'
headers
[
'Content-Length'
]
=
str
(
len
(
query
))
else
:
method
=
method
or
'GET'
if
(
self
.
username
and
self
.
password
and
not
headers
.
has_key
(
'Authorization'
)):
headers
[
'Authorization'
]
=
(
"Basic %s"
%
encodestring
(
'%s:%s'
%
(
self
.
username
,
self
.
password
)).
replace
(
'
\
012
'
,
''
)
)
try
:
h
=
HTTP
(
self
.
host
,
self
.
port
)
h
.
putrequest
(
method
,
self
.
rurl
)
for
hn
,
hv
in
headers
.
items
():
h
.
putheader
(
translate
(
hn
,
dashtrans
),
hv
)
h
.
endheaders
()
if
query
:
h
.
send
(
query
)
ec
,
em
,
headers
=
h
.
getreply
()
response
=
h
.
getfile
().
read
()
except
:
raise
NotAvailable
,
RemoteException
(
NotAvailable
,
sys
.
exc_info
()[
1
],
self
.
url
,
query
)
if
(
ec
-
(
ec
%
100
))
==
200
:
return
(
headers
,
response
)
self
.
handleError
(
query
,
ec
,
em
,
headers
,
response
)
def
handleError
(
self
,
query
,
ec
,
em
,
headers
,
response
):
try
:
v
=
headers
.
dict
[
'bobo-exception-value'
]
except
:
v
=
ec
try
:
f
=
headers
.
dict
[
'bobo-exception-file'
]
except
:
f
=
'Unknown'
try
:
l
=
headers
.
dict
[
'bobo-exception-line'
]
except
:
l
=
'Unknown'
try
:
t
=
exceptmap
[
headers
.
dict
[
'bobo-exception-type'
]]
except
:
if
ec
>=
400
and
ec
<
500
:
t
=
NotFound
elif
ec
==
503
:
t
=
NotAvailable
else
:
t
=
ServerError
raise
t
,
RemoteException
(
t
,
v
,
f
,
l
,
self
.
url
,
query
,
ec
,
em
,
response
)
def
_mp_call
(
self
,
kw
,
type2suffix
=
{
type
(
1.0
):
':float'
,
type
(
1
):
':int'
,
type
(
1L
):
':long'
,
type
([]):
':list'
,
type
(()):
':tuple'
,
}
):
# Call a function using the file-upload protcol
# Add type markers to special values:
d
=
{}
special_type
=
type2suffix
.
has_key
for
k
,
v
in
kw
.
items
():
if
':'
not
in
k
:
t
=
type
(
v
)
if
special_type
(
t
):
d
[
'%s%s'
%
(
k
,
type2suffix
[
t
])]
=
v
else
:
d
[
k
]
=
v
else
:
d
[
k
]
=
v
rq
=
[(
'POST %s HTTP/1.0'
%
self
.
rurl
),]
for
n
,
v
in
self
.
headers
.
items
():
rq
.
append
(
'%s: %s'
%
(
n
,
v
))
if
self
.
username
and
self
.
password
:
c
=
encodestring
(
'%s:%s'
%
(
self
.
username
,
self
.
password
)).
replace
(
'
\
012
'
,
''
)
rq
.
append
(
'Authorization: Basic %s'
%
c
)
rq
.
append
(
MultiPart
(
d
).
render
())
rq
=
'
\
r
\
n
'
.
join
(
rq
)
try
:
sock
=
socket
.
socket
(
socket
.
AF_INET
,
socket
.
SOCK_STREAM
)
sock
.
connect
((
self
.
host
,
self
.
port
))
sock
.
send
(
rq
)
reply
=
sock
.
makefile
(
'rb'
)
sock
=
None
line
=
reply
.
readline
()
try
:
[
ver
,
ec
,
em
]
=
line
.
split
(
None
,
2
)
except
ValueError
:
raise
BadReply
,
'Bad reply from server: '
+
line
if
ver
[:
5
]
!=
'HTTP/'
:
raise
BadReply
,
'Bad reply from server: '
+
line
ec
=
int
(
ec
)
em
=
em
.
strip
()
headers
=
mimetools
.
Message
(
reply
,
0
)
response
=
reply
.
read
()
finally
:
if
0
:
raise
NotAvailable
,
(
RemoteException
(
NotAvailable
,
sys
.
exc_info
()[
1
],
self
.
url
,
'<MultiPart Form>'
))
if
ec
==
200
:
return
(
headers
,
response
)
self
.
handleError
(
''
,
ec
,
em
,
headers
,
response
)
class
Object
:
"""Surrogate object for an object on the web"""
username
=
None
password
=
None
method
=
None
timeout
=
None
special_methods
=
'GET'
,
'POST'
,
'PUT'
def
__init__
(
self
,
url
,
method
=
None
,
username
=
None
,
password
=
None
,
timeout
=
None
,
**
headers
):
self
.
url
=
url
self
.
headers
=
headers
if
not
headers
.
has_key
(
'Host'
)
and
not
headers
.
has_key
(
'host'
):
headers
[
'Host'
]
=
urlparse
(
url
)[
1
]
if
method
is
not
None
:
self
.
method
=
method
if
username
is
not
None
:
self
.
username
=
username
if
password
is
not
None
:
self
.
password
=
password
if
timeout
is
not
None
:
self
.
timeout
=
timeout
def
__getattr__
(
self
,
name
):
if
name
in
self
.
special_methods
:
method
=
name
url
=
self
.
url
else
:
method
=
self
.
method
url
=
"%s/%s"
%
(
self
.
url
,
name
)
f
=
Function
(
url
,
method
=
method
,
username
=
self
.
username
,
password
=
self
.
password
,
timeout
=
self
.
timeout
)
f
.
headers
=
self
.
headers
return
f
def
call
(
url
,
username
=
None
,
password
=
None
,
**
kw
):
return
apply
(
Function
(
url
,
username
=
username
,
password
=
password
),
(),
kw
)
##############################################################################
# Implementation details below here
urlregex
=
re
.
compile
(
r'http://([^:/]+)(:[0-9]+)?(/.+)?'
,
re
.
I
)
dashtrans
=
maketrans
(
'_'
,
'-'
)
def
marshal_float
(
n
,
f
):
return
'%s:float=%s'
%
(
n
,
f
)
def
marshal_int
(
n
,
f
):
return
'%s:int=%s'
%
(
n
,
f
)
def
marshal_long
(
n
,
f
):
value
=
'%s:long=%s'
%
(
n
,
f
)
if
value
[
-
1
]
==
'L'
:
value
=
value
[:
-
1
]
return
value
def
marshal_list
(
n
,
l
,
tname
=
'list'
,
lt
=
type
([]),
tt
=
type
(())):
r
=
[]
for
v
in
l
:
t
=
type
(
v
)
if
t
is
lt
or
t
is
tt
:
raise
TypeError
,
'Invalid recursion in data to be marshaled.'
r
.
append
(
marshal_whatever
(
"%s:%s"
%
(
n
,
tname
)
,
v
))
return
'&'
.
join
(
r
)
def
marshal_tuple
(
n
,
l
):
return
marshal_list
(
n
,
l
,
'tuple'
)
type2marshal
=
{
type
(
1.0
):
marshal_float
,
type
(
1
):
marshal_int
,
type
(
1L
):
marshal_long
,
type
([]):
marshal_list
,
type
(()):
marshal_tuple
,
}
def
marshal_whatever
(
k
,
v
):
try
:
q
=
type2marshal
[
type
(
v
)](
k
,
v
)
except
KeyError
:
q
=
'%s=%s'
%
(
k
,
quote
(
str
(
v
)))
return
q
def
querify
(
items
):
query
=
[]
for
k
,
v
in
items
:
query
.
append
(
marshal_whatever
(
k
,
v
))
return
query
and
'&'
.
join
(
query
)
or
''
NotFound
=
'bci.NotFound'
InternalError
=
'bci.InternalError'
BadRequest
=
'bci.BadRequest'
Unauthorized
=
'bci.Unauthorized'
ServerError
=
'bci.ServerError'
NotAvailable
=
'bci.NotAvailable'
exceptmap
=
{
'AttributeError'
:
AttributeError
,
'BadRequest'
:
BadRequest
,
'EOFError'
:
EOFError
,
'IOError'
:
IOError
,
'ImportError'
:
ImportError
,
'IndexError'
:
IndexError
,
'InternalError'
:
InternalError
,
'KeyError'
:
KeyError
,
'MemoryError'
:
MemoryError
,
'NameError'
:
NameError
,
'NotAvailable'
:
NotAvailable
,
'NotFound'
:
NotFound
,
'OverflowError'
:
OverflowError
,
'RuntimeError'
:
RuntimeError
,
'ServerError'
:
ServerError
,
'SyntaxError'
:
SyntaxError
,
'SystemError'
:
SystemError
,
'SystemExit'
:
SystemExit
,
'TypeError'
:
TypeError
,
'Unauthorized'
:
Unauthorized
,
'ValueError'
:
ValueError
,
'ZeroDivisionError'
:
ZeroDivisionError
}
class
RemoteException
:
def
__init__
(
self
,
etype
=
None
,
evalue
=
None
,
efile
=
None
,
eline
=
None
,
url
=
None
,
query
=
None
,
http_code
=
None
,
http_msg
=
None
,
http_resp
=
None
):
"""Contains information about an exception which
occurs in a remote method call"""
self
.
exc_type
=
etype
self
.
exc_value
=
evalue
self
.
exc_file
=
efile
self
.
exc_line
=
eline
self
.
url
=
url
self
.
query
=
query
self
.
http_code
=
http_code
self
.
http_message
=
http_msg
self
.
response
=
http_resp
def
__repr__
(
self
):
return
'%s (File: %s Line: %s)
\
n
%s %s for %s'
%
(
self
.
exc_value
,
self
.
exc_file
,
self
.
exc_line
,
self
.
http_code
,
self
.
http_message
,
self
.
url
)
class
MultiPart
:
def
__init__
(
self
,
*
args
):
c
=
len
(
args
)
if
c
==
1
:
name
,
val
=
None
,
args
[
0
]
elif
c
==
2
:
name
,
val
=
args
[
0
],
args
[
1
]
else
:
raise
ValueError
,
'Invalid arguments'
h
=
{
'Content-Type'
:
{
'_v'
:
''
},
'Content-Transfer-Encoding'
:
{
'_v'
:
''
},
'Content-Disposition'
:
{
'_v'
:
''
},}
dt
=
type
(
val
)
b
=
t
=
None
if
dt
==
DictType
:
t
=
1
b
=
self
.
boundary
()
d
=
[]
h
[
'Content-Type'
][
'_v'
]
=
'multipart/form-data; boundary=%s'
%
b
for
n
,
v
in
val
.
items
():
d
.
append
(
MultiPart
(
n
,
v
))
elif
(
dt
==
ListType
)
or
(
dt
==
TupleType
):
raise
ValueError
,
'Sorry, nested multipart is not done yet!'
elif
dt
==
FileType
or
hasattr
(
val
,
'read'
):
if
hasattr
(
val
,
'name'
):
fn
=
val
.
name
.
replace
(
'
\
\
'
,
'/'
)
fn
=
fn
[(
fn
.
rfind
(
'/'
)
+
1
):]
ex
=
(
fn
[(
fn
.
rfind
(
'.'
)
+
1
):]).
lower
()
if
self
.
_extmap
.
has_key
(
ex
):
ct
=
self
.
_extmap
[
ex
]
else
:
ct
=
self
.
_extmap
[
''
]
else
:
fn
=
''
ct
=
self
.
_extmap
[
None
]
if
self
.
_encmap
.
has_key
(
ct
):
ce
=
self
.
_encmap
[
ct
]
else
:
ce
=
''
h
[
'Content-Disposition'
][
'_v'
]
=
'form-data'
h
[
'Content-Disposition'
][
'name'
]
=
'"%s"'
%
name
h
[
'Content-Disposition'
][
'filename'
]
=
'"%s"'
%
fn
h
[
'Content-Transfer-Encoding'
][
'_v'
]
=
ce
h
[
'Content-Type'
][
'_v'
]
=
ct
d
=
[]
l
=
val
.
read
(
8192
)
while
l
:
d
.
append
(
l
)
l
=
val
.
read
(
8192
)
else
:
h
[
'Content-Disposition'
][
'_v'
]
=
'form-data'
h
[
'Content-Disposition'
][
'name'
]
=
'"%s"'
%
name
d
=
[
str
(
val
)]
self
.
_headers
=
h
self
.
_data
=
d
self
.
_boundary
=
b
self
.
_top
=
t
def
boundary
(
self
):
return
'%s_%s_%s'
%
(
int
(
time
()),
getpid
(),
int
(
random
()
*
1000000000
))
def
render
(
self
):
h
=
self
.
_headers
s
=
[]
if
self
.
_top
:
for
n
,
v
in
h
.
items
():
if
v
[
'_v'
]:
s
.
append
(
'%s: %s'
%
(
n
,
v
[
'_v'
]))
for
k
in
v
.
keys
():
if
k
!=
'_v'
:
s
.
append
(
'; %s=%s'
%
(
k
,
v
[
k
]))
s
.
append
(
'
\
r
\
n
'
)
p
=
[]
t
=
[]
b
=
self
.
_boundary
for
d
in
self
.
_data
:
p
.
append
(
d
.
render
())
t
.
append
(
'--%s
\
n
'
%
b
)
t
.
append
((
'
\
n
--%s
\
n
'
%
b
).
join
(
p
))
t
.
append
(
'
\
n
--%s--
\
n
'
%
b
)
t
=
''
.
join
(
t
)
s
.
append
(
'Content-Length: %s
\
r
\
n
\
r
\
n
'
%
len
(
t
))
s
.
append
(
t
)
return
''
.
join
(
s
)
else
:
for
n
,
v
in
h
.
items
():
if
v
[
'_v'
]:
s
.
append
(
'%s: %s'
%
(
n
,
v
[
'_v'
]))
for
k
in
v
.
keys
():
if
k
!=
'_v'
:
s
.
append
(
'; %s=%s'
%
(
k
,
v
[
k
]))
s
.
append
(
'
\
r
\
n
'
)
s
.
append
(
'
\
r
\
n
'
)
if
self
.
_boundary
:
p
=
[]
b
=
self
.
_boundary
for
d
in
self
.
_data
:
p
.
append
(
d
.
render
())
s
.
append
(
'--%s
\
n
'
%
b
)
s
.
append
((
'
\
n
--%s
\
n
'
%
b
).
join
(
p
))
s
.
append
(
'
\
n
--%s--
\
n
'
%
b
)
return
''
.
join
(
s
)
else
:
return
''
.
join
(
s
+
self
.
_data
)
_extmap
=
{
''
:
'text/plain'
,
'rdb'
:
'text/plain'
,
'html'
:
'text/html'
,
'dtml'
:
'text/html'
,
'htm'
:
'text/html'
,
'dtm'
:
'text/html'
,
'gif'
:
'image/gif'
,
'jpg'
:
'image/jpeg'
,
'exe'
:
'application/octet-stream'
,
None
:
'application/octet-stream'
,
}
_encmap
=
{
'image/gif'
:
'binary'
,
'image/jpg'
:
'binary'
,
'application/octet-stream'
:
'binary'
,
}
def
ErrorTypes
(
code
):
if
code
>=
400
and
code
<
500
:
return
NotFound
if
code
>=
500
and
code
<
600
:
return
ServerError
return
'HTTP_Error_%s'
%
code
usage
=
"""
Usage: %s [-u username:password] url [name=value ...]
where url is the web resource to call.
The -u option may be used to provide a user name and password.
Optional arguments may be provides as name=value pairs.
In a name value pair, if a name ends in ":file", then the value is
treated as a file name and the file is send using the file-upload
protocol. If the file name is "-", then data are taken from standard
input.
The body of the response is written to standard output.
The headers of the response are written to standard error.
"""
%
sys
.
argv
[
0
]
def
main
():
import
getopt
user
=
None
try
:
optlist
,
args
=
getopt
.
getopt
(
sys
.
argv
[
1
:],
'u:'
)
url
=
args
[
0
]
u
=
filter
(
lambda
o
:
o
[
0
]
==
'-u'
,
optlist
)
if
u
:
[
user
,
pw
]
=
u
[
0
][
1
].
split
(
':'
)
kw
=
{}
for
arg
in
args
[
1
:]:
[
name
,
v
]
=
arg
.
split
(
'='
)
if
name
[
-
5
:]
==
':file'
:
name
=
name
[:
-
5
]
if
v
==
'-'
:
v
=
sys
.
stdin
else
:
v
=
open
(
v
,
'rb'
)
kw
[
name
]
=
v
except
:
print
usage
sys
.
exit
(
1
)
# The "main" program for this module
f
=
Function
(
url
)
if
user
:
f
.
username
,
f
.
password
=
user
,
pw
headers
,
body
=
apply
(
f
,(),
kw
)
sys
.
stderr
.
write
(
''
.
join
(
map
(
lambda
h
:
"%s: %s
\
n
"
%
h
,
headers
.
items
()))
+
"
\
n
\
n
"
)
print
body
if
__name__
==
"__main__"
:
main
()
src/ZPublisher/Converters.py
View file @
efe61189
...
@@ -12,7 +12,6 @@
...
@@ -12,7 +12,6 @@
##############################################################################
##############################################################################
import
re
import
re
from
types
import
ListType
,
TupleType
,
UnicodeType
from
DateTime
import
DateTime
from
DateTime
import
DateTime
from
DateTime.interfaces
import
SyntaxError
from
DateTime.interfaces
import
SyntaxError
from
cgi
import
escape
from
cgi
import
escape
...
@@ -20,89 +19,106 @@ from cgi import escape
...
@@ -20,89 +19,106 @@ from cgi import escape
# This may get overwritten during configuration
# This may get overwritten during configuration
default_encoding
=
'utf-8'
default_encoding
=
'utf-8'
def
field2string
(
v
):
def
field2string
(
v
):
if
hasattr
(
v
,
'read'
):
return
v
.
read
()
if
hasattr
(
v
,
'read'
):
elif
isinstance
(
v
,
UnicodeType
):
return
v
.
read
()
elif
isinstance
(
v
,
unicode
):
return
v
.
encode
(
default_encoding
)
return
v
.
encode
(
default_encoding
)
else
:
else
:
return
str
(
v
)
return
str
(
v
)
def
field2text
(
v
,
nl
=
re
.
compile
(
'
\
r
\
n
|
\
n
\
r
'
).
search
):
def
field2text
(
v
,
nl
=
re
.
compile
(
'
\
r
\
n
|
\
n
\
r
'
).
search
):
v
=
field2string
(
v
)
v
=
field2string
(
v
)
mo
=
nl
(
v
)
mo
=
nl
(
v
)
if
mo
is
None
:
return
v
if
mo
is
None
:
return
v
l
=
mo
.
start
(
0
)
l
=
mo
.
start
(
0
)
r
=
[]
r
=
[]
s
=
0
s
=
0
while
l
>=
s
:
while
l
>=
s
:
r
.
append
(
v
[
s
:
l
])
r
.
append
(
v
[
s
:
l
])
s
=
l
+
2
s
=
l
+
2
mo
=
nl
(
v
,
s
)
mo
=
nl
(
v
,
s
)
if
mo
is
None
:
l
=-
1
if
mo
is
None
:
else
:
l
=
mo
.
start
(
0
)
l
=
-
1
else
:
l
=
mo
.
start
(
0
)
r
.
append
(
v
[
s
:])
r
.
append
(
v
[
s
:])
return
'
\
n
'
.
join
(
r
)
return
'
\
n
'
.
join
(
r
)
def
field2required
(
v
):
def
field2required
(
v
):
v
=
field2string
(
v
)
v
=
field2string
(
v
)
if
v
.
strip
():
return
v
if
v
.
strip
():
raise
ValueError
,
'No input for required field<p>'
return
v
raise
ValueError
(
'No input for required field<p>'
)
def
field2int
(
v
):
def
field2int
(
v
):
if
isinstance
(
v
,
(
ListType
,
TupleTyp
e
)):
if
isinstance
(
v
,
(
list
,
tupl
e
)):
return
map
(
field2int
,
v
)
return
map
(
field2int
,
v
)
v
=
field2string
(
v
)
v
=
field2string
(
v
)
if
v
:
if
v
:
try
:
return
int
(
v
)
try
:
return
int
(
v
)
except
ValueError
:
except
ValueError
:
raise
ValueError
,
(
raise
ValueError
(
"An integer was expected in the value %
s"
%
escape
(
`v`
)
"An integer was expected in the value %
r"
%
escape
(
v
)
)
)
raise
ValueError
,
'Empty entry when <strong>integer</strong> expected'
raise
ValueError
(
'Empty entry when <strong>integer</strong> expected'
)
def
field2float
(
v
):
def
field2float
(
v
):
if
isinstance
(
v
,
(
ListType
,
TupleTyp
e
)):
if
isinstance
(
v
,
(
list
,
tupl
e
)):
return
map
(
field2float
,
v
)
return
map
(
field2float
,
v
)
v
=
field2string
(
v
)
v
=
field2string
(
v
)
if
v
:
if
v
:
try
:
return
float
(
v
)
try
:
return
float
(
v
)
except
ValueError
:
except
ValueError
:
raise
ValueError
,
(
raise
ValueError
(
"A floating-point number was expected in the value %
s
"
%
"A floating-point number was expected in the value %
r
"
%
escape
(
`v`
)
escape
(
v
)
)
)
raise
ValueError
,
(
raise
ValueError
(
'Empty entry when <strong>floating-point number</strong> expected'
)
'Empty entry when <strong>floating-point number</strong> expected'
)
def
field2long
(
v
):
def
field2long
(
v
):
if
isinstance
(
v
,
(
ListType
,
TupleTyp
e
)):
if
isinstance
(
v
,
(
list
,
tupl
e
)):
return
map
(
field2long
,
v
)
return
map
(
field2long
,
v
)
v
=
field2string
(
v
)
v
=
field2string
(
v
)
# handle trailing 'L' if present.
# handle trailing 'L' if present.
if
v
[
-
1
:]
in
(
'L'
,
'l'
):
if
v
[
-
1
:]
in
(
'L'
,
'l'
):
v
=
v
[:
-
1
]
v
=
v
[:
-
1
]
if
v
:
if
v
:
try
:
return
long
(
v
)
try
:
return
int
(
v
)
except
ValueError
:
except
ValueError
:
raise
ValueError
,
(
raise
ValueError
(
"A long integer was expected in the value %
s"
%
escape
(
`v`
)
"A long integer was expected in the value %
r"
%
escape
(
v
)
)
)
raise
ValueError
,
'Empty entry when <strong>integer</strong> expected'
raise
ValueError
(
'Empty entry when <strong>integer</strong> expected'
)
def
field2tokens
(
v
):
def
field2tokens
(
v
):
v
=
field2string
(
v
)
v
=
field2string
(
v
)
return
v
.
split
()
return
v
.
split
()
def
field2lines
(
v
):
def
field2lines
(
v
):
if
isinstance
(
v
,
(
ListType
,
TupleTyp
e
)):
if
isinstance
(
v
,
(
list
,
tupl
e
)):
result
=
[]
result
=
[]
for
item
in
v
:
for
item
in
v
:
result
.
append
(
str
(
item
))
result
.
append
(
str
(
item
))
return
result
return
result
return
field2text
(
v
).
splitlines
()
return
field2text
(
v
).
splitlines
()
def
field2date
(
v
):
def
field2date
(
v
):
v
=
field2string
(
v
)
v
=
field2string
(
v
)
try
:
try
:
...
@@ -111,6 +127,7 @@ def field2date(v):
...
@@ -111,6 +127,7 @@ def field2date(v):
raise
SyntaxError
(
"Invalid DateTime "
+
escape
(
repr
(
v
)))
raise
SyntaxError
(
"Invalid DateTime "
+
escape
(
repr
(
v
)))
return
v
return
v
def
field2date_international
(
v
):
def
field2date_international
(
v
):
v
=
field2string
(
v
)
v
=
field2string
(
v
)
try
:
try
:
...
@@ -119,46 +136,57 @@ def field2date_international(v):
...
@@ -119,46 +136,57 @@ def field2date_international(v):
raise
SyntaxError
(
"Invalid DateTime "
+
escape
(
repr
(
v
)))
raise
SyntaxError
(
"Invalid DateTime "
+
escape
(
repr
(
v
)))
return
v
return
v
def
field2boolean
(
v
):
def
field2boolean
(
v
):
if
v
==
'False'
:
if
v
==
'False'
:
return
not
1
return
not
1
return
not
not
v
return
not
not
v
class
_unicode_converter
:
class
_unicode_converter
:
def
__call__
(
self
,
v
):
# Convert a regular python string. This probably doesnt do what you want,
def
__call__
(
self
,
v
):
# whatever that might be. If you are getting exceptions below, you
# Convert a regular python string. This probably doesn't do
# probably missed the encoding tag from a form field name. Use:
# what you want, whatever that might be. If you are getting
# exceptions below, you probably missed the encoding tag
# from a form field name. Use:
# <input name="description:utf8:ustring" .....
# <input name="description:utf8:ustring" .....
# rather than
# rather than
# <input name="description:ustring" .....
# <input name="description:ustring" .....
if
hasattr
(
v
,
'read'
):
v
=
v
.
read
()
if
hasattr
(
v
,
'read'
):
v
=
v
.
read
()
v
=
unicode
(
v
)
v
=
unicode
(
v
)
return
self
.
convert_unicode
(
v
)
return
self
.
convert_unicode
(
v
)
def
convert_unicode
(
self
,
v
):
def
convert_unicode
(
self
,
v
):
raise
NotImplementedError
(
'convert_unicode'
)
raise
NotImplementedError
(
'convert_unicode'
)
class
field2ustring
(
_unicode_converter
):
class
field2ustring
(
_unicode_converter
):
def
convert_unicode
(
self
,
v
):
def
convert_unicode
(
self
,
v
):
return
v
return
v
field2ustring
=
field2ustring
()
field2ustring
=
field2ustring
()
class
field2utokens
(
_unicode_converter
):
class
field2utokens
(
_unicode_converter
):
def
convert_unicode
(
self
,
v
):
def
convert_unicode
(
self
,
v
):
return
v
.
split
()
return
v
.
split
()
field2utokens
=
field2utokens
()
field2utokens
=
field2utokens
()
class
field2utext
(
_unicode_converter
):
class
field2utext
(
_unicode_converter
):
def
convert_unicode
(
self
,
v
):
def
convert_unicode
(
self
,
v
):
return
unicode
(
field2text
(
v
.
encode
(
'utf8'
)),
'utf8'
)
return
unicode
(
field2text
(
v
.
encode
(
'utf8'
)),
'utf8'
)
field2utext
=
field2utext
()
field2utext
=
field2utext
()
class
field2ulines
:
class
field2ulines
:
def
__call__
(
self
,
v
):
def
__call__
(
self
,
v
):
if
hasattr
(
v
,
'read'
):
if
hasattr
(
v
,
'read'
):
v
=
v
.
read
()
v
=
v
.
read
()
if
isinstance
(
v
,
(
ListType
,
TupleType
)):
if
isinstance
(
v
,
(
list
,
tuple
)):
return
[
field2ustring
(
x
)
for
x
in
v
]
return
[
field2ustring
(
x
)
for
x
in
v
]
v
=
unicode
(
v
)
v
=
unicode
(
v
)
return
self
.
convert_unicode
(
v
)
return
self
.
convert_unicode
(
v
)
...
@@ -184,6 +212,6 @@ type_converters = {
...
@@ -184,6 +212,6 @@ type_converters = {
'utokens'
:
field2utokens
,
'utokens'
:
field2utokens
,
'ulines'
:
field2ulines
,
'ulines'
:
field2ulines
,
'utext'
:
field2utext
,
'utext'
:
field2utext
,
}
}
get_converter
=
type_converters
.
get
get_converter
=
type_converters
.
get
src/ZPublisher/HTTPRangeSupport.py
View file @
efe61189
...
@@ -19,11 +19,13 @@ flag-interface and some support functions for implementing this functionality.
...
@@ -19,11 +19,13 @@ flag-interface and some support functions for implementing this functionality.
For an implementation example, see the File class in OFS/Image.py.
For an implementation example, see the File class in OFS/Image.py.
"""
"""
import
re
,
sys
import
re
import
sys
from
zope.interface
import
Interface
from
zope.interface
import
Interface
WHITESPACE
=
re
.
compile
(
'
\
s*
'
, re.MULTILINE)
WHITESPACE
=
re
.
compile
(
'
\
s*
'
, re.MULTILINE)
def parseRange(header):
def parseRange(header):
"""RFC 2616 (HTTP 1.1) Range header parsing.
"""RFC 2616 (HTTP 1.1) Range header parsing.
...
@@ -32,7 +34,6 @@ def parseRange(header):
...
@@ -32,7 +34,6 @@ def parseRange(header):
end offset to be inclusive, we return python convention indexes, where the
end offset to be inclusive, we return python convention indexes, where the
end is exclusive. Syntactically incorrect headers are to be ignored, so if
end is exclusive. Syntactically incorrect headers are to be ignored, so if
we encounter one we return None.
we encounter one we return None.
"""
"""
ranges = []
ranges = []
...
@@ -43,8 +44,11 @@ def parseRange(header):
...
@@ -43,8 +44,11 @@ def parseRange(header):
header = WHITESPACE.sub('', header)
header = WHITESPACE.sub('', header)
# A range header only can specify a byte range
# A range header only can specify a byte range
try: spec, sets = header.split('
=
')
try:
except ValueError: return None
spec, sets = header.split('
=
')
except ValueError:
return None
if spec != '
bytes
':
if spec != '
bytes
':
return None
return None
...
@@ -57,8 +61,10 @@ def parseRange(header):
...
@@ -57,8 +61,10 @@ def parseRange(header):
return None
return None
for set in sets:
for set in sets:
try: start, end = set.split('
-
')
try:
except ValueError: return None
start, end = set.split('
-
')
except ValueError:
return None
# Catch empty sets
# Catch empty sets
if not start and not end:
if not start and not end:
...
@@ -67,10 +73,14 @@ def parseRange(header):
...
@@ -67,10 +73,14 @@ def parseRange(header):
# Convert to integers or None (which will raise errors if
# Convert to integers or None (which will raise errors if
# non-integers were used (which is what we want)).
# non-integers were used (which is what we want)).
try:
try:
if start == '': start = None
if start == '':
else: start = int(start)
start = None
if end == '': end = None
else:
else: end = int(end)
start = int(start)
if end == '':
end = None
else:
end = int(end)
except ValueError:
except ValueError:
return None
return None
...
@@ -94,11 +104,11 @@ def parseRange(header):
...
@@ -94,11 +104,11 @@ def parseRange(header):
return ranges
return ranges
def expandRanges(ranges, size):
def expandRanges(ranges, size):
"""Expand Range sets, given those sets and the length of the resource.
"""Expand Range sets, given those sets and the length of the resource.
Expansion means relative start values and open ends
Expansion means relative start values and open ends
"""
"""
expanded = []
expanded = []
...
@@ -107,13 +117,15 @@ def expandRanges(ranges, size):
...
@@ -107,13 +117,15 @@ def expandRanges(ranges, size):
if start < 0:
if start < 0:
start = size + start
start = size + start
end = end or size
end = end or size
if end > size: end = size
if end > size:
end = size
# Only use satisfiable ranges
# Only use satisfiable ranges
if start < size:
if start < size:
add((start, end))
add((start, end))
return expanded
return expanded
class HTTPRangeInterface(Interface):
class HTTPRangeInterface(Interface):
"""Objects implementing this Interface support the HTTP Range header.
"""Objects implementing this Interface support the HTTP Range header.
...
@@ -124,5 +136,4 @@ class HTTPRangeInterface(Interface):
...
@@ -124,5 +136,4 @@ class HTTPRangeInterface(Interface):
This interface specifies no methods, as this functionality can either be
This interface specifies no methods, as this functionality can either be
implemented in the index_html or __call__ methods of a published object.
implemented in the index_html or __call__ methods of a published object.
"""
"""
src/ZPublisher/HTTPResponse.py
View file @
efe61189
...
@@ -71,21 +71,23 @@ _gzip_header = ("\037\213" # magic
...
@@ -71,21 +71,23 @@ _gzip_header = ("\037\213" # magic
"
\
002
"
"
\
002
"
"
\
377
"
)
"
\
377
"
)
uncompressableMimeMajorTypes
=
(
'image'
,)
# these mime major types shoul
d
# these mime major types should not be gzip content encode
d
# not be gzip content encoded
uncompressableMimeMajorTypes
=
(
'image'
,)
# The environment variable DONT_GZIP_MAJOR_MIME_TYPES can be set to a list
# The environment variable DONT_GZIP_MAJOR_MIME_TYPES can be set to a list
# of comma seperated mime major types which should also not be compressed
# of comma seperated mime major types which should also not be compressed
otherTypes
=
os
.
environ
.
get
(
'DONT_GZIP_MAJOR_MIME_TYPES'
,
''
).
lower
()
otherTypes
=
os
.
environ
.
get
(
'DONT_GZIP_MAJOR_MIME_TYPES'
,
''
).
lower
()
if
otherTypes
:
if
otherTypes
:
uncompressableMimeMajorTypes
+=
tuple
(
otherTypes
.
split
(
','
))
uncompressableMimeMajorTypes
+=
tuple
(
otherTypes
.
split
(
','
))
_CRLF
=
re
.
compile
(
r'[\r\n]'
)
_CRLF
=
re
.
compile
(
r'[\r\n]'
)
def
_scrubHeader
(
name
,
value
):
def
_scrubHeader
(
name
,
value
):
return
''
.
join
(
_CRLF
.
split
(
str
(
name
))),
''
.
join
(
_CRLF
.
split
(
str
(
value
)))
return
''
.
join
(
_CRLF
.
split
(
str
(
name
))),
''
.
join
(
_CRLF
.
split
(
str
(
value
)))
class
HTTPResponse
(
BaseResponse
):
class
HTTPResponse
(
BaseResponse
):
""" An object representation of an HTTP response.
""" An object representation of an HTTP response.
...
@@ -104,7 +106,7 @@ class HTTPResponse(BaseResponse):
...
@@ -104,7 +106,7 @@ class HTTPResponse(BaseResponse):
If stream oriented output is used, then the response object
If stream oriented output is used, then the response object
passed into the object must be used.
passed into the object must be used.
"""
#'
"""
body
=
''
body
=
''
base
=
''
base
=
''
...
@@ -124,8 +126,7 @@ class HTTPResponse(BaseResponse):
...
@@ -124,8 +126,7 @@ class HTTPResponse(BaseResponse):
status
=
200
,
status
=
200
,
headers
=
None
,
headers
=
None
,
stdout
=
sys
.
stdout
,
stdout
=
sys
.
stdout
,
stderr
=
sys
.
stderr
,
stderr
=
sys
.
stderr
):
):
""" Create a new response using the given values.
""" Create a new response using the given values.
"""
"""
if
headers
is
None
:
if
headers
is
None
:
...
@@ -166,8 +167,8 @@ class HTTPResponse(BaseResponse):
...
@@ -166,8 +167,8 @@ class HTTPResponse(BaseResponse):
# It has already been determined.
# It has already been determined.
return
return
if
(
isinstance
(
status
,
(
type
,
types
.
ClassType
))
if
(
isinstance
(
status
,
(
type
,
types
.
ClassType
))
and
and
issubclass
(
status
,
Exception
)):
issubclass
(
status
,
Exception
)):
status
=
status
.
__name__
status
=
status
.
__name__
if
isinstance
(
status
,
str
):
if
isinstance
(
status
,
str
):
...
@@ -304,7 +305,7 @@ class HTTPResponse(BaseResponse):
...
@@ -304,7 +305,7 @@ class HTTPResponse(BaseResponse):
h
=
"%s%s%s"
%
(
h
,
delimiter
,
value
)
h
=
"%s%s%s"
%
(
h
,
delimiter
,
value
)
else
:
else
:
h
=
value
h
=
value
self
.
setHeader
(
name
,
h
,
scrubbed
=
True
)
self
.
setHeader
(
name
,
h
,
scrubbed
=
True
)
def
addHeader
(
self
,
name
,
value
):
def
addHeader
(
self
,
name
,
value
):
""" Set a new HTTP return header with the given value,
""" Set a new HTTP return header with the given value,
...
@@ -334,8 +335,7 @@ class HTTPResponse(BaseResponse):
...
@@ -334,8 +335,7 @@ class HTTPResponse(BaseResponse):
self
.
base
=
str
(
base
)
self
.
base
=
str
(
base
)
def
insertBase
(
self
,
def
insertBase
(
self
,
base_re_search
=
re
.
compile
(
'(<base.*?>)'
,
re
.
I
).
search
base_re_search
=
re
.
compile
(
'(<base.*?>)'
,
re
.
I
).
search
):
):
# Only insert a base tag if content appears to be html.
# Only insert a base tag if content appears to be html.
content_type
=
self
.
headers
.
get
(
'content-type'
,
''
).
split
(
';'
)[
0
]
content_type
=
self
.
headers
.
get
(
'content-type'
,
''
).
split
(
';'
)[
0
]
...
@@ -370,9 +370,8 @@ class HTTPResponse(BaseResponse):
...
@@ -370,9 +370,8 @@ class HTTPResponse(BaseResponse):
latin1_alias_match
=
re
.
compile
(
latin1_alias_match
=
re
.
compile
(
r'text/html(\
s*;
\s*charset=((latin)|(latin[-_]?1)|'
r'text/html(\
s*;
\s*charset=((latin)|(latin[-_]?1)|'
r'(cp1252)|(cp819)|(csISOLatin1)|(IBM819)|(iso-ir-100)|'
r'(cp1252)|(cp819)|(csISOLatin1)|(IBM819)|(iso-ir-100)|'
r'(iso[-_]8859[-_]1(:1987)?)))?$'
,
re
.
I
).
match
,
r'(iso[-_]8859[-_]1(:1987)?)))?$'
,
re
.
I
).
match
,
lock
=
None
lock
=
None
):
):
""" Set the body of the response
""" Set the body of the response
Sets the return body equal to the (string) argument "body". Also
Sets the return body equal to the (string) argument "body". Also
...
@@ -411,7 +410,7 @@ class HTTPResponse(BaseResponse):
...
@@ -411,7 +410,7 @@ class HTTPResponse(BaseResponse):
title
,
body
=
body
title
,
body
=
body
if
not
isinstance
(
body
,
str
):
if
not
isinstance
(
body
,
str
):
if
hasattr
(
body
,
'asHTML'
):
if
hasattr
(
body
,
'asHTML'
):
body
=
body
.
asHTML
()
body
=
body
.
asHTML
()
if
isinstance
(
body
,
unicode
):
if
isinstance
(
body
,
unicode
):
...
@@ -425,7 +424,7 @@ class HTTPResponse(BaseResponse):
...
@@ -425,7 +424,7 @@ class HTTPResponse(BaseResponse):
body
=
self
.
_encode_unicode
(
unicode
(
body
))
body
=
self
.
_encode_unicode
(
unicode
(
body
))
l
=
len
(
body
)
l
=
len
(
body
)
if
((
l
<
200
)
and
body
[:
1
]
==
'<'
and
body
.
find
(
'>'
)
==
l
-
1
and
if
((
l
<
200
)
and
body
[:
1
]
==
'<'
and
body
.
find
(
'>'
)
==
l
-
1
and
bogus_str_search
(
body
)
is
not
None
):
bogus_str_search
(
body
)
is
not
None
):
self
.
notFoundError
(
body
[
1
:
-
1
])
self
.
notFoundError
(
body
[
1
:
-
1
])
else
:
else
:
...
@@ -466,25 +465,25 @@ class HTTPResponse(BaseResponse):
...
@@ -466,25 +465,25 @@ class HTTPResponse(BaseResponse):
self
.
insertBase
()
self
.
insertBase
()
if
self
.
use_HTTP_content_compression
and
\
if
(
self
.
use_HTTP_content_compression
and
self
.
headers
.
get
(
'content-encoding'
,
'gzip'
)
==
'gzip'
:
self
.
headers
.
get
(
'content-encoding'
,
'gzip'
)
==
'gzip'
)
:
# use HTTP content encoding to compress body contents unless
# use HTTP content encoding to compress body contents unless
# this response already has another type of content encoding
# this response already has another type of content encoding
if
content_type
.
split
(
'/'
)[
0
]
not
in
uncompressableMimeMajorTypes
:
if
content_type
.
split
(
'/'
)[
0
]
not
in
uncompressableMimeMajorTypes
:
# only compress if not listed as uncompressable
# only compress if not listed as uncompressable
body
=
self
.
body
body
=
self
.
body
startlen
=
len
(
body
)
startlen
=
len
(
body
)
co
=
zlib
.
compressobj
(
6
,
zlib
.
DEFLATED
,
-
zlib
.
MAX_WBITS
,
co
=
zlib
.
compressobj
(
6
,
zlib
.
DEFLATED
,
-
zlib
.
MAX_WBITS
,
zlib
.
DEF_MEM_LEVEL
,
0
)
zlib
.
DEF_MEM_LEVEL
,
0
)
chunks
=
[
_gzip_header
,
co
.
compress
(
body
),
chunks
=
[
_gzip_header
,
co
.
compress
(
body
),
co
.
flush
(),
co
.
flush
(),
struct
.
pack
(
"<ll"
,
zlib
.
crc32
(
body
),
startlen
)]
struct
.
pack
(
"<ll"
,
zlib
.
crc32
(
body
),
startlen
)]
z
=
""
.
join
(
chunks
)
z
=
""
.
join
(
chunks
)
newlen
=
len
(
z
)
newlen
=
len
(
z
)
if
newlen
<
startlen
:
if
newlen
<
startlen
:
self
.
body
=
z
self
.
body
=
z
self
.
setHeader
(
'content-length'
,
newlen
)
self
.
setHeader
(
'content-length'
,
newlen
)
self
.
setHeader
(
'content-encoding'
,
'gzip'
)
self
.
setHeader
(
'content-encoding'
,
'gzip'
)
if
self
.
use_HTTP_content_compression
==
1
:
if
self
.
use_HTTP_content_compression
==
1
:
# use_HTTP_content_compression == 1 if force was
# use_HTTP_content_compression == 1 if force was
# NOT used in enableHTTPCompression().
# NOT used in enableHTTPCompression().
...
@@ -542,7 +541,7 @@ class HTTPResponse(BaseResponse):
...
@@ -542,7 +541,7 @@ class HTTPResponse(BaseResponse):
self
.
use_HTTP_content_compression
=
0
self
.
use_HTTP_content_compression
=
0
elif
(
force
or
elif
(
force
or
(
REQUEST
.
get
(
'HTTP_ACCEPT_ENCODING'
,
''
).
find
(
'gzip'
)
!=
-
1
)):
(
REQUEST
.
get
(
'HTTP_ACCEPT_ENCODING'
,
''
).
find
(
'gzip'
)
!=
-
1
)):
if
force
:
if
force
:
self
.
use_HTTP_content_compression
=
2
self
.
use_HTTP_content_compression
=
2
else
:
else
:
...
@@ -574,7 +573,7 @@ class HTTPResponse(BaseResponse):
...
@@ -574,7 +573,7 @@ class HTTPResponse(BaseResponse):
"""
"""
return
self
.
_shutdown_flag
is
not
None
return
self
.
_shutdown_flag
is
not
None
def
_encode_unicode
(
self
,
body
,
def
_encode_unicode
(
self
,
body
,
charset_re
=
re
.
compile
(
charset_re
=
re
.
compile
(
r'(?:application|text)/[-+0-9a-z]+\
s*;
\s*'
+
r'(?:application|text)/[-+0-9a-z]+\
s*;
\s*'
+
r'charset=([-_0-9a-z]+'
+
r'charset=([-_0-9a-z]+'
+
...
@@ -587,8 +586,8 @@ class HTTPResponse(BaseResponse):
...
@@ -587,8 +586,8 @@ class HTTPResponse(BaseResponse):
if
body
.
startswith
(
'<?xml'
):
if
body
.
startswith
(
'<?xml'
):
pos_right
=
body
.
find
(
'?>'
)
# right end of the XML preamble
pos_right
=
body
.
find
(
'?>'
)
# right end of the XML preamble
body
=
(
'<?xml version="1.0" encoding="%s" ?>'
body
=
(
'<?xml version="1.0" encoding="%s" ?>'
%
%
encoding
)
+
body
[
pos_right
+
2
:]
encoding
)
+
body
[
pos_right
+
2
:]
return
body
return
body
# Encode the Unicode data as requested
# Encode the Unicode data as requested
...
@@ -603,8 +602,8 @@ class HTTPResponse(BaseResponse):
...
@@ -603,8 +602,8 @@ class HTTPResponse(BaseResponse):
return
body
return
body
else
:
else
:
if
ct
.
startswith
(
'text/'
)
or
ct
.
startswith
(
'application/'
):
if
ct
.
startswith
(
'text/'
)
or
ct
.
startswith
(
'application/'
):
self
.
headers
[
'content-type'
]
=
'%s; charset=%s'
%
(
ct
,
self
.
headers
[
'content-type'
]
=
'%s; charset=%s'
%
(
default_encoding
)
ct
,
default_encoding
)
# Use the default character encoding
# Use the default character encoding
body
=
body
.
encode
(
default_encoding
,
'replace'
)
body
=
body
.
encode
(
default_encoding
,
'replace'
)
...
@@ -619,12 +618,11 @@ class HTTPResponse(BaseResponse):
...
@@ -619,12 +618,11 @@ class HTTPResponse(BaseResponse):
tb
=
format_exception
(
t
,
v
,
tb
,
as_html
=
as_html
)
tb
=
format_exception
(
t
,
v
,
tb
,
as_html
=
as_html
)
return
'
\
n
'
.
join
(
tb
)
return
'
\
n
'
.
join
(
tb
)
def
_html
(
self
,
title
,
body
):
def
_html
(
self
,
title
,
body
):
return
(
"<html>
\
n
"
return
(
"<html>
\
n
"
"<head>
\
n
<title>%s</title>
\
n
</head>
\
n
"
"<head>
\
n
<title>%s</title>
\
n
</head>
\
n
"
"<body>
\
n
%s
\
n
</body>
\
n
"
"<body>
\
n
%s
\
n
</body>
\
n
"
"</html>
\
n
"
%
(
title
,
body
))
"</html>
\
n
"
%
(
title
,
body
))
def
_error_html
(
self
,
title
,
body
):
def
_error_html
(
self
,
title
,
body
):
return
(
"""<html>
return
(
"""<html>
...
@@ -635,8 +633,7 @@ class HTTPResponse(BaseResponse):
...
@@ -635,8 +633,7 @@ class HTTPResponse(BaseResponse):
</p>
</p>
<p><strong>%s</strong></p>
<p><strong>%s</strong></p>
%s"""
%
(
title
,
body
)
+
\
%s"""
%
(
title
,
body
)
+
"""
"""
<hr noshade="noshade"/>
<hr noshade="noshade"/>
<p>Troubleshooting Suggestions</p>
<p>Troubleshooting Suggestions</p>
...
@@ -652,7 +649,7 @@ class HTTPResponse(BaseResponse):
...
@@ -652,7 +649,7 @@ class HTTPResponse(BaseResponse):
Thank you for your patience.
Thank you for your patience.
</p></body></html>"""
)
</p></body></html>"""
)
def
notFoundError
(
self
,
entry
=
'Unknown'
):
def
notFoundError
(
self
,
entry
=
'Unknown'
):
self
.
setStatus
(
404
)
self
.
setStatus
(
404
)
raise
NotFound
(
self
.
_error_html
(
raise
NotFound
(
self
.
_error_html
(
"Resource not found"
,
"Resource not found"
,
...
@@ -660,18 +657,18 @@ class HTTPResponse(BaseResponse):
...
@@ -660,18 +657,18 @@ class HTTPResponse(BaseResponse):
"<p>Check the URL and try again.</p>"
+
"<p>Check the URL and try again.</p>"
+
"<p><b>Resource:</b> %s</p>"
%
escape
(
entry
)))
"<p><b>Resource:</b> %s</p>"
%
escape
(
entry
)))
forbiddenError
=
notFoundError
# If a resource is forbidden,
# If a resource is forbidden, why reveal that it exists?
# why reveal that it exists?
forbiddenError
=
notFoundError
def
debugError
(
self
,
entry
):
def
debugError
(
self
,
entry
):
raise
NotFound
(
self
.
_error_html
(
raise
NotFound
(
self
.
_error_html
(
"Debugging Notice"
,
"Debugging Notice"
,
"Zope has encountered a problem publishing your object.<p>"
"Zope has encountered a problem publishing your object.<p>"
"
\
n
%s</p>"
%
entry
))
"
\
n
%s</p>"
%
entry
))
def
badRequestError
(
self
,
name
):
def
badRequestError
(
self
,
name
):
self
.
setStatus
(
400
)
self
.
setStatus
(
400
)
if
re
.
match
(
'^[A-Z_0-9]+$'
,
name
):
if
re
.
match
(
'^[A-Z_0-9]+$'
,
name
):
raise
InternalError
(
self
.
_error_html
(
raise
InternalError
(
self
.
_error_html
(
"Internal Error"
,
"Internal Error"
,
"Sorry, an internal error occurred in this resource."
))
"Sorry, an internal error occurred in this resource."
))
...
@@ -761,15 +758,14 @@ class HTTPResponse(BaseResponse):
...
@@ -761,15 +758,14 @@ class HTTPResponse(BaseResponse):
else:
else:
try:
try:
l, b = v
l, b = v
if (isinstance(l, str)
if (isinstance(l, str) and absuri_match(l) is not None):
and absuri_match(l) is not None):
if self.status == 300:
if self.status == 300:
self.setStatus(302)
self.setStatus(302)
self.setHeader('
location
', l)
self.setHeader('
location
', l)
self.setBody(b)
self.setBody(b)
tb = None # one more patch covered
tb = None # one more patch covered
return self
return self
except:
except
Exception
:
pass # tb is not cleared in this case
pass # tb is not cleared in this case
b = v
b = v
...
@@ -785,8 +781,8 @@ class HTTPResponse(BaseResponse):
...
@@ -785,8 +781,8 @@ class HTTPResponse(BaseResponse):
if fatal and t is SystemExit and v.code == 0:
if fatal and t is SystemExit and v.code == 0:
body = self.setBody(
body = self.setBody(
(str(t),
(str(t),
'
Zope
has
exited
normally
.
<
p
>
'
'
Zope
has
exited
normally
.
<
p
>
'
+
+
self._traceback(t, v, tb) + '
</
p
>
'),
self._traceback(t, v, tb) + '
</
p
>
'),
is_error=1)
is_error=1)
else:
else:
try:
try:
...
@@ -796,9 +792,8 @@ class HTTPResponse(BaseResponse):
...
@@ -796,9 +792,8 @@ class HTTPResponse(BaseResponse):
if match is None:
if match is None:
body = self.setBody(
body = self.setBody(
(str(t),
(str(t),
'
Sorry
,
a
site
error
occurred
.
<
p
>
'
'
Sorry
,
a
site
error
occurred
.
<
p
>
' +
+ self._traceback(t, v, tb)
self._traceback(t, v, tb) + '
</
p
>
'),
+ '
</
p
>
'),
is_error=1)
is_error=1)
elif self.isHTML(b):
elif self.isHTML(b):
# error is an HTML document, not just a snippet of html
# error is an HTML document, not just a snippet of html
...
@@ -809,7 +804,7 @@ class HTTPResponse(BaseResponse):
...
@@ -809,7 +804,7 @@ class HTTPResponse(BaseResponse):
body = self.setBody(b, is_error=1)
body = self.setBody(b, is_error=1)
else:
else:
body = self.setBody(
body = self.setBody(
(str(t), b + self._traceback(t,'
(
see
above
)
', tb, 0)),
(str(t), b + self._traceback(t,
'
(
see
above
)
', tb, 0)),
is_error=1)
is_error=1)
del tb
del tb
return body
return body
...
@@ -831,15 +826,15 @@ class HTTPResponse(BaseResponse):
...
@@ -831,15 +826,15 @@ class HTTPResponse(BaseResponse):
for name, v in attrs.items():
for name, v in attrs.items():
name = name.lower()
name = name.lower()
if name == '
expires
':
if name == '
expires
':
cookie = '
%
s
;
Expires
=%
s
' % (cookie,v)
cookie = '
%
s
;
Expires
=%
s
' % (cookie,
v)
elif name == '
domain
':
elif name == '
domain
':
cookie = '
%
s
;
Domain
=%
s
' % (cookie,v)
cookie = '
%
s
;
Domain
=%
s
' % (cookie,
v)
elif name == '
path
':
elif name == '
path
':
cookie = '
%
s
;
Path
=%
s
' % (cookie,v)
cookie = '
%
s
;
Path
=%
s
' % (cookie,
v)
elif name == '
max_age
':
elif name == '
max_age
':
cookie = '
%
s
;
Max
-
Age
=%
s
' % (cookie,v)
cookie = '
%
s
;
Max
-
Age
=%
s
' % (cookie,
v)
elif name == '
comment
':
elif name == '
comment
':
cookie = '
%
s
;
Comment
=%
s
' % (cookie,v)
cookie = '
%
s
;
Comment
=%
s
' % (cookie,
v)
elif name == '
secure
' and v:
elif name == '
secure
' and v:
cookie = '
%
s
;
Secure
' % cookie
cookie = '
%
s
;
Secure
' % cookie
# Some browsers recognize this cookie attribute
# Some browsers recognize this cookie attribute
...
@@ -856,8 +851,8 @@ class HTTPResponse(BaseResponse):
...
@@ -856,8 +851,8 @@ class HTTPResponse(BaseResponse):
""" Set headers required by various parts of protocol.
""" Set headers required by various parts of protocol.
"""
"""
body = self.body
body = self.body
if (
not '
content
-
length
'
in self.headers and
if (
'
content
-
length
' not
in self.headers and
not '
transfer
-
encoding
'
in self.headers):
'
transfer
-
encoding
' not
in self.headers):
self.setHeader('
content
-
length
', len(body))
self.setHeader('
content
-
length
', len(body))
return "%d %s" % (self.status, self.errmsg), self.listHeaders()
return "%d %s" % (self.status, self.errmsg), self.listHeaders()
...
@@ -881,9 +876,7 @@ class HTTPResponse(BaseResponse):
...
@@ -881,9 +876,7 @@ class HTTPResponse(BaseResponse):
result.extend(self.accumulated_headers)
result.extend(self.accumulated_headers)
return result
return result
def __str__(self,
def __str__(self, html_search=re.compile('
<
html
>
', re.I).search):
html_search=re.compile('
<
html
>
',re.I).search,
):
if self._wrote:
if self._wrote:
return '' # Streaming output was used.
return '' # Streaming output was used.
...
@@ -902,8 +895,8 @@ class HTTPResponse(BaseResponse):
...
@@ -902,8 +895,8 @@ class HTTPResponse(BaseResponse):
chunks.append(body)
chunks.append(body)
return '
\
r
\
n
'.join(chunks)
return '
\
r
\
n
'.join(chunks)
def write(self,data):
def write(self,
data):
"""
\
"""
Return data as a stream
Return data as a stream
HTML data may be returned using a stream-oriented interface.
HTML data may be returned using a stream-oriented interface.
...
@@ -915,10 +908,8 @@ class HTTPResponse(BaseResponse):
...
@@ -915,10 +908,8 @@ class HTTPResponse(BaseResponse):
Note that published objects must not generate any errors
Note that published objects must not generate any errors
after beginning stream-oriented output.
after beginning stream-oriented output.
"""
"""
if not self._wrote:
if not self._wrote:
notify(PubBeforeStreaming(self))
notify(PubBeforeStreaming(self))
self.outputBody()
self.outputBody()
...
...
src/ZPublisher/Iterators.py
View file @
efe61189
from
zope.interface
import
Interface
from
zope.interface
import
Interface
from
zope.interface
import
implements
from
zope.interface
import
implements
class
IUnboundStreamIterator
(
Interface
):
class
IUnboundStreamIterator
(
Interface
):
"""
"""
An iterator with unknown length that can be published.
An iterator with unknown length that can be published.
...
@@ -25,7 +26,8 @@ class IStreamIterator(IUnboundStreamIterator):
...
@@ -25,7 +26,8 @@ class IStreamIterator(IUnboundStreamIterator):
is still closed, ZODB would raise an error. If the connection
is still closed, ZODB would raise an error. If the connection
happens to be re-opened by another thread, ZODB might allow it,
happens to be re-opened by another thread, ZODB might allow it,
but it has a chance of going insane if it happens to be loading
but it has a chance of going insane if it happens to be loading
or storing something in the other thread at the same time. """
or storing something in the other thread at the same time.
"""
def
__len__
():
def
__len__
():
"""
"""
...
@@ -42,7 +44,7 @@ class filestream_iterator(file):
...
@@ -42,7 +44,7 @@ class filestream_iterator(file):
implements
(
IStreamIterator
)
implements
(
IStreamIterator
)
def
__init__
(
self
,
name
,
mode
=
'r'
,
bufsize
=-
1
,
streamsize
=
1
<<
16
):
def
__init__
(
self
,
name
,
mode
=
'r'
,
bufsize
=-
1
,
streamsize
=
1
<<
16
):
file
.
__init__
(
self
,
name
,
mode
,
bufsize
)
file
.
__init__
(
self
,
name
,
mode
,
bufsize
)
self
.
streamsize
=
streamsize
self
.
streamsize
=
streamsize
...
@@ -57,5 +59,4 @@ class filestream_iterator(file):
...
@@ -57,5 +59,4 @@ class filestream_iterator(file):
self
.
seek
(
0
,
2
)
self
.
seek
(
0
,
2
)
size
=
self
.
tell
()
size
=
self
.
tell
()
self
.
seek
(
cur_pos
,
0
)
self
.
seek
(
cur_pos
,
0
)
return
size
return
size
src/ZPublisher/Publish.py
View file @
efe61189
...
@@ -14,6 +14,7 @@
...
@@ -14,6 +14,7 @@
"""
"""
import
os
import
os
import
sys
import
sys
from
thread
import
allocate_lock
import
transaction
import
transaction
from
urlparse
import
urlparse
from
urlparse
import
urlparse
...
@@ -24,11 +25,10 @@ from zope.publisher.interfaces.browser import IBrowserPage
...
@@ -24,11 +25,10 @@ from zope.publisher.interfaces.browser import IBrowserPage
from
zope.publisher.skinnable
import
setDefaultSkin
from
zope.publisher.skinnable
import
setDefaultSkin
from
zope.security.management
import
newInteraction
,
endInteraction
from
zope.security.management
import
newInteraction
,
endInteraction
from
.mapply
import
mapply
from
ZPublisher.mapply
import
mapply
from
.maybe_lock
import
allocate_lock
from
ZPublisher
import
pubevents
from
ZPublisher
import
pubevents
from
.Request
import
Request
from
ZPublisher.HTTPRequest
import
HTTPRequest
as
Request
from
.Response
import
Response
from
ZPublisher.HTTPResponse
import
HTTPResponse
as
Response
class
Retry
(
Exception
):
class
Retry
(
Exception
):
...
@@ -36,37 +36,47 @@ class Retry(Exception):
...
@@ -36,37 +36,47 @@ class Retry(Exception):
"""
"""
def
__init__
(
self
,
t
=
None
,
v
=
None
,
tb
=
None
):
def
__init__
(
self
,
t
=
None
,
v
=
None
,
tb
=
None
):
self
.
_args
=
t
,
v
,
tb
self
.
_args
=
t
,
v
,
tb
def
reraise
(
self
):
def
reraise
(
self
):
t
,
v
,
tb
=
self
.
_args
t
,
v
,
tb
=
self
.
_args
if
t
is
None
:
t
=
Retry
if
t
is
None
:
if
tb
is
None
:
raise
t
,
v
t
=
Retry
try
:
raise
t
,
v
,
tb
if
tb
is
None
:
finally
:
tb
=
None
raise
t
(
v
)
try
:
raise
t
,
v
,
tb
finally
:
tb
=
None
def
call_object
(
object
,
args
,
request
):
def
call_object
(
object
,
args
,
request
):
re
sult
=
apply
(
object
,
args
)
# Type s<cr> to step into published object.
re
turn
object
(
*
args
)
return
result
def
missing_name
(
name
,
request
):
def
missing_name
(
name
,
request
):
if
name
==
'self'
:
return
request
[
'PARENTS'
][
0
]
if
name
==
'self'
:
return
request
[
'PARENTS'
][
0
]
request
.
response
.
badRequestError
(
name
)
request
.
response
.
badRequestError
(
name
)
def
dont_publish_class
(
klass
,
request
):
def
dont_publish_class
(
klass
,
request
):
request
.
response
.
forbiddenError
(
"class %s"
%
klass
.
__name__
)
request
.
response
.
forbiddenError
(
"class %s"
%
klass
.
__name__
)
_default_debug_mode
=
False
_default_debug_mode
=
False
_default_realm
=
None
_default_realm
=
None
def
set_default_debug_mode
(
debug_mode
):
def
set_default_debug_mode
(
debug_mode
):
global
_default_debug_mode
global
_default_debug_mode
_default_debug_mode
=
debug_mode
_default_debug_mode
=
debug_mode
def
set_default_authentication_realm
(
realm
):
def
set_default_authentication_realm
(
realm
):
global
_default_realm
global
_default_realm
_default_realm
=
realm
_default_realm
=
realm
def
publish
(
request
,
module_name
,
after_list
,
debug
=
0
,
def
publish
(
request
,
module_name
,
after_list
,
debug
=
0
,
# Optimize:
# Optimize:
call_object
=
call_object
,
call_object
=
call_object
,
...
@@ -76,10 +86,10 @@ def publish(request, module_name, after_list, debug=0,
...
@@ -76,10 +86,10 @@ def publish(request, module_name, after_list, debug=0,
):
):
(
bobo_before
,
bobo_after
,
object
,
realm
,
debug_mode
,
err_hook
,
(
bobo_before
,
bobo_after
,
object
,
realm
,
debug_mode
,
err_hook
,
validated_hook
,
transactions_manager
)
=
get_module_info
(
module_name
)
validated_hook
,
transactions_manager
)
=
get_module_info
(
module_name
)
parents
=
None
parents
=
None
response
=
None
response
=
None
try
:
try
:
notify
(
pubevents
.
PubStart
(
request
))
notify
(
pubevents
.
PubStart
(
request
))
...
@@ -88,8 +98,8 @@ def publish(request, module_name, after_list, debug=0,
...
@@ -88,8 +98,8 @@ def publish(request, module_name, after_list, debug=0,
request
.
processInputs
()
request
.
processInputs
()
request_get
=
request
.
get
request_get
=
request
.
get
response
=
request
.
response
response
=
request
.
response
# First check for "cancel" redirect:
# First check for "cancel" redirect:
if
request_get
(
'SUBMIT'
,
''
).
strip
().
lower
()
==
'cancel'
:
if
request_get
(
'SUBMIT'
,
''
).
strip
().
lower
()
==
'cancel'
:
...
@@ -105,27 +115,27 @@ def publish(request, module_name, after_list, debug=0,
...
@@ -105,27 +115,27 @@ def publish(request, module_name, after_list, debug=0,
cancel
=
''
cancel
=
''
break
break
if
cancel
:
if
cancel
:
raise
Redirect
,
cancel
raise
Redirect
(
cancel
)
after_list
[
0
]
=
bobo_after
after_list
[
0
]
=
bobo_after
if
debug_mode
:
if
debug_mode
:
response
.
debug_mode
=
debug_mode
response
.
debug_mode
=
debug_mode
if
realm
and
not
request
.
get
(
'REMOTE_USER'
,
None
):
if
realm
and
not
request
.
get
(
'REMOTE_USER'
,
None
):
response
.
realm
=
realm
response
.
realm
=
realm
if
bobo_before
is
not
None
:
if
bobo_before
is
not
None
:
bobo_before
()
bobo_before
()
# Get the path list.
# Get the path list.
# According to RFC1738 a trailing space in the path is valid.
# According to RFC1738 a trailing space in the path is valid.
path
=
request_get
(
'PATH_INFO'
)
path
=
request_get
(
'PATH_INFO'
)
request
[
'PARENTS'
]
=
parents
=
[
object
]
request
[
'PARENTS'
]
=
parents
=
[
object
]
if
transactions_manager
:
if
transactions_manager
:
transactions_manager
.
begin
()
transactions_manager
.
begin
()
object
=
request
.
traverse
(
path
,
validated_hook
=
validated_hook
)
object
=
request
.
traverse
(
path
,
validated_hook
=
validated_hook
)
if
IBrowserPage
.
providedBy
(
object
):
if
IBrowserPage
.
providedBy
(
object
):
request
.
postProcessInputs
()
request
.
postProcessInputs
()
...
@@ -135,8 +145,8 @@ def publish(request, module_name, after_list, debug=0,
...
@@ -135,8 +145,8 @@ def publish(request, module_name, after_list, debug=0,
if
transactions_manager
:
if
transactions_manager
:
transactions_manager
.
recordMetaData
(
object
,
request
)
transactions_manager
.
recordMetaData
(
object
,
request
)
result
=
mapply
(
object
,
request
.
args
,
request
,
result
=
mapply
(
object
,
request
.
args
,
request
,
call_object
,
1
,
call_object
,
1
,
missing_name
,
missing_name
,
dont_publish_class
,
dont_publish_class
,
request
,
bind
=
1
)
request
,
bind
=
1
)
...
@@ -163,16 +173,16 @@ def publish(request, module_name, after_list, debug=0,
...
@@ -163,16 +173,16 @@ def publish(request, module_name, after_list, debug=0,
if
sm
is
not
None
:
if
sm
is
not
None
:
from
asyncore
import
compact_traceback
from
asyncore
import
compact_traceback
cl
,
val
=
sys
.
exc_info
()[:
2
]
cl
,
val
=
sys
.
exc_info
()[:
2
]
sm
(
'%s: %s %s'
%
(
sm
(
'%s: %s %s'
%
(
getattr
(
cl
,
'__name__'
,
cl
),
val
,
getattr
(
cl
,
'__name__'
,
cl
),
val
,
debug_mode
and
compact_traceback
()[
-
1
]
or
''
))
debug_mode
and
compact_traceback
()[
-
1
]
or
''
))
# debug is just used by tests (has nothing to do with debug_mode!)
# debug is just used by tests (has nothing to do with debug_mode!)
if
not
debug
and
err_hook
is
not
None
:
if
not
debug
and
err_hook
is
not
None
:
retry
=
False
retry
=
False
if
parents
:
if
parents
:
parents
=
parents
[
0
]
parents
=
parents
[
0
]
try
:
try
:
try
:
try
:
return
err_hook
(
parents
,
request
,
return
err_hook
(
parents
,
request
,
...
@@ -189,7 +199,8 @@ def publish(request, module_name, after_list, debug=0,
...
@@ -189,7 +199,8 @@ def publish(request, module_name, after_list, debug=0,
)
)
retry
=
True
retry
=
True
finally
:
finally
:
# Note: 'abort's can fail. Nevertheless, we want end request handling
# Note: 'abort's can fail.
# Nevertheless, we want end request handling.
try
:
try
:
try
:
try
:
notify
(
pubevents
.
PubBeforeAbort
(
notify
(
pubevents
.
PubBeforeAbort
(
...
@@ -202,7 +213,7 @@ def publish(request, module_name, after_list, debug=0,
...
@@ -202,7 +213,7 @@ def publish(request, module_name, after_list, debug=0,
notify
(
pubevents
.
PubFailure
(
request
,
exc_info
,
retry
))
notify
(
pubevents
.
PubFailure
(
request
,
exc_info
,
retry
))
# Only reachable if Retry is raised and request supports retry.
# Only reachable if Retry is raised and request supports retry.
newrequest
=
request
.
retry
()
newrequest
=
request
.
retry
()
request
.
close
()
# Free resources held by the request.
request
.
close
()
# Free resources held by the request.
# Set the default layer/skin on the newly generated request
# Set the default layer/skin on the newly generated request
...
@@ -214,7 +225,8 @@ def publish(request, module_name, after_list, debug=0,
...
@@ -214,7 +225,8 @@ def publish(request, module_name, after_list, debug=0,
newrequest
.
close
()
newrequest
.
close
()
else
:
else
:
# Note: 'abort's can fail. Nevertheless, we want end request handling
# Note: 'abort's can fail.
# Nevertheless, we want end request handling.
try
:
try
:
try
:
try
:
notify
(
pubevents
.
PubBeforeAbort
(
request
,
exc_info
,
False
))
notify
(
pubevents
.
PubBeforeAbort
(
request
,
exc_info
,
False
))
...
@@ -226,24 +238,26 @@ def publish(request, module_name, after_list, debug=0,
...
@@ -226,24 +238,26 @@ def publish(request, module_name, after_list, debug=0,
notify
(
pubevents
.
PubFailure
(
request
,
exc_info
,
False
))
notify
(
pubevents
.
PubFailure
(
request
,
exc_info
,
False
))
raise
raise
def
publish_module_standard
(
module_name
,
def
publish_module_standard
(
module_name
,
stdin
=
sys
.
stdin
,
stdout
=
sys
.
stdout
,
stderr
=
sys
.
stderr
,
stdin
=
sys
.
stdin
,
stdout
=
sys
.
stdout
,
stderr
=
sys
.
stderr
,
environ
=
os
.
environ
,
debug
=
0
,
request
=
None
,
response
=
None
):
environ
=
os
.
environ
,
debug
=
0
,
request
=
None
,
response
=
None
):
must_die
=
0
must_die
=
0
status
=
200
status
=
200
after_list
=
[
None
]
after_list
=
[
None
]
try
:
try
:
try
:
try
:
if
response
is
None
:
if
response
is
None
:
response
=
Response
(
stdout
=
stdout
,
stderr
=
stderr
)
response
=
Response
(
stdout
=
stdout
,
stderr
=
stderr
)
else
:
else
:
stdout
=
response
.
stdout
stdout
=
response
.
stdout
# debug is just used by tests (has nothing to do with debug_mode!)
# debug is just used by tests (has nothing to do with debug_mode!)
response
.
handle_errors
=
not
debug
response
.
handle_errors
=
not
debug
if
request
is
None
:
if
request
is
None
:
request
=
Request
(
stdin
,
environ
,
response
)
request
=
Request
(
stdin
,
environ
,
response
)
# make sure that the request we hand over has the
# make sure that the request we hand over has the
# default layer/skin set on it; subsequent code that
# default layer/skin set on it; subsequent code that
...
@@ -267,116 +281,129 @@ def publish_module_standard(module_name,
...
@@ -267,116 +281,129 @@ def publish_module_standard(module_name,
status
=
response
.
getStatus
()
status
=
response
.
getStatus
()
if
response
:
if
response
:
outputBody
=
getattr
(
response
,
'outputBody'
,
None
)
outputBody
=
getattr
(
response
,
'outputBody'
,
None
)
if
outputBody
is
not
None
:
if
outputBody
is
not
None
:
outputBody
()
outputBody
()
else
:
else
:
response
=
str
(
response
)
response
=
str
(
response
)
if
response
:
stdout
.
write
(
response
)
if
response
:
stdout
.
write
(
response
)
# The module defined a post-access function, call it
# The module defined a post-access function, call it
if
after_list
[
0
]
is
not
None
:
after_list
[
0
]()
if
after_list
[
0
]
is
not
None
:
after_list
[
0
]()
finally
:
finally
:
if
request
is
not
None
:
request
.
close
()
if
request
is
not
None
:
request
.
close
()
if
must_die
:
if
must_die
:
# Try to turn exception value into an exit code.
# Try to turn exception value into an exit code.
try
:
try
:
if
hasattr
(
must_die
[
1
],
'code'
):
if
hasattr
(
must_die
[
1
],
'code'
):
code
=
must_die
[
1
].
code
code
=
must_die
[
1
].
code
else
:
code
=
int
(
must_die
[
1
])
else
:
code
=
int
(
must_die
[
1
])
except
:
except
:
code
=
must_die
[
1
]
and
1
or
0
code
=
must_die
[
1
]
and
1
or
0
if
hasattr
(
request
.
response
,
'_requestShutdown'
):
if
hasattr
(
request
.
response
,
'_requestShutdown'
):
request
.
response
.
_requestShutdown
(
code
)
request
.
response
.
_requestShutdown
(
code
)
try
:
raise
must_die
[
0
],
must_die
[
1
],
must_die
[
2
]
try
:
finally
:
must_die
=
None
raise
must_die
[
0
],
must_die
[
1
],
must_die
[
2
]
finally
:
must_die
=
None
return
status
return
status
_l
=
allocate_lock
()
_l
=
allocate_lock
()
def
get_module_info
(
module_name
,
modules
=
{},
def
get_module_info
(
module_name
,
modules
=
{},
acquire
=
_l
.
acquire
,
acquire
=
_l
.
acquire
,
release
=
_l
.
release
,
release
=
_l
.
release
):
):
if
module_name
in
modules
:
return
modules
[
module_name
]
if
module_name
in
modules
:
return
modules
[
module_name
]
if
module_name
[
-
4
:]
==
'.cgi'
:
module_name
=
module_name
[:
-
4
]
if
module_name
[
-
4
:]
==
'.cgi'
:
module_name
=
module_name
[:
-
4
]
acquire
()
acquire
()
tb
=
None
tb
=
None
g
=
globals
()
g
=
globals
()
try
:
try
:
try
:
try
:
module
=
__import__
(
module_name
,
g
,
g
,
(
'__doc__'
,))
module
=
__import__
(
module_name
,
g
,
g
,
(
'__doc__'
,))
# Let the app specify a realm
# Let the app specify a realm
if
hasattr
(
module
,
'__bobo_realm__'
):
if
hasattr
(
module
,
'__bobo_realm__'
):
realm
=
module
.
__bobo_realm__
realm
=
module
.
__bobo_realm__
elif
_default_realm
is
not
None
:
elif
_default_realm
is
not
None
:
realm
=
_default_realm
realm
=
_default_realm
else
:
else
:
realm
=
module_name
realm
=
module_name
# Check for debug mode
# Check for debug mode
debug_mode
=
None
debug_mode
=
None
if
hasattr
(
module
,
'__bobo_debug_mode__'
):
if
hasattr
(
module
,
'__bobo_debug_mode__'
):
debug_mode
=
not
not
module
.
__bobo_debug_mode__
debug_mode
=
bool
(
module
.
__bobo_debug_mode__
)
else
:
else
:
debug_mode
=
_default_debug_mode
debug_mode
=
_default_debug_mode
bobo_before
=
getattr
(
module
,
"__bobo_before__"
,
None
)
bobo_before
=
getattr
(
module
,
"__bobo_before__"
,
None
)
bobo_after
=
getattr
(
module
,
"__bobo_after__"
,
None
)
bobo_after
=
getattr
(
module
,
"__bobo_after__"
,
None
)
if
hasattr
(
module
,
'bobo_application'
):
if
hasattr
(
module
,
'bobo_application'
):
object
=
module
.
bobo_application
object
=
module
.
bobo_application
elif
hasattr
(
module
,
'web_objects'
):
elif
hasattr
(
module
,
'web_objects'
):
object
=
module
.
web_objects
object
=
module
.
web_objects
else
:
object
=
module
else
:
object
=
module
error_hook
=
getattr
(
module
,
'zpublisher_exception_hook'
,
None
)
error_hook
=
getattr
(
module
,
'zpublisher_exception_hook'
,
None
)
validated_hook
=
getattr
(
module
,
'zpublisher_validated_hook'
,
None
)
validated_hook
=
getattr
(
module
,
'zpublisher_validated_hook'
,
None
)
transactions_manager
=
getattr
(
transactions_manager
=
getattr
(
module
,
'zpublisher_transactions_manager'
,
None
)
module
,
'zpublisher_transactions_manager'
,
None
)
if
not
transactions_manager
:
if
not
transactions_manager
:
# Create a default transactions manager for use
# Create a default transactions manager for use
# by software that uses ZPublisher and ZODB but
# by software that uses ZPublisher and ZODB but
# not the rest of Zope.
# not the rest of Zope.
transactions_manager
=
DefaultTransactionsManager
()
transactions_manager
=
DefaultTransactionsManager
()
info
=
(
bobo_before
,
bobo_after
,
object
,
realm
,
debug_mode
,
info
=
(
bobo_before
,
bobo_after
,
object
,
realm
,
debug_mode
,
error_hook
,
validated_hook
,
transactions_manager
)
error_hook
,
validated_hook
,
transactions_manager
)
modules
[
module_name
]
=
modules
[
module_name
+
'.cgi'
]
=
info
modules
[
module_name
]
=
modules
[
module_name
+
'.cgi'
]
=
info
return
info
return
info
except
:
except
:
t
,
v
,
tb
=
sys
.
exc_info
()
t
,
v
,
tb
=
sys
.
exc_info
()
v
=
str
(
v
)
v
=
str
(
v
)
raise
ImportError
,
(
t
,
v
),
tb
raise
ImportError
,
(
t
,
v
),
tb
finally
:
finally
:
tb
=
None
tb
=
None
release
()
release
()
class
DefaultTransactionsManager
:
class
DefaultTransactionsManager
:
def
begin
(
self
):
def
begin
(
self
):
transaction
.
begin
()
transaction
.
begin
()
def
commit
(
self
):
def
commit
(
self
):
transaction
.
commit
()
transaction
.
commit
()
def
abort
(
self
):
def
abort
(
self
):
transaction
.
abort
()
transaction
.
abort
()
def
recordMetaData
(
self
,
object
,
request
):
def
recordMetaData
(
self
,
object
,
request
):
# Is this code needed?
# Is this code needed?
request_get
=
request
.
get
request_get
=
request
.
get
T
=
transaction
.
get
()
T
=
transaction
.
get
()
T
.
note
(
request_get
(
'PATH_INFO'
))
T
.
note
(
request_get
(
'PATH_INFO'
))
auth_user
=
request_get
(
'AUTHENTICATED_USER'
,
None
)
auth_user
=
request_get
(
'AUTHENTICATED_USER'
,
None
)
if
auth_user
is
not
None
:
if
auth_user
is
not
None
:
T
.
setUser
(
auth_user
,
request_get
(
'AUTHENTICATION_PATH'
))
T
.
setUser
(
auth_user
,
request_get
(
'AUTHENTICATION_PATH'
))
...
@@ -384,6 +411,6 @@ class DefaultTransactionsManager:
...
@@ -384,6 +411,6 @@ class DefaultTransactionsManager:
def
publish_module
(
module_name
,
def
publish_module
(
module_name
,
stdin
=
sys
.
stdin
,
stdout
=
sys
.
stdout
,
stderr
=
sys
.
stderr
,
stdin
=
sys
.
stdin
,
stdout
=
sys
.
stdout
,
stderr
=
sys
.
stderr
,
environ
=
os
.
environ
,
debug
=
0
,
request
=
None
,
response
=
None
):
environ
=
os
.
environ
,
debug
=
0
,
request
=
None
,
response
=
None
):
""" publish a Python module
, with or without profiling enabled
"""
""" publish a Python module """
return
publish_module_standard
(
module_name
,
stdin
,
stdout
,
stderr
,
return
publish_module_standard
(
module_name
,
stdin
,
stdout
,
stderr
,
environ
,
debug
,
request
,
response
)
environ
,
debug
,
request
,
response
)
src/ZPublisher/Request.py
View file @
efe61189
...
@@ -10,6 +10,11 @@
...
@@ -10,6 +10,11 @@
# FOR A PARTICULAR PURPOSE
# FOR A PARTICULAR PURPOSE
#
#
##############################################################################
##############################################################################
import
HTTPRequest
Request
=
HTTPRequest
.
HTTPRequest
from
zope.deferredimport
import
deprecated
del
HTTPRequest
# BBB: Zope 5.0
deprecated
(
'Please import from ZPublisher.HTTPRequest'
,
Request
=
'ZPublisher.HTTPRequest:HTTPRequest'
,
)
src/ZPublisher/Response.py
View file @
efe61189
...
@@ -10,6 +10,11 @@
...
@@ -10,6 +10,11 @@
# FOR A PARTICULAR PURPOSE
# FOR A PARTICULAR PURPOSE
#
#
##############################################################################
##############################################################################
import
HTTPResponse
Response
=
HTTPResponse
.
HTTPResponse
from
zope.deferredimport
import
deprecated
del
HTTPResponse
# BBB: Zope 5.0
deprecated
(
'Please import from ZPublisher.HTTPResponse'
,
Response
=
'ZPublisher.HTTPResponse:HTTPResponse'
,
)
src/ZPublisher/__init__.py
View file @
efe61189
...
@@ -11,18 +11,6 @@
...
@@ -11,18 +11,6 @@
#
#
##############################################################################
##############################################################################
# This allows ZPublisher to work with embedded interpreters
from
zExceptions
import
NotFound
,
BadRequest
,
InternalError
,
Forbidden
# NOQA
# that for some reason have no sys.argv (required by cgi.py).
import
sys
if
not
hasattr
(
sys
,
'argv'
):
sys
.
argv
=
[]
from
zExceptions
import
NotFound
,
BadRequest
,
InternalError
,
Forbidden
from
ZPublisher.Publish
import
publish_module
,
Retry
# NOQA
from
Publish
import
publish_module
,
Retry
def
test
(
*
args
,
**
kw
):
global
test
import
Test
test
=
Test
.
publish
return
apply
(
test
,
args
,
kw
)
src/ZPublisher/interfaces.py
View file @
efe61189
...
@@ -4,6 +4,7 @@ from zope.interface import Interface, Attribute
...
@@ -4,6 +4,7 @@ from zope.interface import Interface, Attribute
# Publication events
# Publication events
# These are events notified in 'ZPublisher.Publish.publish'.
# These are events notified in 'ZPublisher.Publish.publish'.
class
IPubEvent
(
Interface
):
class
IPubEvent
(
Interface
):
'''Base class for publication events.
'''Base class for publication events.
...
@@ -12,9 +13,11 @@ class IPubEvent(Interface):
...
@@ -12,9 +13,11 @@ class IPubEvent(Interface):
'''
'''
request
=
Attribute
(
'The request being affected'
)
request
=
Attribute
(
'The request being affected'
)
class
IPubStart
(
IPubEvent
):
class
IPubStart
(
IPubEvent
):
'''Event notified at the beginning of 'ZPublisher.Publish.publish'.'''
'''Event notified at the beginning of 'ZPublisher.Publish.publish'.'''
class
IPubEnd
(
IPubEvent
):
class
IPubEnd
(
IPubEvent
):
'''Event notified after request processing.
'''Event notified after request processing.
...
@@ -22,16 +25,19 @@ class IPubEnd(IPubEvent):
...
@@ -22,16 +25,19 @@ class IPubEnd(IPubEvent):
itself is considered a new event.
itself is considered a new event.
'''
'''
class
IPubSuccess
(
IPubEnd
):
class
IPubSuccess
(
IPubEnd
):
'''A successful request processing.'''
'''A successful request processing.'''
class
IPubFailure
(
IPubEnd
):
class
IPubFailure
(
IPubEnd
):
'''A failed request processing.
'''A failed request processing.
Note: If a subscriber to 'IPubSuccess' raises an exception,
Note: If a subscriber to 'IPubSuccess' raises an exception,
then 'IPubFailure' may be notified in addtion to 'IPubSuccess'.
then 'IPubFailure' may be notified in addtion to 'IPubSuccess'.
'''
'''
exc_info
=
Attribute
(
'''The exception info as returned by 'sys.exc_info()'.'''
)
exc_info
=
Attribute
(
'''The exception info as returned by 'sys.exc_info()'.'''
)
retry
=
Attribute
(
'Whether the request will be retried'
)
retry
=
Attribute
(
'Whether the request will be retried'
)
...
@@ -44,29 +50,28 @@ class IPubBeforeCommit(IPubEvent):
...
@@ -44,29 +50,28 @@ class IPubBeforeCommit(IPubEvent):
request processing is finished).
request processing is finished).
"""
"""
class
IPubBeforeAbort
(
IPubEvent
):
class
IPubBeforeAbort
(
IPubEvent
):
"""notified immediately before the transaction abort (i.e. after the main
"""notified immediately before the transaction abort (i.e. after the main
request processing is finished, and there was an error).
request processing is finished, and there was an error).
"""
"""
exc_info
=
Attribute
(
'''The exception info as returned by 'sys.exc_info()'.'''
)
exc_info
=
Attribute
(
'''The exception info as returned by 'sys.exc_info()'.'''
)
retry
=
Attribute
(
'Whether the request will be retried'
)
retry
=
Attribute
(
'Whether the request will be retried'
)
class
IPubBeforeStreaming
(
Interface
):
class
IPubBeforeStreaming
(
Interface
):
"""Event fired just before a streaming response is initiated, i.e. when
"""Event fired just before a streaming response is initiated, i.e. when
something calls response.write() for the first time. Note that this is
something calls response.write() for the first time. Note that this is
carries a reference to the *response*, not the request.
carries a reference to the *response*, not the request.
"""
"""
response
=
Attribute
(
u"The current HTTP response"
)
response
=
Attribute
(
u"The current HTTP response"
)
# Exceptions
class
UseTraversalDefault
(
Exception
):
class
UseTraversalDefault
(
Exception
):
"""Indicate default traversal in ``__bobo_traverse__``
"""Indicate default traversal in ``__bobo_traverse__``
This exception can be raised by '__bobo_traverse__' implementations to
This exception can be raised by '__bobo_traverse__' implementations to
indicate that it has no special casing for the given name and that standard
indicate that it has no special casing for the given name and that standard
traversal logic should be applied.
traversal logic should be applied.
"""
"""
src/ZPublisher/mapply.py
View file @
efe61189
...
@@ -14,22 +14,26 @@
...
@@ -14,22 +14,26 @@
"""
"""
import
zope.publisher.publish
import
zope.publisher.publish
def
default_call_object
(
object
,
args
,
context
):
def
default_call_object
(
object
,
args
,
context
):
result
=
object
(
*
args
)
# Type s<cr> to step into published object.
result
=
object
(
*
args
)
# Type s<cr> to step into published object.
return
result
return
result
def
default_missing_name
(
name
,
context
):
def
default_missing_name
(
name
,
context
):
raise
TypeError
,
'argument %s was ommitted'
%
name
raise
TypeError
(
'argument %s was ommitted'
%
name
)
def
default_handle_class
(
klass
,
context
):
def
default_handle_class
(
klass
,
context
):
if
hasattr
(
klass
,
'__init__'
):
if
hasattr
(
klass
,
'__init__'
):
f
=
klass
.
__init__
.
im_func
f
=
klass
.
__init__
.
im_func
c
=
f
.
func_code
c
=
f
.
func_code
names
=
c
.
co_varnames
[
1
:
c
.
co_argcount
]
names
=
c
.
co_varnames
[
1
:
c
.
co_argcount
]
return
klass
,
names
,
f
.
func_defaults
return
klass
,
names
,
f
.
func_defaults
else
:
else
:
return
klass
,
(),
()
return
klass
,
(),
()
def
mapply
(
object
,
positional
=
(),
keyword
=
{},
def
mapply
(
object
,
positional
=
(),
keyword
=
{},
debug
=
None
,
maybe
=
None
,
debug
=
None
,
maybe
=
None
,
missing_name
=
default_missing_name
,
missing_name
=
default_missing_name
,
...
@@ -37,7 +41,7 @@ def mapply(object, positional=(), keyword={},
...
@@ -37,7 +41,7 @@ def mapply(object, positional=(), keyword={},
context
=
None
,
bind
=
0
,
context
=
None
,
bind
=
0
,
):
):
if
hasattr
(
object
,
'__bases__'
):
if
hasattr
(
object
,
'__bases__'
):
f
,
names
,
defaults
=
handle_class
(
object
,
context
)
f
,
names
,
defaults
=
handle_class
(
object
,
context
)
else
:
else
:
try
:
try
:
...
@@ -50,29 +54,34 @@ def mapply(object, positional=(), keyword={},
...
@@ -50,29 +54,34 @@ def mapply(object, positional=(), keyword={},
defaults
=
f
.
func_defaults
defaults
=
f
.
func_defaults
names
=
code
.
co_varnames
[
count
:
code
.
co_argcount
]
names
=
code
.
co_varnames
[
count
:
code
.
co_argcount
]
nargs
=
len
(
names
)
nargs
=
len
(
names
)
if
positional
:
if
positional
:
positional
=
list
(
positional
)
positional
=
list
(
positional
)
if
bind
and
nargs
and
names
[
0
]
==
'self'
:
if
bind
and
nargs
and
names
[
0
]
==
'self'
:
positional
.
insert
(
0
,
missing_name
(
'self'
,
context
))
positional
.
insert
(
0
,
missing_name
(
'self'
,
context
))
if
len
(
positional
)
>
nargs
:
raise
TypeError
,
'too many arguments'
if
len
(
positional
)
>
nargs
:
args
=
positional
raise
TypeError
(
'too many arguments'
)
args
=
positional
else
:
else
:
if
bind
and
nargs
and
names
[
0
]
==
'self'
:
if
bind
and
nargs
and
names
[
0
]
==
'self'
:
args
=
[
missing_name
(
'self'
,
context
)]
args
=
[
missing_name
(
'self'
,
context
)]
else
:
else
:
args
=
[]
args
=
[]
get
=
keyword
.
get
get
=
keyword
.
get
nrequired
=
len
(
names
)
-
(
len
(
defaults
or
()))
nrequired
=
len
(
names
)
-
(
len
(
defaults
or
()))
for
index
in
range
(
len
(
args
),
len
(
names
)):
for
index
in
range
(
len
(
args
),
len
(
names
)):
name
=
names
[
index
]
name
=
names
[
index
]
v
=
get
(
name
,
args
)
v
=
get
(
name
,
args
)
if
v
is
args
:
if
v
is
args
:
if
index
<
nrequired
:
v
=
missing_name
(
name
,
context
)
if
index
<
nrequired
:
else
:
v
=
defaults
[
index
-
nrequired
]
v
=
missing_name
(
name
,
context
)
else
:
v
=
defaults
[
index
-
nrequired
]
args
.
append
(
v
)
args
.
append
(
v
)
args
=
tuple
(
args
)
args
=
tuple
(
args
)
if
debug
is
not
None
:
return
debug
(
object
,
args
,
context
)
if
debug
is
not
None
:
else
:
return
object
(
*
args
)
return
debug
(
object
,
args
,
context
)
else
:
return
object
(
*
args
)
src/ZPublisher/maybe_lock.py
View file @
efe61189
...
@@ -11,9 +11,4 @@
...
@@ -11,9 +11,4 @@
#
#
##############################################################################
##############################################################################
# Waaaa, I wish I didn't have to work this hard.
from
thread
import
allocate_lock
# NOQA
try
:
from
thread
import
allocate_lock
except
:
class
allocate_lock
:
def
acquire
(
*
args
):
pass
def
release
(
*
args
):
pass
src/ZPublisher/pubevents.py
View file @
efe61189
...
@@ -9,9 +9,12 @@ for detailed time related analysis, inline request monitoring.
...
@@ -9,9 +9,12 @@ for detailed time related analysis, inline request monitoring.
'''
'''
from
zope.interface
import
implements
from
zope.interface
import
implements
from
interfaces
import
IPubStart
,
IPubSuccess
,
IPubFailure
,
\
from
ZPublisher.interfaces
import
(
IPubAfterTraversal
,
IPubBeforeCommit
,
IPubBeforeAbort
,
\
IPubStart
,
IPubSuccess
,
IPubFailure
,
IPubBeforeStreaming
IPubAfterTraversal
,
IPubBeforeCommit
,
IPubBeforeAbort
,
IPubBeforeStreaming
,
)
class
_Base
(
object
):
class
_Base
(
object
):
"""PubEvent base class."""
"""PubEvent base class."""
...
@@ -19,14 +22,17 @@ class _Base(object):
...
@@ -19,14 +22,17 @@ class _Base(object):
def
__init__
(
self
,
request
):
def
__init__
(
self
,
request
):
self
.
request
=
request
self
.
request
=
request
class
PubStart
(
_Base
):
class
PubStart
(
_Base
):
'''notified at the beginning of 'ZPublisher.Publish.publish'.'''
'''notified at the beginning of 'ZPublisher.Publish.publish'.'''
implements
(
IPubStart
)
implements
(
IPubStart
)
class
PubSuccess
(
_Base
):
class
PubSuccess
(
_Base
):
'''notified at successful request end.'''
'''notified at successful request end.'''
implements
(
IPubSuccess
)
implements
(
IPubSuccess
)
class
PubFailure
(
object
):
class
PubFailure
(
object
):
'''notified at failed request end.'''
'''notified at failed request end.'''
implements
(
IPubFailure
)
implements
(
IPubFailure
)
...
@@ -44,6 +50,7 @@ class PubBeforeCommit(_Base):
...
@@ -44,6 +50,7 @@ class PubBeforeCommit(_Base):
"""notified immediately before the commit."""
"""notified immediately before the commit."""
implements
(
IPubBeforeCommit
)
implements
(
IPubBeforeCommit
)
class
PubBeforeAbort
(
_Base
):
class
PubBeforeAbort
(
_Base
):
"""notified immediately before an abort."""
"""notified immediately before an abort."""
implements
(
IPubBeforeAbort
)
implements
(
IPubBeforeAbort
)
...
@@ -51,6 +58,7 @@ class PubBeforeAbort(_Base):
...
@@ -51,6 +58,7 @@ class PubBeforeAbort(_Base):
def
__init__
(
self
,
request
,
exc_info
,
retry
):
def
__init__
(
self
,
request
,
exc_info
,
retry
):
self
.
request
,
self
.
exc_info
,
self
.
retry
=
request
,
exc_info
,
retry
self
.
request
,
self
.
exc_info
,
self
.
retry
=
request
,
exc_info
,
retry
class
PubBeforeStreaming
(
object
):
class
PubBeforeStreaming
(
object
):
"""Notified immediately before streaming via response.write() commences
"""Notified immediately before streaming via response.write() commences
"""
"""
...
...
src/ZPublisher/tests/__init__.py
View file @
efe61189
# This helps debugging.
src/ZPublisher/tests/generate_conflicts.py
deleted
100644 → 0
View file @
2e9d01ea
## This script requires:
## - python >= 2.4
## - zope.testbrowser
##
## The just run:
## $python generate_conflicts.py
import
base64
import
string
import
threading
import
urllib2
from
zope.testbrowser.browser
import
Browser
# create our browser
class
AuthBrowser
(
Browser
):
def
addBasicAuth
(
self
,
username
,
password
):
self
.
addHeader
(
'Authorization'
,
'Basic '
+
base64
.
encodestring
(
username
+
':'
+
password
).
strip
()
)
def
open
(
self
,
uri
,
include_server
=
True
):
if
include_server
:
uri
=
server
+
uri
return
Browser
.
open
(
self
,
uri
)
browser
=
AuthBrowser
()
# constants
server
=
'http://localhost:8080'
# the following user must be able to view the management screens
# and create file objects
username
=
'username'
password
=
'password'
browser
.
addBasicAuth
(
username
,
password
)
threads
=
10
filename
=
'conflict.txt'
filesize
=
10000
hits
=
5
# delete the file if it's already there
browser
.
open
(
'/manage_main'
)
if
filename
in
[
c
.
optionValue
for
c
in
browser
.
getControl
(
name
=
'ids:list'
).
controls
]:
browser
.
open
(
'/manage_delObjects?ids:list='
+
filename
)
# create it
browser
.
open
(
'/manage_addFile?id='
+
filename
)
# edit it, hopefully causing conflicts
data
=
'X'
*
filesize
class
EditThread
(
threading
.
Thread
):
def
__init__
(
self
,
i
):
self
.
conflicts
=
0
self
.
browser
=
AuthBrowser
()
self
.
browser
.
handleErrors
=
False
self
.
browser
.
addBasicAuth
(
username
,
password
)
threading
.
Thread
.
__init__
(
self
,
name
=
str
(
i
))
def
run
(
self
):
for
i
in
range
(
1
,
hits
+
1
):
self
.
browser
.
open
(
'/conflict.txt/manage_main'
)
self
.
browser
.
getControl
(
name
=
'title'
).
value
=
'Test Title'
self
.
browser
.
getControl
(
name
=
'filedata:text'
).
value
=
data
try
:
self
.
browser
.
getControl
(
name
=
'manage_edit:method'
).
click
()
except
urllib2
.
HTTPError
,
e
:
# print e.read()
self
.
conflicts
+=
1
print
"Thread %s - CONFLICT"
%
self
.
getName
()
else
:
print
"Thread %s - EDIT"
%
self
.
getName
()
thread_objects
=
[]
for
i
in
range
(
1
,
threads
+
1
):
t
=
EditThread
(
i
)
thread_objects
.
append
(
t
)
t
.
start
()
for
t
in
thread_objects
:
t
.
join
()
total
=
0
print
for
t
in
thread_objects
:
print
"Thread %s - %i conflicts seen"
%
(
t
.
getName
(),
t
.
conflicts
)
total
+=
t
.
conflicts
print
print
"%i conflicts seen by browsers"
%
total
src/ZPublisher/tests/testBaseRequest.py
View file @
efe61189
...
@@ -33,26 +33,24 @@ class BaseRequest_factory:
...
@@ -33,26 +33,24 @@ class BaseRequest_factory:
if
base
is
None
:
if
base
is
None
:
base
=
''
base
=
''
elif
not
base
.
endswith
(
'/'
):
elif
not
base
.
endswith
(
'/'
):
base
=
base
+
'/'
base
=
base
+
'/'
self
.
base
=
str
(
base
)
self
.
base
=
str
(
base
)
def
notFoundError
(
self
,
name
):
def
notFoundError
(
self
,
name
):
from
zExceptions
import
NotFound
from
zExceptions
import
NotFound
raise
NotFound
(
name
)
raise
NotFound
(
name
)
# Real responses raise NotFound, to avoid information disclosure
#def forbiddenError(self, name):
# from zExceptions import Forbidden
# raise Forbidden(name)
forbiddenError
=
notFoundError
forbiddenError
=
notFoundError
response
=
DummyResponse
()
response
=
DummyResponse
()
environment
=
{
'URL'
:
''
,
environment
=
{
'URL'
:
''
,
'PARENTS'
:
[
root
],
'PARENTS'
:
[
root
],
'steps'
:
[],
'steps'
:
[],
'_hacked_path'
:
0
,
'_hacked_path'
:
0
,
'_test_counter'
:
0
,
'_test_counter'
:
0
,
'response'
:
response
}
'response'
:
response
}
return
self
.
_getTargetClass
()(
environment
)
return
self
.
_getTargetClass
()(
environment
)
def
_makeBasicObjectClass
(
self
):
def
_makeBasicObjectClass
(
self
):
...
@@ -112,7 +110,7 @@ class BaseRequest_factory:
...
@@ -112,7 +110,7 @@ class BaseRequest_factory:
else
:
else
:
raise
RuntimeError
(
'Infinite loop detected.'
)
raise
RuntimeError
(
'Infinite loop detected.'
)
REQUEST
[
'TraversalRequestNameStack'
]
+=
self
.
_path
REQUEST
[
'TraversalRequestNameStack'
]
+=
self
.
_path
REQUEST
.
_hacked_path
=
1
REQUEST
.
_hacked_path
=
1
return
DummyObjectWithBPTH
()
return
DummyObjectWithBPTH
()
...
@@ -151,16 +149,18 @@ class BaseRequest_factory:
...
@@ -151,16 +149,18 @@ class BaseRequest_factory:
def
_makeObjectWithBDBBT
(
self
):
def
_makeObjectWithBDBBT
(
self
):
class
DummyObjectWithBDBBT
(
self
.
_makeBasicObjectClass
()):
class
DummyObjectWithBDBBT
(
self
.
_makeBasicObjectClass
()):
"""Dummy class with __browser_default__."""
"""Dummy class with __browser_default__."""
def
__browser_default__
(
self
,
REQUEST
):
def
__browser_default__
(
self
,
REQUEST
):
if
REQUEST
[
'_test_counter'
]
<
100
:
if
REQUEST
[
'_test_counter'
]
<
100
:
REQUEST
[
'_test_counter'
]
+=
1
REQUEST
[
'_test_counter'
]
+=
1
else
:
else
:
raise
RuntimeError
(
'Infinite loop detected.'
)
raise
RuntimeError
(
'Infinite loop detected.'
)
return
self
,
self
.
_default_path
return
self
,
self
.
_default_path
def
__bobo_traverse__
(
self
,
REQUEST
,
name
):
def
__bobo_traverse__
(
self
,
REQUEST
,
name
):
if
name
==
self
.
_default_path
[
0
]:
if
name
==
self
.
_default_path
[
0
]:
return
getattr
(
self
,
name
)
return
getattr
(
self
,
name
)
raise
AttributeError
,
name
raise
AttributeError
(
name
)
return
DummyObjectWithBDBBT
()
return
DummyObjectWithBDBBT
()
def
_makeObjectWithEmptyDocstring
(
self
):
def
_makeObjectWithEmptyDocstring
(
self
):
...
@@ -292,8 +292,9 @@ class TestBaseRequest(unittest.TestCase, BaseRequest_factory):
...
@@ -292,8 +292,9 @@ class TestBaseRequest(unittest.TestCase, BaseRequest_factory):
# that we get a NotFound
# that we get a NotFound
from
ZPublisher
import
NotFound
from
ZPublisher
import
NotFound
root
,
folder
=
self
.
_makeRootAndFolder
()
root
,
folder
=
self
.
_makeRootAndFolder
()
def
_faux___bobo_traverse__
(
REQUEST
,
name
):
def
_faux___bobo_traverse__
(
REQUEST
,
name
):
raise
AttributeError
,
name
raise
AttributeError
(
name
)
obj
=
self
.
_makeBasicObject
()
obj
=
self
.
_makeBasicObject
()
obj
.
__bobo_traverse__
=
_faux___bobo_traverse__
obj
.
__bobo_traverse__
=
_faux___bobo_traverse__
folder
.
_setObject
(
'objWithBBT'
,
obj
)
folder
.
_setObject
(
'objWithBBT'
,
obj
)
...
@@ -309,7 +310,8 @@ class TestBaseRequest(unittest.TestCase, BaseRequest_factory):
...
@@ -309,7 +310,8 @@ class TestBaseRequest(unittest.TestCase, BaseRequest_factory):
self
.
assertEqual
(
r
.
traverse
(
'folder/objWithBBT/normal'
).
tag
,
'Normal'
)
self
.
assertEqual
(
r
.
traverse
(
'folder/objWithBBT/normal'
).
tag
,
'Normal'
)
# test default usage
# test default usage
r
=
self
.
_makeOne
(
root
)
r
=
self
.
_makeOne
(
root
)
self
.
assertEqual
(
r
.
traverse
(
'folder/objWithBBT/default'
).
tag
,
'Default'
)
self
.
assertEqual
(
r
.
traverse
(
'folder/objWithBBT/default'
).
tag
,
'Default'
)
def
test_traverse_withBDBBT
(
self
):
def
test_traverse_withBDBBT
(
self
):
# Test for an object which has a __browser_default__
# Test for an object which has a __browser_default__
...
@@ -444,6 +446,7 @@ class TestBaseRequest(unittest.TestCase, BaseRequest_factory):
...
@@ -444,6 +446,7 @@ class TestBaseRequest(unittest.TestCase, BaseRequest_factory):
r
=
self
.
_makeOne
(
root
)
r
=
self
.
_makeOne
(
root
)
r
.
other
[
'foo'
]
=
'Foo'
r
.
other
[
'foo'
]
=
'Foo'
BEFORE
=
subscribers
[:]
BEFORE
=
subscribers
[:]
def
_broken
(
event
):
def
_broken
(
event
):
raise
ValueError
(
"I'm broken"
)
raise
ValueError
(
"I'm broken"
)
subscribers
.
append
(
_broken
)
subscribers
.
append
(
_broken
)
...
@@ -481,7 +484,7 @@ class TestBaseRequest(unittest.TestCase, BaseRequest_factory):
...
@@ -481,7 +484,7 @@ class TestBaseRequest(unittest.TestCase, BaseRequest_factory):
self
.
assertRaises
(
NotFound
,
r
.
traverse
,
'not_found'
)
self
.
assertRaises
(
NotFound
,
r
.
traverse
,
'not_found'
)
class
TestRequest
Zope3
ViewsBase
(
unittest
.
TestCase
,
BaseRequest_factory
):
class
TestRequestViewsBase
(
unittest
.
TestCase
,
BaseRequest_factory
):
_dummy_interface
=
None
_dummy_interface
=
None
...
@@ -492,7 +495,7 @@ class TestRequestZope3ViewsBase(unittest.TestCase, BaseRequest_factory):
...
@@ -492,7 +495,7 @@ class TestRequestZope3ViewsBase(unittest.TestCase, BaseRequest_factory):
def
_makeOne
(
self
,
root
):
def
_makeOne
(
self
,
root
):
from
zope.interface
import
directlyProvides
from
zope.interface
import
directlyProvides
from
zope.publisher.browser
import
IDefaultBrowserLayer
from
zope.publisher.browser
import
IDefaultBrowserLayer
request
=
super
(
TestRequest
Zope3
ViewsBase
,
self
).
_makeOne
(
root
)
request
=
super
(
TestRequestViewsBase
,
self
).
_makeOne
(
root
)
# The request needs to implement the proper interface
# The request needs to implement the proper interface
directlyProvides
(
request
,
IDefaultBrowserLayer
)
directlyProvides
(
request
,
IDefaultBrowserLayer
)
return
request
return
request
...
@@ -532,6 +535,7 @@ class TestRequestZope3ViewsBase(unittest.TestCase, BaseRequest_factory):
...
@@ -532,6 +535,7 @@ class TestRequestZope3ViewsBase(unittest.TestCase, BaseRequest_factory):
class
DummyObjectZ3
(
self
.
_makeBasicObjectClass
()):
class
DummyObjectZ3
(
self
.
_makeBasicObjectClass
()):
implements
(
self
.
_dummyInterface
())
implements
(
self
.
_dummyInterface
())
def
__init__
(
self
,
name
):
def
__init__
(
self
,
name
):
self
.
name
=
name
self
.
name
=
name
...
@@ -542,12 +546,14 @@ class TestRequestZope3ViewsBase(unittest.TestCase, BaseRequest_factory):
...
@@ -542,12 +546,14 @@ class TestRequestZope3ViewsBase(unittest.TestCase, BaseRequest_factory):
class
DummyObjectZ3WithAttr
(
self
.
_makeBasicObjectClass
()):
class
DummyObjectZ3WithAttr
(
self
.
_makeBasicObjectClass
()):
implements
(
self
.
_dummyInterface
())
implements
(
self
.
_dummyInterface
())
def
__init__
(
self
,
name
):
def
__init__
(
self
,
name
):
self
.
name
=
name
self
.
name
=
name
def
meth
(
self
):
def
meth
(
self
):
"""doc"""
"""doc"""
return
'meth on %s'
%
self
.
name
return
'meth on %s'
%
self
.
name
def
methonly
(
self
):
def
methonly
(
self
):
"""doc"""
"""doc"""
return
'methonly on %s'
%
self
.
name
return
'methonly on %s'
%
self
.
name
...
@@ -577,11 +583,11 @@ class TestRequestZope3ViewsBase(unittest.TestCase, BaseRequest_factory):
...
@@ -577,11 +583,11 @@ class TestRequestZope3ViewsBase(unittest.TestCase, BaseRequest_factory):
def
__init__
(
self
,
content
,
request
):
def
__init__
(
self
,
content
,
request
):
self
.
content
=
content
self
.
content
=
content
self
.
request
=
request
self
.
request
=
request
def
__call__
(
self
):
def
__call__
(
self
):
return
'view on %s'
%
(
self
.
content
.
name
)
return
'view on %s'
%
(
self
.
content
.
name
)
class
DummyPage
(
BrowserPage
):
class
DummyPage
(
BrowserPage
):
# BrowserPage is an IBrowserPublisher with a browserDefault that
# BrowserPage is an IBrowserPublisher with a browserDefault that
# returns self, () so that __call__ is invoked by the publisher.
# returns self, () so that __call__ is invoked by the publisher.
...
@@ -594,7 +600,8 @@ class TestRequestZope3ViewsBase(unittest.TestCase, BaseRequest_factory):
...
@@ -594,7 +600,8 @@ class TestRequestZope3ViewsBase(unittest.TestCase, BaseRequest_factory):
# intentionally return something that's not self
# intentionally return something that's not self
return
DummyPage
(
self
.
context
,
request
),
()
return
DummyPage
(
self
.
context
,
request
),
()
# __call__ remains unimplemented, baseclass raises NotImplementedError
# __call__ remains unimplemented,
# baseclass raises NotImplementedError
class
DummyPage3
(
BrowserPage
):
class
DummyPage3
(
BrowserPage
):
...
@@ -605,7 +612,8 @@ class TestRequestZope3ViewsBase(unittest.TestCase, BaseRequest_factory):
...
@@ -605,7 +612,8 @@ class TestRequestZope3ViewsBase(unittest.TestCase, BaseRequest_factory):
def
foo
(
self
):
def
foo
(
self
):
return
'Test page'
return
'Test page'
# __call__ remains unimplemented, baseclass raises NotImplementedError
# __call__ remains unimplemented,
# baseclass raises NotImplementedError
class
DummyPage4
(
Implicit
,
DummyPage
):
class
DummyPage4
(
Implicit
,
DummyPage
):
# a normal page that can implicitly acquire attributes
# a normal page that can implicitly acquire attributes
...
@@ -641,10 +649,10 @@ class TestRequestZope3ViewsBase(unittest.TestCase, BaseRequest_factory):
...
@@ -641,10 +649,10 @@ class TestRequestZope3ViewsBase(unittest.TestCase, BaseRequest_factory):
IDefaultViewName
,
''
)
IDefaultViewName
,
''
)
class
TestBaseRequest
Zope3Views
(
TestRequestZope3
ViewsBase
):
class
TestBaseRequest
Views
(
TestRequest
ViewsBase
):
def
test_traverse_view
(
self
):
def
test_traverse_view
(
self
):
#simple view
#
simple view
root
,
folder
=
self
.
_makeRootAndFolder
()
root
,
folder
=
self
.
_makeRootAndFolder
()
folder
.
_setObject
(
'obj'
,
self
.
_makeDummyObject
(
'obj'
))
folder
.
_setObject
(
'obj'
,
self
.
_makeDummyObject
(
'obj'
))
r
=
self
.
_makeOne
(
root
)
r
=
self
.
_makeOne
(
root
)
...
@@ -658,9 +666,10 @@ class TestBaseRequestZope3Views(TestRequestZope3ViewsBase):
...
@@ -658,9 +666,10 @@ class TestBaseRequestZope3Views(TestRequestZope3ViewsBase):
self
.
assertEqual
(
ob
(),
'view on obj'
)
self
.
assertEqual
(
ob
(),
'view on obj'
)
def
test_traverse_view_attr_local
(
self
):
def
test_traverse_view_attr_local
(
self
):
#method on object used first
#
method on object used first
root
,
folder
=
self
.
_makeRootAndFolder
()
root
,
folder
=
self
.
_makeRootAndFolder
()
folder
.
_setObject
(
'withattr'
,
self
.
_makeDummyObjectWithAttr
(
'withattr'
))
folder
.
_setObject
(
'withattr'
,
self
.
_makeDummyObjectWithAttr
(
'withattr'
))
r
=
self
.
_makeOne
(
root
)
r
=
self
.
_makeOne
(
root
)
ob
=
r
.
traverse
(
'folder/withattr/meth'
)
ob
=
r
.
traverse
(
'folder/withattr/meth'
)
self
.
assertEqual
(
ob
(),
'meth on withattr'
)
self
.
assertEqual
(
ob
(),
'meth on withattr'
)
...
@@ -672,9 +681,10 @@ class TestBaseRequestZope3Views(TestRequestZope3ViewsBase):
...
@@ -672,9 +681,10 @@ class TestBaseRequestZope3Views(TestRequestZope3ViewsBase):
self
.
assertEqual
(
ob
(),
'view on withattr'
)
self
.
assertEqual
(
ob
(),
'view on withattr'
)
def
test_traverse_view_attr_above
(
self
):
def
test_traverse_view_attr_above
(
self
):
#view takes precedence over acquired attribute
#
view takes precedence over acquired attribute
root
,
folder
=
self
.
_makeRootAndFolder
()
root
,
folder
=
self
.
_makeRootAndFolder
()
folder2
=
root
.
_setObject
(
'folder2'
,
self
.
_makeDummyObjectWithAttr
(
'folder2'
))
folder2
=
root
.
_setObject
(
'folder2'
,
self
.
_makeDummyObjectWithAttr
(
'folder2'
))
folder2
.
_setObject
(
'obj2'
,
self
.
_makeDummyObject
(
'obj2'
))
folder2
.
_setObject
(
'obj2'
,
self
.
_makeDummyObject
(
'obj2'
))
r
=
self
.
_makeOne
(
root
)
r
=
self
.
_makeOne
(
root
)
ob
=
r
.
traverse
(
'folder2/obj2/meth'
)
ob
=
r
.
traverse
(
'folder2/obj2/meth'
)
...
@@ -687,10 +697,12 @@ class TestBaseRequestZope3Views(TestRequestZope3ViewsBase):
...
@@ -687,10 +697,12 @@ class TestBaseRequestZope3Views(TestRequestZope3ViewsBase):
self
.
assertEqual
(
ob
(),
'view on obj2'
)
self
.
assertEqual
(
ob
(),
'view on obj2'
)
def
test_traverse_view_attr_local2
(
self
):
def
test_traverse_view_attr_local2
(
self
):
#method with other method above
#
method with other method above
root
,
folder
=
self
.
_makeRootAndFolder
()
root
,
folder
=
self
.
_makeRootAndFolder
()
folder2
=
root
.
_setObject
(
'folder2'
,
self
.
_makeDummyObjectWithAttr
(
'folder2'
))
folder2
=
root
.
_setObject
(
folder2
.
_setObject
(
'withattr2'
,
self
.
_makeDummyObjectWithAttr
(
'withattr2'
))
'folder2'
,
self
.
_makeDummyObjectWithAttr
(
'folder2'
))
folder2
.
_setObject
(
'withattr2'
,
self
.
_makeDummyObjectWithAttr
(
'withattr2'
))
r
=
self
.
_makeOne
(
root
)
r
=
self
.
_makeOne
(
root
)
ob
=
r
.
traverse
(
'folder2/withattr2/meth'
)
ob
=
r
.
traverse
(
'folder2/withattr2/meth'
)
self
.
assertEqual
(
ob
(),
'meth on withattr2'
)
self
.
assertEqual
(
ob
(),
'meth on withattr2'
)
...
@@ -702,10 +714,11 @@ class TestBaseRequestZope3Views(TestRequestZope3ViewsBase):
...
@@ -702,10 +714,11 @@ class TestBaseRequestZope3Views(TestRequestZope3ViewsBase):
self
.
assertEqual
(
ob
(),
'view on withattr2'
)
self
.
assertEqual
(
ob
(),
'view on withattr2'
)
def
test_traverse_view_attr_acquired
(
self
):
def
test_traverse_view_attr_acquired
(
self
):
#normal acquired attribute without view
#
normal acquired attribute without view
from
ZPublisher
import
NotFound
from
ZPublisher
import
NotFound
root
,
folder
=
self
.
_makeRootAndFolder
()
root
,
folder
=
self
.
_makeRootAndFolder
()
folder2
=
root
.
_setObject
(
'folder2'
,
self
.
_makeDummyObjectWithAttr
(
'folder2'
))
folder2
=
root
.
_setObject
(
'folder2'
,
self
.
_makeDummyObjectWithAttr
(
'folder2'
))
folder2
.
_setObject
(
'obj2'
,
self
.
_makeDummyObject
(
'obj2'
))
folder2
.
_setObject
(
'obj2'
,
self
.
_makeDummyObject
(
'obj2'
))
r
=
self
.
_makeOne
(
root
)
r
=
self
.
_makeOne
(
root
)
ob
=
r
.
traverse
(
'folder2/obj2/methonly'
)
ob
=
r
.
traverse
(
'folder2/obj2/methonly'
)
...
@@ -716,7 +729,7 @@ class TestBaseRequestZope3Views(TestRequestZope3ViewsBase):
...
@@ -716,7 +729,7 @@ class TestBaseRequestZope3Views(TestRequestZope3ViewsBase):
self
.
assertRaises
(
NotFound
,
r
.
traverse
,
'folder2/obj2'
)
self
.
assertRaises
(
NotFound
,
r
.
traverse
,
'folder2/obj2'
)
def
test_quoting_goggles
(
self
):
def
test_quoting_goggles
(
self
):
#View goggles ('@@') should not be quoted
#
View goggles ('@@') should not be quoted
root
,
folder
=
self
.
_makeRootAndFolder
()
root
,
folder
=
self
.
_makeRootAndFolder
()
folder
.
_setObject
(
'obj'
,
self
.
_makeDummyObject
(
'obj'
))
folder
.
_setObject
(
'obj'
,
self
.
_makeDummyObject
(
'obj'
))
r
=
self
.
_makeOne
(
root
)
r
=
self
.
_makeOne
(
root
)
...
@@ -724,7 +737,7 @@ class TestBaseRequestZope3Views(TestRequestZope3ViewsBase):
...
@@ -724,7 +737,7 @@ class TestBaseRequestZope3Views(TestRequestZope3ViewsBase):
self
.
assertEqual
(
r
[
'URL'
],
'/folder/obj/@@meth'
)
self
.
assertEqual
(
r
[
'URL'
],
'/folder/obj/@@meth'
)
def
test_quoting_plusplus
(
self
):
def
test_quoting_plusplus
(
self
):
#View markers ('++ should not be quoted
#
View markers ('++ should not be quoted
root
,
folder
=
self
.
_makeRootAndFolder
()
root
,
folder
=
self
.
_makeRootAndFolder
()
folder
.
_setObject
(
'obj'
,
self
.
_makeDummyObject
(
'obj'
))
folder
.
_setObject
(
'obj'
,
self
.
_makeDummyObject
(
'obj'
))
r
=
self
.
_makeOne
(
root
)
r
=
self
.
_makeOne
(
root
)
...
@@ -764,10 +777,3 @@ class TestBaseRequestZope3Views(TestRequestZope3ViewsBase):
...
@@ -764,10 +777,3 @@ class TestBaseRequestZope3Views(TestRequestZope3ViewsBase):
self
.
assertEqual
(
ob
(),
'Test page'
)
self
.
assertEqual
(
ob
(),
'Test page'
)
# make sure we can acquire
# make sure we can acquire
self
.
assertEqual
(
ob
.
ob2
,
ob2
)
self
.
assertEqual
(
ob
.
ob2
,
ob2
)
def
test_suite
():
return
unittest
.
TestSuite
((
unittest
.
makeSuite
(
TestBaseRequest
),
unittest
.
makeSuite
(
TestBaseRequestZope3Views
),
))
src/ZPublisher/tests/testBeforeTraverse.py
View file @
efe61189
import
sys
import
doctest
import
logging
from
Acquisition
import
Implicit
from
Acquisition
import
Implicit
from
ZPublisher
import
BeforeTraverse
from
ZPublisher.BaseRequest
import
BaseRequest
from
ZPublisher.BaseRequest
import
BaseRequest
from
ZPublisher.HTTPResponse
import
HTTPResponse
from
ZPublisher.HTTPResponse
import
HTTPResponse
def
makeBaseRequest
(
root
):
def
makeBaseRequest
(
root
):
response
=
HTTPResponse
()
response
=
HTTPResponse
()
environment
=
{
'URL'
:
''
,
environment
=
{
'URL'
:
''
,
'PARENTS'
:
[
root
],
'PARENTS'
:
[
root
],
'steps'
:
[],
'steps'
:
[],
'_hacked_path'
:
0
,
'_hacked_path'
:
0
,
'_test_counter'
:
0
,
'_test_counter'
:
0
,
'response'
:
response
}
'response'
:
response
,
}
return
BaseRequest
(
environment
)
return
BaseRequest
(
environment
)
...
@@ -23,11 +24,12 @@ class DummyObjectBasic(Implicit):
...
@@ -23,11 +24,12 @@ class DummyObjectBasic(Implicit):
pass
pass
class
BrokenHook
:
class
BrokenHook
(
object
)
:
def
__call__
(
self
,
*
args
):
def
__call__
(
self
,
*
args
):
print
self
.
__class__
.
__name__
,
'called'
print
(
'%s called'
%
self
.
__class__
.
__name__
)
raise
TypeError
,
self
.
__class__
.
__name__
raise
TypeError
(
self
.
__class__
.
__name__
)
def
testBeforeTraverse
(
self
):
def
testBeforeTraverse
(
self
):
"""
"""
...
@@ -36,6 +38,10 @@ def testBeforeTraverse(self):
...
@@ -36,6 +38,10 @@ def testBeforeTraverse(self):
special API for registering hooks, and the hooks themselves are
special API for registering hooks, and the hooks themselves are
called during traversal by ZPublisher.
called during traversal by ZPublisher.
>>> import sys
>>> import logging
>>> from ZPublisher import BeforeTraverse
>>> root = DummyObjectBasic()
>>> root = DummyObjectBasic()
>>> request = makeBaseRequest(root)
>>> request = makeBaseRequest(root)
...
@@ -131,10 +137,7 @@ def testBeforeTraverse(self):
...
@@ -131,10 +137,7 @@ def testBeforeTraverse(self):
>>> logger.handlers = handlers[:]
>>> logger.handlers = handlers[:]
"""
"""
pass
import
doctest
def
test_suite
():
def
test_suite
():
return
doctest
.
DocTestSuite
(
optionflags
=
doctest
.
ELLIPSIS
)
return
doctest
.
DocTestSuite
(
optionflags
=
doctest
.
ELLIPSIS
)
src/ZPublisher/tests/testHTTPRangeSupport.py
View file @
efe61189
...
@@ -16,17 +16,19 @@ from ZPublisher.HTTPRangeSupport import parseRange, expandRanges
...
@@ -16,17 +16,19 @@ from ZPublisher.HTTPRangeSupport import parseRange, expandRanges
import
unittest
import
unittest
class
TestRangeHeaderParse
(
unittest
.
TestCase
):
class
TestRangeHeaderParse
(
unittest
.
TestCase
):
# Utility methods
# Utility methods
def
expectNone
(
self
,
header
):
def
expectNone
(
self
,
header
):
result
=
parseRange
(
header
)
result
=
parseRange
(
header
)
self
.
assertTrue
(
result
is
None
,
'Expected None, got %
s'
%
`result`
)
self
.
assertTrue
(
result
is
None
,
'Expected None, got %
r'
%
result
)
def
expectSets
(
self
,
header
,
sets
):
def
expectSets
(
self
,
header
,
sets
):
result
=
parseRange
(
header
)
result
=
parseRange
(
header
)
self
.
assertTrue
(
result
==
sets
,
self
.
assertTrue
(
'Expected %s, got %s'
%
(
`sets`
,
`result`
))
result
==
sets
,
'Expected %r, got %r'
%
(
sets
,
result
))
# Syntactically incorrect headers
# Syntactically incorrect headers
def
testGarbage
(
self
):
def
testGarbage
(
self
):
...
@@ -67,7 +69,8 @@ class TestRangeHeaderParse(unittest.TestCase):
...
@@ -67,7 +69,8 @@ class TestRangeHeaderParse(unittest.TestCase):
self
.
expectSets
(
'bytes=100-100'
,
[(
100
,
101
)])
self
.
expectSets
(
'bytes=100-100'
,
[(
100
,
101
)])
def
testMultiple
(
self
):
def
testMultiple
(
self
):
self
.
expectSets
(
'bytes=-100,,1-2,20-'
,
self
.
expectSets
(
'bytes=-100,,1-2,20-'
,
[(
-
100
,
None
),
(
1
,
3
),
(
20
,
None
)])
[(
-
100
,
None
),
(
1
,
3
),
(
20
,
None
)])
def
testFirstByte
(
self
):
def
testFirstByte
(
self
):
...
@@ -81,8 +84,9 @@ class TestExpandRanges(unittest.TestCase):
...
@@ -81,8 +84,9 @@ class TestExpandRanges(unittest.TestCase):
def
expectSets
(
self
,
sets
,
size
,
expect
):
def
expectSets
(
self
,
sets
,
size
,
expect
):
result
=
expandRanges
(
sets
,
size
)
result
=
expandRanges
(
sets
,
size
)
self
.
assertTrue
(
result
==
expect
,
self
.
assertTrue
(
'Expected %s, got %s'
%
(
`expect`
,
`result`
))
result
==
expect
,
'Expected %r, got %r'
%
(
expect
,
result
))
def
testExpandOpenEnd
(
self
):
def
testExpandOpenEnd
(
self
):
self
.
expectSets
([(
1
,
2
),
(
5
,
None
)],
50
,
[(
1
,
2
),
(
5
,
50
)])
self
.
expectSets
([(
1
,
2
),
(
5
,
None
)],
50
,
[(
1
,
2
),
(
5
,
50
)])
...
@@ -91,23 +95,28 @@ class TestExpandRanges(unittest.TestCase):
...
@@ -91,23 +95,28 @@ class TestExpandRanges(unittest.TestCase):
self
.
expectSets
([(
1
,
2
),
(
-
5
,
None
)],
50
,
[(
1
,
2
),
(
45
,
50
)])
self
.
expectSets
([(
1
,
2
),
(
-
5
,
None
)],
50
,
[(
1
,
2
),
(
45
,
50
)])
def
testNoOverlapInOrder
(
self
):
def
testNoOverlapInOrder
(
self
):
self
.
expectSets
([(
1
,
5
),
(
1000
,
2000
),
(
3000
,
None
)],
5000
,
self
.
expectSets
(
[(
1
,
5
),
(
1000
,
2000
),
(
3000
,
None
)],
5000
,
[(
1
,
5
),
(
1000
,
2000
),
(
3000
,
5000
)])
[(
1
,
5
),
(
1000
,
2000
),
(
3000
,
5000
)])
def
testNoOverlapOutOfOrder
(
self
):
def
testNoOverlapOutOfOrder
(
self
):
self
.
expectSets
([(
1000
,
2000
),
(
3000
,
None
),
(
1
,
5
)],
5000
,
self
.
expectSets
(
[(
1000
,
2000
),
(
3000
,
None
),
(
1
,
5
)],
5000
,
[(
1000
,
2000
),
(
3000
,
5000
),
(
1
,
5
)])
[(
1000
,
2000
),
(
3000
,
5000
),
(
1
,
5
)])
def
testOverlapInOrder
(
self
):
def
testOverlapInOrder
(
self
):
self
.
expectSets
([(
1
,
10
),
(
8
,
20
),
(
25
,
None
)],
5000
,
self
.
expectSets
(
[(
1
,
10
),
(
8
,
20
),
(
25
,
None
)],
5000
,
[(
1
,
10
),
(
8
,
20
),
(
25
,
5000
)])
[(
1
,
10
),
(
8
,
20
),
(
25
,
5000
)])
def
testOverlapOutOfOrder
(
self
):
def
testOverlapOutOfOrder
(
self
):
self
.
expectSets
([(
25
,
50
),
(
8
,
None
),
(
1
,
10
)],
5000
,
self
.
expectSets
(
[(
25
,
50
),
(
8
,
None
),
(
1
,
10
)],
5000
,
[(
25
,
50
),
(
8
,
5000
),
(
1
,
10
)])
[(
25
,
50
),
(
8
,
5000
),
(
1
,
10
)])
def
testAdjacentInOrder
(
self
):
def
testAdjacentInOrder
(
self
):
self
.
expectSets
([(
1
,
10
),
(
10
,
20
),
(
25
,
50
)],
5000
,
self
.
expectSets
(
[(
1
,
10
),
(
10
,
20
),
(
25
,
50
)],
5000
,
[(
1
,
10
),
(
10
,
20
),
(
25
,
50
)])
[(
1
,
10
),
(
10
,
20
),
(
25
,
50
)])
def
testAdjacentOutOfOrder
(
self
):
def
testAdjacentOutOfOrder
(
self
):
...
@@ -119,20 +128,3 @@ class TestExpandRanges(unittest.TestCase):
...
@@ -119,20 +128,3 @@ class TestExpandRanges(unittest.TestCase):
def
testRemoveUnsatisfiable
(
self
):
def
testRemoveUnsatisfiable
(
self
):
self
.
expectSets
([(
sys
.
maxint
,
None
),
(
10
,
20
)],
50
,
[(
10
,
20
)])
self
.
expectSets
([(
sys
.
maxint
,
None
),
(
10
,
20
)],
50
,
[(
10
,
20
)])
def
test_suite
():
suite
=
unittest
.
TestSuite
()
suite
.
addTest
(
unittest
.
makeSuite
(
TestRangeHeaderParse
,
'test'
))
suite
.
addTest
(
unittest
.
makeSuite
(
TestExpandRanges
,
'test'
))
return
suite
def
main
():
unittest
.
TextTestRunner
().
run
(
test_suite
())
def
debug
():
test_suite
().
debug
()
def
pdebug
():
import
pdb
pdb
.
run
(
'debug()'
)
src/ZPublisher/tests/testHTTPRequest.py
View file @
efe61189
import
unittest
import
unittest
from
ZPublisher.tests.testBaseRequest
import
TestRequest
Zope3
ViewsBase
from
ZPublisher.tests.testBaseRequest
import
TestRequestViewsBase
from
zope.testing.cleanup
import
cleanUp
from
zope.testing.cleanup
import
cleanUp
...
@@ -54,8 +54,8 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
...
@@ -54,8 +54,8 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
def
_processInputs
(
self
,
inputs
):
def
_processInputs
(
self
,
inputs
):
from
urllib
import
quote_plus
from
urllib
import
quote_plus
# Have the inputs processed, and return a HTTPRequest object
holding the
# Have the inputs processed, and return a HTTPRequest object
# result.
#
holding the
result.
# inputs is expected to be a list of (key, value) tuples, no CGI
# inputs is expected to be a list of (key, value) tuples, no CGI
# encoding is required.
# encoding is required.
...
@@ -86,55 +86,66 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
...
@@ -86,55 +86,66 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
retval
=
0
retval
=
0
if
isinstance
(
val
,
TaintedString
):
if
isinstance
(
val
,
TaintedString
):
self
.
assertFalse
(
not
'<'
in
val
,
self
.
assertFalse
(
'<'
not
in
val
,
"%r is not dangerous, no taint required."
%
val
)
"%r is not dangerous, no taint required."
%
val
)
retval
=
1
retval
=
1
elif
isinstance
(
val
,
record
):
elif
isinstance
(
val
,
record
):
for
attr
,
value
in
val
.
__dict__
.
items
():
for
attr
,
value
in
val
.
__dict__
.
items
():
rval
=
self
.
_valueIsOrHoldsTainted
(
attr
)
rval
=
self
.
_valueIsOrHoldsTainted
(
attr
)
if
rval
:
retval
=
1
if
rval
:
retval
=
1
rval
=
self
.
_valueIsOrHoldsTainted
(
value
)
rval
=
self
.
_valueIsOrHoldsTainted
(
value
)
if
rval
:
retval
=
1
if
rval
:
retval
=
1
elif
type
(
val
)
in
(
list
,
tuple
):
elif
type
(
val
)
in
(
list
,
tuple
):
for
entry
in
val
:
for
entry
in
val
:
rval
=
self
.
_valueIsOrHoldsTainted
(
entry
)
rval
=
self
.
_valueIsOrHoldsTainted
(
entry
)
if
rval
:
retval
=
1
if
rval
:
retval
=
1
elif
type
(
val
)
in
(
str
,
unicode
):
elif
type
(
val
)
in
(
str
,
unicode
):
self
.
assertFalse
(
'<'
in
val
,
self
.
assertFalse
(
'<'
in
val
,
"'%s' is dangerous and should have been tainted."
%
val
)
"'%s' is dangerous and should have been tainted."
%
val
)
return
retval
return
retval
def
_noFormValuesInOther
(
self
,
req
):
def
_noFormValuesInOther
(
self
,
req
):
for
key
in
req
.
taintedform
.
keys
():
for
key
in
req
.
taintedform
.
keys
():
self
.
assertFalse
(
req
.
other
.
has_key
(
key
),
self
.
assertFalse
(
key
in
req
.
other
,
'REQUEST.other should not hold tainted values at first!'
)
'REQUEST.other should not hold tainted values at first!'
)
for
key
in
req
.
form
.
keys
():
for
key
in
req
.
form
.
keys
():
self
.
assertFalse
(
req
.
other
.
has_key
(
key
),
self
.
assertFalse
(
key
in
req
.
other
,
'REQUEST.other should not hold form values at first!'
)
'REQUEST.other should not hold form values at first!'
)
def
_onlyTaintedformHoldsTaintedStrings
(
self
,
req
):
def
_onlyTaintedformHoldsTaintedStrings
(
self
,
req
):
for
key
,
val
in
req
.
taintedform
.
items
():
for
key
,
val
in
req
.
taintedform
.
items
():
self
.
assert_
(
self
.
_valueIsOrHoldsTainted
(
key
)
or
self
.
assert_
(
self
.
_valueIsOrHoldsTainted
(
key
)
or
self
.
_valueIsOrHoldsTainted
(
val
),
self
.
_valueIsOrHoldsTainted
(
val
),
'Tainted form holds item %s that is not tainted'
%
key
)
'Tainted form holds item %s that is not tainted'
%
key
)
for
key
,
val
in
req
.
form
.
items
():
for
key
,
val
in
req
.
form
.
items
():
if
req
.
taintedform
.
has_key
(
key
)
:
if
key
in
req
.
taintedform
:
continue
continue
self
.
assertFalse
(
self
.
_valueIsOrHoldsTainted
(
key
)
or
self
.
assertFalse
(
self
.
_valueIsOrHoldsTainted
(
key
)
or
self
.
_valueIsOrHoldsTainted
(
val
),
self
.
_valueIsOrHoldsTainted
(
val
),
'Normal form holds item %s that is tainted'
%
key
)
'Normal form holds item %s that is tainted'
%
key
)
def
_taintedKeysAlsoInForm
(
self
,
req
):
def
_taintedKeysAlsoInForm
(
self
,
req
):
for
key
in
req
.
taintedform
.
keys
():
for
key
in
req
.
taintedform
.
keys
():
self
.
assert_
(
req
.
form
.
has_key
(
key
),
self
.
assert_
(
key
in
req
.
form
,
"Found tainted %s not in form"
%
key
)
"Found tainted %s not in form"
%
key
)
self
.
assertEquals
(
req
.
form
[
key
],
req
.
taintedform
[
key
],
self
.
assertEqual
(
req
.
form
[
key
],
req
.
taintedform
[
key
],
"Key %s not correctly reproduced in tainted; expected %r, "
"Key %s not correctly reproduced in tainted; expected %r, "
"got %r"
%
(
key
,
req
.
form
[
key
],
req
.
taintedform
[
key
]))
"got %r"
%
(
key
,
req
.
form
[
key
],
req
.
taintedform
[
key
]))
...
@@ -156,7 +167,7 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
...
@@ -156,7 +167,7 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
req
=
self
.
_makeOne
(
environ
=
env
)
req
=
self
.
_makeOne
(
environ
=
env
)
req
.
processInputs
()
req
.
processInputs
()
self
.
_noFormValuesInOther
(
req
)
self
.
_noFormValuesInOther
(
req
)
self
.
assertEqual
s
(
req
.
form
,
{})
self
.
assertEqual
(
req
.
form
,
{})
def
test_processInputs_wo_marshalling
(
self
):
def
test_processInputs_wo_marshalling
(
self
):
inputs
=
(
inputs
=
(
...
@@ -168,12 +179,13 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
...
@@ -168,12 +179,13 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
formkeys
=
list
(
req
.
form
.
keys
())
formkeys
=
list
(
req
.
form
.
keys
())
formkeys
.
sort
()
formkeys
.
sort
()
self
.
assertEquals
(
formkeys
,
[
'foo'
,
'key'
,
'multi'
,
'number'
,
self
.
assertEqual
(
'spacey key'
,
'spam'
])
formkeys
,
self
.
assertEquals
(
req
[
'number'
],
'1'
)
[
'foo'
,
'key'
,
'multi'
,
'number'
,
'spacey key'
,
'spam'
])
self
.
assertEquals
(
req
[
'multi'
],
[
'1'
,
'2'
])
self
.
assertEqual
(
req
[
'number'
],
'1'
)
self
.
assertEquals
(
req
[
'spacey key'
],
'val'
)
self
.
assertEqual
(
req
[
'multi'
],
[
'1'
,
'2'
])
self
.
assertEquals
(
req
[
'key'
],
'spacey val'
)
self
.
assertEqual
(
req
[
'spacey key'
],
'val'
)
self
.
assertEqual
(
req
[
'key'
],
'spacey val'
)
self
.
_noTaintedValues
(
req
)
self
.
_noTaintedValues
(
req
)
self
.
_onlyTaintedformHoldsTaintedStrings
(
req
)
self
.
_onlyTaintedformHoldsTaintedStrings
(
req
)
...
@@ -191,18 +203,20 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
...
@@ -191,18 +203,20 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
formkeys
=
list
(
req
.
form
.
keys
())
formkeys
=
list
(
req
.
form
.
keys
())
formkeys
.
sort
()
formkeys
.
sort
()
self
.
assertEquals
(
formkeys
,
[
'2tokens'
,
'accountedfor'
,
'aday'
,
'bign'
,
self
.
assertEqual
(
formkeys
,
[
'2tokens'
,
'accountedfor'
,
'aday'
,
'bign'
,
'fract'
,
'morewords'
,
'multiline'
,
'num'
,
'words'
])
'fract'
,
'morewords'
,
'multiline'
,
'num'
,
'words'
])
self
.
assertEqual
s
(
req
[
'2tokens'
],
[
'one'
,
'two'
])
self
.
assertEqual
(
req
[
'2tokens'
],
[
'one'
,
'two'
])
self
.
assertEqual
s
(
req
[
'accountedfor'
],
'yes'
)
self
.
assertEqual
(
req
[
'accountedfor'
],
'yes'
)
self
.
assertEqual
s
(
req
[
'aday'
],
DateTime
(
'2002/07/23'
))
self
.
assertEqual
(
req
[
'aday'
],
DateTime
(
'2002/07/23'
))
self
.
assertEqual
s
(
req
[
'bign'
],
45L
)
self
.
assertEqual
(
req
[
'bign'
],
45
)
self
.
assertEqual
s
(
req
[
'fract'
],
4.2
)
self
.
assertEqual
(
req
[
'fract'
],
4.2
)
self
.
assertEqual
s
(
req
[
'morewords'
],
'one
\
n
two
\
n
'
)
self
.
assertEqual
(
req
[
'morewords'
],
'one
\
n
two
\
n
'
)
self
.
assertEqual
s
(
req
[
'multiline'
],
[
'one'
,
'two'
])
self
.
assertEqual
(
req
[
'multiline'
],
[
'one'
,
'two'
])
self
.
assertEqual
s
(
req
[
'num'
],
42
)
self
.
assertEqual
(
req
[
'num'
],
42
)
self
.
assertEqual
s
(
req
[
'words'
],
'Some words'
)
self
.
assertEqual
(
req
[
'words'
],
'Some words'
)
self
.
_noTaintedValues
(
req
)
self
.
_noTaintedValues
(
req
)
self
.
_onlyTaintedformHoldsTaintedStrings
(
req
)
self
.
_onlyTaintedformHoldsTaintedStrings
(
req
)
...
@@ -217,16 +231,17 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
...
@@ -217,16 +231,17 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
formkeys
=
list
(
req
.
form
.
keys
())
formkeys
=
list
(
req
.
form
.
keys
())
formkeys
.
sort
()
formkeys
.
sort
()
self
.
assertEquals
(
formkeys
,
[
'nouconverter'
,
'ulines'
,
'ustring'
,
self
.
assertEqual
(
'utext'
,
'utokens'
])
formkeys
,
[
'nouconverter'
,
'ulines'
,
'ustring'
,
'utext'
,
'utokens'
])
self
.
assertEqual
s
(
req
[
'ustring'
],
u'test
\
u00AE
'
)
self
.
assertEqual
(
req
[
'ustring'
],
u'test
\
u00AE
'
)
self
.
assertEqual
s
(
req
[
'utext'
],
u'test
\
u00AE
\
n
test
\
u00AE
\
n
'
)
self
.
assertEqual
(
req
[
'utext'
],
u'test
\
u00AE
\
n
test
\
u00AE
\
n
'
)
self
.
assertEqual
s
(
req
[
'utokens'
],
[
u'test
\
u00AE
'
,
u'test
\
u00AE
'
])
self
.
assertEqual
(
req
[
'utokens'
],
[
u'test
\
u00AE
'
,
u'test
\
u00AE
'
])
self
.
assertEqual
s
(
req
[
'ulines'
],
[
u'test
\
u00AE
'
,
u'test
\
u00AE
'
])
self
.
assertEqual
(
req
[
'ulines'
],
[
u'test
\
u00AE
'
,
u'test
\
u00AE
'
])
# expect a utf-8 encoded version
# expect a utf-8 encoded version
self
.
assertEqual
s
(
req
[
'nouconverter'
],
'test
\
xc2
\
xae
'
)
self
.
assertEqual
(
req
[
'nouconverter'
],
'test
\
xc2
\
xae
'
)
self
.
_noTaintedValues
(
req
)
self
.
_noTaintedValues
(
req
)
self
.
_onlyTaintedformHoldsTaintedStrings
(
req
)
self
.
_onlyTaintedformHoldsTaintedStrings
(
req
)
...
@@ -244,20 +259,21 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
...
@@ -244,20 +259,21 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
formkeys
=
list
(
req
.
form
.
keys
())
formkeys
=
list
(
req
.
form
.
keys
())
formkeys
.
sort
()
formkeys
.
sort
()
self
.
assertEquals
(
formkeys
,
[
'alist'
,
'atuple'
,
'oneitem'
,
self
.
assertEqual
(
'oneitemtuple'
,
'onerec'
,
'setrec'
])
formkeys
,
[
'alist'
,
'atuple'
,
'oneitem'
,
'oneitemtuple'
,
'onerec'
,
'setrec'
])
self
.
assertEquals
(
req
[
'oneitem'
],
[
'one'
])
self
.
assertEquals
(
req
[
'oneitemtuple'
],
(
'one'
,))
self
.
assertEqual
(
req
[
'oneitem'
],
[
'one'
])
self
.
assertEquals
(
req
[
'alist'
],
[
'one'
,
'two'
])
self
.
assertEqual
(
req
[
'oneitemtuple'
],
(
'one'
,))
self
.
assertEquals
(
req
[
'atuple'
],
(
'one'
,
'two'
))
self
.
assertEqual
(
req
[
'alist'
],
[
'one'
,
'two'
])
self
.
assertEquals
(
req
[
'onerec'
].
foo
,
'foo'
)
self
.
assertEqual
(
req
[
'atuple'
],
(
'one'
,
'two'
))
self
.
assertEquals
(
req
[
'onerec'
].
bar
,
'bar'
)
self
.
assertEqual
(
req
[
'onerec'
].
foo
,
'foo'
)
self
.
assertEquals
(
len
(
req
[
'setrec'
]),
2
)
self
.
assertEqual
(
req
[
'onerec'
].
bar
,
'bar'
)
self
.
assertEquals
(
req
[
'setrec'
][
0
].
foo
,
'foo'
)
self
.
assertEqual
(
len
(
req
[
'setrec'
]),
2
)
self
.
assertEquals
(
req
[
'setrec'
][
0
].
bar
,
'bar'
)
self
.
assertEqual
(
req
[
'setrec'
][
0
].
foo
,
'foo'
)
self
.
assertEquals
(
req
[
'setrec'
][
1
].
foo
,
'spam'
)
self
.
assertEqual
(
req
[
'setrec'
][
0
].
bar
,
'bar'
)
self
.
assertEquals
(
req
[
'setrec'
][
1
].
bar
,
'eggs'
)
self
.
assertEqual
(
req
[
'setrec'
][
1
].
foo
,
'spam'
)
self
.
assertEqual
(
req
[
'setrec'
][
1
].
bar
,
'eggs'
)
self
.
_noTaintedValues
(
req
)
self
.
_noTaintedValues
(
req
)
self
.
_onlyTaintedformHoldsTaintedStrings
(
req
)
self
.
_onlyTaintedformHoldsTaintedStrings
(
req
)
...
@@ -273,11 +289,11 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
...
@@ -273,11 +289,11 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
formkeys
=
list
(
req
.
form
.
keys
())
formkeys
=
list
(
req
.
form
.
keys
())
formkeys
.
sort
()
formkeys
.
sort
()
self
.
assertEqual
s
(
formkeys
,
[
'ftuple'
,
'ilist'
,
'tlist'
])
self
.
assertEqual
(
formkeys
,
[
'ftuple'
,
'ilist'
,
'tlist'
])
self
.
assertEqual
s
(
req
[
'ilist'
],
[
1
,
2
,
3
])
self
.
assertEqual
(
req
[
'ilist'
],
[
1
,
2
,
3
])
self
.
assertEqual
s
(
req
[
'ftuple'
],
(
1.0
,
1.1
,
1.2
))
self
.
assertEqual
(
req
[
'ftuple'
],
(
1.0
,
1.1
,
1.2
))
self
.
assertEqual
s
(
req
[
'tlist'
],
[[
'one'
,
'two'
],
[
'3'
,
'4'
]])
self
.
assertEqual
(
req
[
'tlist'
],
[[
'one'
,
'two'
],
[
'3'
,
'4'
]])
self
.
_noTaintedValues
(
req
)
self
.
_noTaintedValues
(
req
)
self
.
_onlyTaintedformHoldsTaintedStrings
(
req
)
self
.
_onlyTaintedformHoldsTaintedStrings
(
req
)
...
@@ -303,20 +319,20 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
...
@@ -303,20 +319,20 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
formkeys
=
list
(
req
.
form
.
keys
())
formkeys
=
list
(
req
.
form
.
keys
())
formkeys
.
sort
()
formkeys
.
sort
()
self
.
assertEqual
s
(
formkeys
,
[
'onerec'
,
'setrec'
])
self
.
assertEqual
(
formkeys
,
[
'onerec'
,
'setrec'
])
self
.
assertEqual
s
(
req
[
'onerec'
].
name
,
'foo'
)
self
.
assertEqual
(
req
[
'onerec'
].
name
,
'foo'
)
self
.
assertEqual
s
(
req
[
'onerec'
].
tokens
,
[
'one'
,
'two'
])
self
.
assertEqual
(
req
[
'onerec'
].
tokens
,
[
'one'
,
'two'
])
# Implicit sequences and records don't mix.
# Implicit sequences and records don't mix.
self
.
assertEqual
s
(
req
[
'onerec'
].
ints
,
2
)
self
.
assertEqual
(
req
[
'onerec'
].
ints
,
2
)
self
.
assertEqual
s
(
len
(
req
[
'setrec'
]),
2
)
self
.
assertEqual
(
len
(
req
[
'setrec'
]),
2
)
self
.
assertEqual
s
(
req
[
'setrec'
][
0
].
name
,
'first'
)
self
.
assertEqual
(
req
[
'setrec'
][
0
].
name
,
'first'
)
self
.
assertEqual
s
(
req
[
'setrec'
][
1
].
name
,
'second'
)
self
.
assertEqual
(
req
[
'setrec'
][
1
].
name
,
'second'
)
for
i
in
range
(
2
):
for
i
in
range
(
2
):
self
.
assertEqual
s
(
req
[
'setrec'
][
i
].
ilist
,
[
1
,
2
])
self
.
assertEqual
(
req
[
'setrec'
][
i
].
ilist
,
[
1
,
2
])
self
.
assertEqual
s
(
req
[
'setrec'
][
i
].
ituple
,
(
1
,
2
))
self
.
assertEqual
(
req
[
'setrec'
][
i
].
ituple
,
(
1
,
2
))
self
.
_noTaintedValues
(
req
)
self
.
_noTaintedValues
(
req
)
self
.
_onlyTaintedformHoldsTaintedStrings
(
req
)
self
.
_onlyTaintedformHoldsTaintedStrings
(
req
)
...
@@ -350,21 +366,21 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
...
@@ -350,21 +366,21 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
formkeys
=
list
(
req
.
form
.
keys
())
formkeys
=
list
(
req
.
form
.
keys
())
formkeys
.
sort
()
formkeys
.
sort
()
self
.
assertEqual
s
(
formkeys
,
[
'alist'
,
'bar'
,
'explicitlist'
,
'foo'
,
self
.
assertEqual
(
'setrec'
])
formkeys
,
[
'alist'
,
'bar'
,
'explicitlist'
,
'foo'
,
'setrec'
])
self
.
assertEqual
s
(
req
[
'alist'
],
[
1
,
2
,
3
,
4
,
5
])
self
.
assertEqual
(
req
[
'alist'
],
[
1
,
2
,
3
,
4
,
5
])
self
.
assertEqual
s
(
req
[
'explicitlist'
],
[
1
,
2
,
3
,
4
,
5
])
self
.
assertEqual
(
req
[
'explicitlist'
],
[
1
,
2
,
3
,
4
,
5
])
self
.
assertEqual
s
(
req
[
'foo'
],
5
)
self
.
assertEqual
(
req
[
'foo'
],
5
)
self
.
assertEqual
s
(
req
[
'bar'
].
spam
,
'eggs'
)
self
.
assertEqual
(
req
[
'bar'
].
spam
,
'eggs'
)
self
.
assertEqual
s
(
req
[
'bar'
].
foo
,
'baz'
)
self
.
assertEqual
(
req
[
'bar'
].
foo
,
'baz'
)
self
.
assertEqual
s
(
len
(
req
[
'setrec'
]),
2
)
self
.
assertEqual
(
len
(
req
[
'setrec'
]),
2
)
self
.
assertEqual
s
(
req
[
'setrec'
][
0
].
spam
,
'eggs'
)
self
.
assertEqual
(
req
[
'setrec'
][
0
].
spam
,
'eggs'
)
self
.
assertEqual
s
(
req
[
'setrec'
][
0
].
foo
,
'baz'
)
self
.
assertEqual
(
req
[
'setrec'
][
0
].
foo
,
'baz'
)
self
.
assertEqual
s
(
req
[
'setrec'
][
1
].
spam
,
'eggs'
)
self
.
assertEqual
(
req
[
'setrec'
][
1
].
spam
,
'eggs'
)
self
.
assertEqual
s
(
req
[
'setrec'
][
1
].
foo
,
'ham'
)
self
.
assertEqual
(
req
[
'setrec'
][
1
].
foo
,
'ham'
)
self
.
_noTaintedValues
(
req
)
self
.
_noTaintedValues
(
req
)
self
.
_onlyTaintedformHoldsTaintedStrings
(
req
)
self
.
_onlyTaintedformHoldsTaintedStrings
(
req
)
...
@@ -383,7 +399,9 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
...
@@ -383,7 +399,9 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
taintedformkeys
=
list
(
req
.
taintedform
.
keys
())
taintedformkeys
=
list
(
req
.
taintedform
.
keys
())
taintedformkeys
.
sort
()
taintedformkeys
.
sort
()
self
.
assertEquals
(
taintedformkeys
,
[
'<tainted key>'
,
'tainted'
,
self
.
assertEqual
(
taintedformkeys
,
[
'<tainted key>'
,
'tainted'
,
'tallmulti'
,
'tdefermulti'
,
'tinitmulti'
])
'tallmulti'
,
'tdefermulti'
,
'tinitmulti'
])
self
.
_taintedKeysAlsoInForm
(
req
)
self
.
_taintedKeysAlsoInForm
(
req
)
...
@@ -393,7 +411,8 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
...
@@ -393,7 +411,8 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
inputs
=
(
inputs
=
(
(
'<tnum>:int'
,
'42'
),
(
'<tfract>:float'
,
'4.2'
),
(
'<tnum>:int'
,
'42'
),
(
'<tfract>:float'
,
'4.2'
),
(
'<tbign>:long'
,
'45'
),
(
'<tbign>:long'
,
'45'
),
(
'twords:string'
,
'Some <words>'
),
(
't2tokens:tokens'
,
'one <two>'
),
(
'twords:string'
,
'Some <words>'
),
(
't2tokens:tokens'
,
'one <two>'
),
(
'<taday>:date'
,
'2002/07/23'
),
(
'<taday>:date'
,
'2002/07/23'
),
(
'taccountedfor:required'
,
'<yes>'
),
(
'taccountedfor:required'
,
'<yes>'
),
(
'tmultiline:lines'
,
'<one
\
n
two>'
),
(
'tmultiline:lines'
,
'<one
\
n
two>'
),
...
@@ -402,7 +421,9 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
...
@@ -402,7 +421,9 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
taintedformkeys
=
list
(
req
.
taintedform
.
keys
())
taintedformkeys
=
list
(
req
.
taintedform
.
keys
())
taintedformkeys
.
sort
()
taintedformkeys
.
sort
()
self
.
assertEquals
(
taintedformkeys
,
[
'<taday>'
,
'<tbign>'
,
'<tfract>'
,
self
.
assertEqual
(
taintedformkeys
,
[
'<taday>'
,
'<tbign>'
,
'<tfract>'
,
'<tnum>'
,
't2tokens'
,
'taccountedfor'
,
'tmorewords'
,
'tmultiline'
,
'<tnum>'
,
't2tokens'
,
'taccountedfor'
,
'tmorewords'
,
'tmultiline'
,
'twords'
])
'twords'
])
...
@@ -410,7 +431,8 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
...
@@ -410,7 +431,8 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
self
.
_onlyTaintedformHoldsTaintedStrings
(
req
)
self
.
_onlyTaintedformHoldsTaintedStrings
(
req
)
def
test_processInputs_w_unicode_w_taints
(
self
):
def
test_processInputs_w_unicode_w_taints
(
self
):
inputs
=
((
'tustring:ustring:utf8'
,
'<test
\
xc2
\
xae
>'
),
inputs
=
(
(
'tustring:ustring:utf8'
,
'<test
\
xc2
\
xae
>'
),
(
'tutext:utext:utf8'
,
'<test
\
xc2
\
xae
>
\
n
<test
\
xc2
\
xae
\
n
>'
),
(
'tutext:utext:utf8'
,
'<test
\
xc2
\
xae
>
\
n
<test
\
xc2
\
xae
\
n
>'
),
(
'tinitutokens:utokens:utf8'
,
'<test
\
xc2
\
xae
> test
\
xc2
\
xae
'
),
(
'tinitutokens:utokens:utf8'
,
'<test
\
xc2
\
xae
> test
\
xc2
\
xae
'
),
...
@@ -419,12 +441,15 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
...
@@ -419,12 +441,15 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
(
'tdeferutokens:utokens:utf8'
,
'test
\
xc2
\
xae
<test
\
xc2
\
xae
>'
),
(
'tdeferutokens:utokens:utf8'
,
'test
\
xc2
\
xae
<test
\
xc2
\
xae
>'
),
(
'tdeferulines:ulines:utf8'
,
'test
\
xc2
\
xae
\
n
<test
\
xc2
\
xae
>'
),
(
'tdeferulines:ulines:utf8'
,
'test
\
xc2
\
xae
\
n
<test
\
xc2
\
xae
>'
),
(
'tnouconverter:string:utf8'
,
'<test
\
xc2
\
xae
>'
))
(
'tnouconverter:string:utf8'
,
'<test
\
xc2
\
xae
>'
),
)
req
=
self
.
_processInputs
(
inputs
)
req
=
self
.
_processInputs
(
inputs
)
taintedformkeys
=
list
(
req
.
taintedform
.
keys
())
taintedformkeys
=
list
(
req
.
taintedform
.
keys
())
taintedformkeys
.
sort
()
taintedformkeys
.
sort
()
self
.
assertEquals
(
taintedformkeys
,
[
'tdeferulines'
,
'tdeferutokens'
,
self
.
assertEqual
(
taintedformkeys
,
[
'tdeferulines'
,
'tdeferutokens'
,
'tinitulines'
,
'tinitutokens'
,
'tnouconverter'
,
'tustring'
,
'tinitulines'
,
'tinitutokens'
,
'tnouconverter'
,
'tustring'
,
'tutext'
])
'tutext'
])
...
@@ -470,7 +495,9 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
...
@@ -470,7 +495,9 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
taintedformkeys
=
list
(
req
.
taintedform
.
keys
())
taintedformkeys
=
list
(
req
.
taintedform
.
keys
())
taintedformkeys
.
sort
()
taintedformkeys
.
sort
()
self
.
assertEquals
(
taintedformkeys
,
[
'<tkeyoneitem>'
,
'tdeferalist'
,
self
.
assertEqual
(
taintedformkeys
,
[
'<tkeyoneitem>'
,
'tdeferalist'
,
'tdeferatuple'
,
'tdeferdefersetrec'
,
'tdeferinitsetrec'
,
'tdeferatuple'
,
'tdeferdefersetrec'
,
'tdeferinitsetrec'
,
'tdeferonerec'
,
'tinitalist'
,
'tinitatuple'
,
'tinitdefersetrec'
,
'tdeferonerec'
,
'tinitalist'
,
'tinitatuple'
,
'tinitdefersetrec'
,
'tinitinitsetrec'
,
'tinitonerec'
,
'toneitem'
,
'toneitemtuple'
])
'tinitinitsetrec'
,
'tinitonerec'
,
'toneitem'
,
'toneitemtuple'
])
...
@@ -520,7 +547,9 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
...
@@ -520,7 +547,9 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
taintedformkeys
=
list
(
req
.
taintedform
.
keys
())
taintedformkeys
=
list
(
req
.
taintedform
.
keys
())
taintedformkeys
.
sort
()
taintedformkeys
.
sort
()
self
.
assertEquals
(
taintedformkeys
,
[
'tdeferfirstsetrec'
,
'tdeferonerec'
,
self
.
assertEqual
(
taintedformkeys
,
[
'tdeferfirstsetrec'
,
'tdeferonerec'
,
'tdefersecondsetrec'
,
'tinitonerec'
,
'tinitsetrec'
])
'tdefersecondsetrec'
,
'tinitonerec'
,
'tinitsetrec'
])
self
.
_taintedKeysAlsoInForm
(
req
)
self
.
_taintedKeysAlsoInForm
(
req
)
...
@@ -572,7 +601,9 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
...
@@ -572,7 +601,9 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
taintedformkeys
=
list
(
req
.
taintedform
.
keys
())
taintedformkeys
=
list
(
req
.
taintedform
.
keys
())
taintedformkeys
.
sort
()
taintedformkeys
.
sort
()
self
.
assertEquals
(
taintedformkeys
,
[
'tdeferbar'
,
'tdeferlist'
,
self
.
assertEqual
(
taintedformkeys
,
[
'tdeferbar'
,
'tdeferlist'
,
'tdefersetrec'
,
'tfoo'
,
'tinitbar'
,
'tinitlist'
,
'tinitsetrec'
])
'tdefersetrec'
,
'tfoo'
,
'tinitbar'
,
'tinitlist'
,
'tinitsetrec'
])
self
.
_taintedKeysAlsoInForm
(
req
)
self
.
_taintedKeysAlsoInForm
(
req
)
...
@@ -592,10 +623,12 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
...
@@ -592,10 +623,12 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
try
:
try
:
convert
(
'<html garbage>'
)
convert
(
'<html garbage>'
)
except
Exception
as
e
:
except
Exception
as
e
:
self
.
assertFalse
(
'<'
in
e
.
args
,
self
.
assertFalse
(
'<'
in
e
.
args
,
'%s converter does not quote unsafe value!'
%
type
)
'%s converter does not quote unsafe value!'
%
type
)
except
SyntaxError
as
e
:
except
SyntaxError
as
e
:
self
.
assertFalse
(
'<'
in
e
,
self
.
assertFalse
(
'<'
in
e
,
'%s converter does not quote unsafe value!'
%
type
)
'%s converter does not quote unsafe value!'
%
type
)
def
test_processInputs_w_dotted_name_as_tuple
(
self
):
def
test_processInputs_w_dotted_name_as_tuple
(
self
):
...
@@ -606,9 +639,9 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
...
@@ -606,9 +639,9 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
formkeys
=
list
(
req
.
form
.
keys
())
formkeys
=
list
(
req
.
form
.
keys
())
formkeys
.
sort
()
formkeys
.
sort
()
self
.
assertEqual
s
(
formkeys
,
[
'name.'
])
self
.
assertEqual
(
formkeys
,
[
'name.'
])
self
.
assertEqual
s
(
req
[
'name.'
],
(
'name with dot as tuple'
,))
self
.
assertEqual
(
req
[
'name.'
],
(
'name with dot as tuple'
,))
self
.
_noTaintedValues
(
req
)
self
.
_noTaintedValues
(
req
)
self
.
_onlyTaintedformHoldsTaintedStrings
(
req
)
self
.
_onlyTaintedformHoldsTaintedStrings
(
req
)
...
@@ -618,20 +651,20 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
...
@@ -618,20 +651,20 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
env
[
'HTTP_COOKIE'
]
=
'foo=bar; baz=gee'
env
[
'HTTP_COOKIE'
]
=
'foo=bar; baz=gee'
req
=
self
.
_makeOne
(
environ
=
env
)
req
=
self
.
_makeOne
(
environ
=
env
)
self
.
assertEqual
s
(
req
.
cookies
[
'foo'
],
'bar'
)
self
.
assertEqual
(
req
.
cookies
[
'foo'
],
'bar'
)
self
.
assertEqual
s
(
req
.
cookies
[
'baz'
],
'gee'
)
self
.
assertEqual
(
req
.
cookies
[
'baz'
],
'gee'
)
env
[
'HTTP_COOKIE'
]
=
'foo=bar; baz="gee, like, e=mc^2"'
env
[
'HTTP_COOKIE'
]
=
'foo=bar; baz="gee, like, e=mc^2"'
req
=
self
.
_makeOne
(
environ
=
env
)
req
=
self
.
_makeOne
(
environ
=
env
)
self
.
assertEqual
s
(
req
.
cookies
[
'foo'
],
'bar'
)
self
.
assertEqual
(
req
.
cookies
[
'foo'
],
'bar'
)
self
.
assertEqual
s
(
req
.
cookies
[
'baz'
],
'gee, like, e=mc^2'
)
self
.
assertEqual
(
req
.
cookies
[
'baz'
],
'gee, like, e=mc^2'
)
# Collector #1498: empty cookies
# Collector #1498: empty cookies
env
[
'HTTP_COOKIE'
]
=
'foo=bar; hmm; baz=gee'
env
[
'HTTP_COOKIE'
]
=
'foo=bar; hmm; baz=gee'
req
=
self
.
_makeOne
(
environ
=
env
)
req
=
self
.
_makeOne
(
environ
=
env
)
self
.
assertEqual
s
(
req
.
cookies
[
'foo'
],
'bar'
)
self
.
assertEqual
(
req
.
cookies
[
'foo'
],
'bar'
)
self
.
assertEqual
s
(
req
.
cookies
[
'hmm'
],
''
)
self
.
assertEqual
(
req
.
cookies
[
'hmm'
],
''
)
self
.
assertEqual
s
(
req
.
cookies
[
'baz'
],
'gee'
)
self
.
assertEqual
(
req
.
cookies
[
'baz'
],
'gee'
)
# Unquoted multi-space cookies
# Unquoted multi-space cookies
env
[
'HTTP_COOKIE'
]
=
'single=cookie data; '
\
env
[
'HTTP_COOKIE'
]
=
'single=cookie data; '
\
...
@@ -639,12 +672,12 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
...
@@ -639,12 +672,12 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
'multi=cookie data with unquoted spaces; '
\
'multi=cookie data with unquoted spaces; '
\
'multi2=cookie data with unquoted spaces'
'multi2=cookie data with unquoted spaces'
req
=
self
.
_makeOne
(
environ
=
env
)
req
=
self
.
_makeOne
(
environ
=
env
)
self
.
assertEqual
s
(
req
.
cookies
[
'single'
],
'cookie data'
)
self
.
assertEqual
(
req
.
cookies
[
'single'
],
'cookie data'
)
self
.
assertEqual
s
(
req
.
cookies
[
'quoted'
],
self
.
assertEqual
(
req
.
cookies
[
'quoted'
],
'cookie data with unquoted spaces'
)
'cookie data with unquoted spaces'
)
self
.
assertEqual
s
(
req
.
cookies
[
'multi'
],
self
.
assertEqual
(
req
.
cookies
[
'multi'
],
'cookie data with unquoted spaces'
)
'cookie data with unquoted spaces'
)
self
.
assertEqual
s
(
req
.
cookies
[
'multi2'
],
self
.
assertEqual
(
req
.
cookies
[
'multi2'
],
'cookie data with unquoted spaces'
)
'cookie data with unquoted spaces'
)
def
test_postProcessInputs
(
self
):
def
test_postProcessInputs
(
self
):
...
@@ -707,43 +740,43 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
...
@@ -707,43 +740,43 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
req
=
self
.
_makeOne
(
stdin
=
s
,
environ
=
TEST_ENVIRON
.
copy
())
req
=
self
.
_makeOne
(
stdin
=
s
,
environ
=
TEST_ENVIRON
.
copy
())
req
.
processInputs
()
req
.
processInputs
()
f
=
req
.
form
.
get
(
'file'
)
f
=
req
.
form
.
get
(
'file'
)
self
.
assertEqual
(
list
(
f
),[
'test
\
n
'
])
self
.
assertEqual
(
list
(
f
),
[
'test
\
n
'
])
f
.
seek
(
0
)
f
.
seek
(
0
)
self
.
assertEqual
(
f
.
next
(),
'test
\
n
'
)
self
.
assertEqual
(
f
.
next
(),
'test
\
n
'
)
f
.
seek
(
0
)
f
.
seek
(
0
)
self
.
assertEqual
(
f
.
xreadlines
(),
f
)
self
.
assertEqual
(
f
.
xreadlines
(),
f
)
def
test__authUserPW_simple
(
self
):
def
test__authUserPW_simple
(
self
):
import
base64
import
base64
user_id
=
'user'
user_id
=
'user'
password
=
'password'
password
=
'password'
encoded
=
base64
.
encodestring
(
'%s:%s'
%
(
user_id
,
password
)
)
encoded
=
base64
.
encodestring
(
'%s:%s'
%
(
user_id
,
password
)
)
auth_header
=
'basic %s'
%
encoded
auth_header
=
'basic %s'
%
encoded
environ
=
{
'HTTP_AUTHORIZATION'
:
auth_header
}
environ
=
{
'HTTP_AUTHORIZATION'
:
auth_header
}
request
=
self
.
_makeOne
(
environ
=
environ
)
request
=
self
.
_makeOne
(
environ
=
environ
)
user_id_x
,
password_x
=
request
.
_authUserPW
()
user_id_x
,
password_x
=
request
.
_authUserPW
()
self
.
assertEqual
(
user_id_x
,
user_id
)
self
.
assertEqual
(
user_id_x
,
user_id
)
self
.
assertEqual
(
password_x
,
password
)
self
.
assertEqual
(
password_x
,
password
)
def
test__authUserPW_with_embedded_colon
(
self
):
def
test__authUserPW_with_embedded_colon
(
self
):
# http://www.zope.org/Collectors/Zope/2039
# http://www.zope.org/Collectors/Zope/2039
import
base64
import
base64
user_id
=
'user'
user_id
=
'user'
password
=
'embedded:colon'
password
=
'embedded:colon'
encoded
=
base64
.
encodestring
(
'%s:%s'
%
(
user_id
,
password
)
)
encoded
=
base64
.
encodestring
(
'%s:%s'
%
(
user_id
,
password
)
)
auth_header
=
'basic %s'
%
encoded
auth_header
=
'basic %s'
%
encoded
environ
=
{
'HTTP_AUTHORIZATION'
:
auth_header
}
environ
=
{
'HTTP_AUTHORIZATION'
:
auth_header
}
request
=
self
.
_makeOne
(
environ
=
environ
)
request
=
self
.
_makeOne
(
environ
=
environ
)
user_id_x
,
password_x
=
request
.
_authUserPW
()
user_id_x
,
password_x
=
request
.
_authUserPW
()
self
.
assertEqual
(
user_id_x
,
user_id
)
self
.
assertEqual
(
user_id_x
,
user_id
)
self
.
assertEqual
(
password_x
,
password
)
self
.
assertEqual
(
password_x
,
password
)
def
test_debug_not_in_qs_still_gets_attr
(
self
):
def
test_debug_not_in_qs_still_gets_attr
(
self
):
from
zope.publisher.base
import
DebugFlags
from
zope.publisher.base
import
DebugFlags
...
@@ -774,14 +807,6 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
...
@@ -774,14 +807,6 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
request
[
'debug'
]
=
'2'
request
[
'debug'
]
=
'2'
self
.
assertEqual
(
request
.
debug
,
'2'
)
self
.
assertEqual
(
request
.
debug
,
'2'
)
def
test_interfaces
(
self
):
from
zope.publisher.interfaces.browser
import
IBrowserRequest
from
zope.interface.verify
import
verifyClass
klass
=
self
.
_getTargetClass
()
# TODO
# verifyClass(IBrowserRequest, klass)
def
test_locale_property_accessor
(
self
):
def
test_locale_property_accessor
(
self
):
from
zope.component
import
provideAdapter
from
zope.component
import
provideAdapter
from
zope.publisher.browser
import
BrowserLanguages
from
zope.publisher.browser
import
BrowserLanguages
...
@@ -920,7 +945,7 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
...
@@ -920,7 +945,7 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
def
test_getClientAddr_one_trusted_proxy
(
self
):
def
test_getClientAddr_one_trusted_proxy
(
self
):
from
ZPublisher.HTTPRequest
import
trusted_proxies
from
ZPublisher.HTTPRequest
import
trusted_proxies
env
=
{
'REMOTE_ADDR'
:
'127.0.0.1'
,
env
=
{
'REMOTE_ADDR'
:
'127.0.0.1'
,
'HTTP_X_FORWARDED_FOR'
:
'10.1.20.30, 192.168.1.100'
}
'HTTP_X_FORWARDED_FOR'
:
'10.1.20.30, 192.168.1.100'
}
orig
=
trusted_proxies
[:]
orig
=
trusted_proxies
[:]
try
:
try
:
...
@@ -1029,6 +1054,7 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
...
@@ -1029,6 +1054,7 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
def
test_clone_preserves_direct_interfaces
(
self
):
def
test_clone_preserves_direct_interfaces
(
self
):
from
zope.interface
import
directlyProvides
from
zope.interface
import
directlyProvides
from
zope.interface
import
Interface
from
zope.interface
import
Interface
class
IFoo
(
Interface
):
class
IFoo
(
Interface
):
pass
pass
request
=
self
.
_makeOne
()
request
=
self
.
_makeOne
()
...
@@ -1047,7 +1073,8 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
...
@@ -1047,7 +1073,8 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
request
.
resolve_url
(
request
.
script
+
'/'
)
request
.
resolve_url
(
request
.
script
+
'/'
)
finally
:
finally
:
zope
.
event
.
subscribers
.
remove
(
events
.
append
)
zope
.
event
.
subscribers
.
remove
(
events
.
append
)
self
.
assertFalse
(
len
(
events
),
self
.
assertFalse
(
len
(
events
),
"HTTPRequest.resolve_url should not emit events"
)
"HTTPRequest.resolve_url should not emit events"
)
def
test_resolve_url_errorhandling
(
self
):
def
test_resolve_url_errorhandling
(
self
):
...
@@ -1056,37 +1083,36 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
...
@@ -1056,37 +1083,36 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
from
zExceptions
import
NotFound
from
zExceptions
import
NotFound
request
=
self
.
_makeOne
()
request
=
self
.
_makeOne
()
request
[
'PARENTS'
]
=
[
object
()]
request
[
'PARENTS'
]
=
[
object
()]
self
.
assertRaises
(
NotFound
self
.
assertRaises
(
,
request
.
resolve_url
NotFound
,
request
.
resolve_url
,
request
.
script
+
'/does_not_exist'
)
,
request
.
script
+
'/does_not_exist'
)
def
test_parses_json_cookies
(
self
):
def
test_parses_json_cookies
(
self
):
# https://bugs.launchpad.net/zope2/+bug/563229
# https://bugs.launchpad.net/zope2/+bug/563229
# reports cookies in the wild with embedded double quotes (e.g,
# reports cookies in the wild with embedded double quotes (e.g,
# JSON-encoded data structures.
# JSON-encoded data structures.
env
=
{
'SERVER_NAME'
:
'testingharnas'
,
env
=
{
'SERVER_NAME'
:
'testingharnas'
,
'SERVER_PORT'
:
'80'
,
'SERVER_PORT'
:
'80'
,
'HTTP_COOKIE'
:
'json={"intkey":123,"stringkey":"blah"}; '
'HTTP_COOKIE'
:
'json={"intkey":123,"stringkey":"blah"}; '
'anothercookie=boring; baz'
'anothercookie=boring; baz'
}
}
req
=
self
.
_makeOne
(
environ
=
env
)
req
=
self
.
_makeOne
(
environ
=
env
)
self
.
assertEqual
s
(
req
.
cookies
[
'json'
],
self
.
assertEqual
(
req
.
cookies
[
'json'
],
'{"intkey":123,"stringkey":"blah"}'
)
'{"intkey":123,"stringkey":"blah"}'
)
self
.
assertEqual
s
(
req
.
cookies
[
'anothercookie'
],
'boring'
)
self
.
assertEqual
(
req
.
cookies
[
'anothercookie'
],
'boring'
)
def
test_getVirtualRoot
(
self
):
def
test_getVirtualRoot
(
self
):
# https://bugs.launchpad.net/zope2/+bug/193122
# https://bugs.launchpad.net/zope2/+bug/193122
req
=
self
.
_makeOne
()
req
=
self
.
_makeOne
()
req
.
_script
=
[]
req
.
_script
=
[]
self
.
assertEqual
s
(
req
.
getVirtualRoot
(),
''
)
self
.
assertEqual
(
req
.
getVirtualRoot
(),
''
)
req
.
_script
=
[
'foo'
,
'bar'
]
req
.
_script
=
[
'foo'
,
'bar'
]
self
.
assertEqual
s
(
req
.
getVirtualRoot
(),
'/foo/bar'
)
self
.
assertEqual
(
req
.
getVirtualRoot
(),
'/foo/bar'
)
class
TestHTTPRequestZope3Views
(
TestRequest
Zope3ViewsBase
,
):
class
TestHTTPRequestZope3Views
(
TestRequest
ViewsBase
):
def
_makeOne
(
self
,
root
):
def
_makeOne
(
self
,
root
):
from
zope.interface
import
directlyProvides
from
zope.interface
import
directlyProvides
...
@@ -1118,7 +1144,7 @@ TEST_ENVIRON = {
...
@@ -1118,7 +1144,7 @@ TEST_ENVIRON = {
'REQUEST_METHOD'
:
'POST'
,
'REQUEST_METHOD'
:
'POST'
,
'SERVER_NAME'
:
'localhost'
,
'SERVER_NAME'
:
'localhost'
,
'SERVER_PORT'
:
'80'
,
'SERVER_PORT'
:
'80'
,
}
}
TEST_FILE_DATA
=
'''
TEST_FILE_DATA
=
'''
--12345
--12345
...
@@ -1138,11 +1164,3 @@ Content-Type: application/octet-stream
...
@@ -1138,11 +1164,3 @@ Content-Type: application/octet-stream
test %s
test %s
'''
%
(
'test'
*
1000
)
'''
%
(
'test'
*
1000
)
def
test_suite
():
suite
=
unittest
.
TestSuite
()
suite
.
addTest
(
unittest
.
makeSuite
(
RecordTests
))
suite
.
addTest
(
unittest
.
makeSuite
(
HTTPRequestTests
))
suite
.
addTest
(
unittest
.
makeSuite
(
TestHTTPRequestZope3Views
))
return
suite
src/ZPublisher/tests/testHTTPResponse.py
View file @
efe61189
...
@@ -13,17 +13,15 @@ class HTTPResponseTests(unittest.TestCase):
...
@@ -13,17 +13,15 @@ class HTTPResponseTests(unittest.TestCase):
self
.
_setDefaultEncoding
(
self
.
_old_default_encoding
)
self
.
_setDefaultEncoding
(
self
.
_old_default_encoding
)
def
_setDefaultEncoding
(
self
,
value
):
def
_setDefaultEncoding
(
self
,
value
):
from
ZPublisher
import
HTTPResponse
as
module
from
ZPublisher
import
HTTPResponse
(
modul
e
.
default_encoding
,
(
HTTPRespons
e
.
default_encoding
,
self
.
_old_default_encoding
)
=
(
value
,
modul
e
.
default_encoding
)
self
.
_old_default_encoding
)
=
(
value
,
HTTPRespons
e
.
default_encoding
)
def
_getTargetClass
(
self
):
def
_getTargetClass
(
self
):
from
ZPublisher.HTTPResponse
import
HTTPResponse
from
ZPublisher.HTTPResponse
import
HTTPResponse
return
HTTPResponse
return
HTTPResponse
def
_makeOne
(
self
,
*
args
,
**
kw
):
def
_makeOne
(
self
,
*
args
,
**
kw
):
return
self
.
_getTargetClass
()(
*
args
,
**
kw
)
return
self
.
_getTargetClass
()(
*
args
,
**
kw
)
def
test_ctor_defaults
(
self
):
def
test_ctor_defaults
(
self
):
...
@@ -43,8 +41,7 @@ class HTTPResponseTests(unittest.TestCase):
...
@@ -43,8 +41,7 @@ class HTTPResponseTests(unittest.TestCase):
def
test_ctor_w_headers
(
self
):
def
test_ctor_w_headers
(
self
):
response
=
self
.
_makeOne
(
headers
=
{
'foo'
:
'bar'
})
response
=
self
.
_makeOne
(
headers
=
{
'foo'
:
'bar'
})
self
.
assertEqual
(
response
.
headers
,
{
'foo'
:
'bar'
,
self
.
assertEqual
(
response
.
headers
,
{
'foo'
:
'bar'
})
})
def
test_ctor_w_status_code
(
self
):
def
test_ctor_w_status_code
(
self
):
response
=
self
.
_makeOne
(
status
=
401
)
response
=
self
.
_makeOne
(
status
=
401
)
...
@@ -83,9 +80,9 @@ class HTTPResponseTests(unittest.TestCase):
...
@@ -83,9 +80,9 @@ class HTTPResponseTests(unittest.TestCase):
'application/foo'
)
'application/foo'
)
def
test_ctor_charset_application_header_with_header
(
self
):
def
test_ctor_charset_application_header_with_header
(
self
):
response
=
self
.
_makeOne
(
body
=
'foo'
,
response
=
self
.
_makeOne
(
headers
=
{
'content-type'
:
body
=
'foo'
,
'application/foo; charset: something'
})
headers
=
{
'content-type'
:
'application/foo; charset: something'
})
self
.
assertEqual
(
response
.
headers
.
get
(
'content-type'
),
self
.
assertEqual
(
response
.
headers
.
get
(
'content-type'
),
'application/foo; charset: something'
)
'application/foo; charset: something'
)
...
@@ -109,16 +106,18 @@ class HTTPResponseTests(unittest.TestCase):
...
@@ -109,16 +106,18 @@ class HTTPResponseTests(unittest.TestCase):
def
test_ctor_body_recodes_to_match_content_type_charset
(
self
):
def
test_ctor_body_recodes_to_match_content_type_charset
(
self
):
xml
=
(
u'<?xml version="1.0" encoding="iso-8859-15" ?>
\
n
'
xml
=
(
u'<?xml version="1.0" encoding="iso-8859-15" ?>
\
n
'
'<foo><bar/></foo>'
)
u'<foo><bar/></foo>'
)
response
=
self
.
_makeOne
(
body
=
xml
,
headers
=
{
'content-type'
:
response
=
self
.
_makeOne
(
'text/xml; charset=utf-8'
})
body
=
xml
,
headers
=
{
'content-type'
:
'text/xml; charset=utf-8'
})
self
.
assertEqual
(
response
.
body
,
xml
.
replace
(
'iso-8859-15'
,
'utf-8'
))
self
.
assertEqual
(
response
.
body
,
xml
.
replace
(
'iso-8859-15'
,
'utf-8'
))
def
test_ctor_body_already_matches_charset_unchanged
(
self
):
def
test_ctor_body_already_matches_charset_unchanged
(
self
):
xml
=
(
u'<?xml version="1.0" encoding="iso-8859-15" ?>
\
n
'
xml
=
(
u'<?xml version="1.0" encoding="iso-8859-15" ?>
\
n
'
'<foo><bar/></foo>'
)
u'<foo><bar/></foo>'
)
response
=
self
.
_makeOne
(
body
=
xml
,
headers
=
{
'content-type'
:
response
=
self
.
_makeOne
(
'text/xml; charset=iso-8859-15'
})
body
=
xml
,
headers
=
{
'content-type'
:
'text/xml; charset=iso-8859-15'
})
self
.
assertEqual
(
response
.
body
,
xml
)
self
.
assertEqual
(
response
.
body
,
xml
)
def
test_retry
(
self
):
def
test_retry
(
self
):
...
@@ -278,7 +277,7 @@ class HTTPResponseTests(unittest.TestCase):
...
@@ -278,7 +277,7 @@ class HTTPResponseTests(unittest.TestCase):
cookies
=
response
.
_cookie_list
()
cookies
=
response
.
_cookie_list
()
self
.
assertEqual
(
len
(
cookies
),
1
)
self
.
assertEqual
(
len
(
cookies
),
1
)
self
.
assertEqual
(
cookies
[
0
],
(
'Set-Cookie'
,
'foo="bar"; Secure'
))
self
.
assertEqual
(
cookies
[
0
],
(
'Set-Cookie'
,
'foo="bar"; Secure'
))
def
test_setCookie_w_secure_false_value
(
self
):
def
test_setCookie_w_secure_false_value
(
self
):
response
=
self
.
_makeOne
()
response
=
self
.
_makeOne
()
...
@@ -586,6 +585,7 @@ class HTTPResponseTests(unittest.TestCase):
...
@@ -586,6 +585,7 @@ class HTTPResponseTests(unittest.TestCase):
def
test_setBody_object_with_asHTML
(
self
):
def
test_setBody_object_with_asHTML
(
self
):
HTML
=
'<html><head></head><body></body></html>'
HTML
=
'<html><head></head><body></body></html>'
class
Dummy
:
class
Dummy
:
def
asHTML
(
self
):
def
asHTML
(
self
):
return
HTML
return
HTML
...
@@ -598,7 +598,8 @@ class HTTPResponseTests(unittest.TestCase):
...
@@ -598,7 +598,8 @@ class HTTPResponseTests(unittest.TestCase):
self
.
assertEqual
(
response
.
getHeader
(
'Content-Length'
),
str
(
len
(
HTML
)))
self
.
assertEqual
(
response
.
getHeader
(
'Content-Length'
),
str
(
len
(
HTML
)))
def
test_setBody_object_with_unicode
(
self
):
def
test_setBody_object_with_unicode
(
self
):
HTML
=
u'<html><head></head><body><h1>Tr
\
u0039
s Bien</h1></body></html>'
HTML
=
(
u'<html><head></head><body>'
u'<h1>Tr
\
u0039
s Bien</h1></body></html>'
)
ENCODED
=
HTML
.
encode
(
'utf-8'
)
ENCODED
=
HTML
.
encode
(
'utf-8'
)
response
=
self
.
_makeOne
()
response
=
self
.
_makeOne
()
result
=
response
.
setBody
(
HTML
)
result
=
response
.
setBody
(
HTML
)
...
@@ -646,14 +647,13 @@ class HTTPResponseTests(unittest.TestCase):
...
@@ -646,14 +647,13 @@ class HTTPResponseTests(unittest.TestCase):
def
test_setBody_calls_insertBase
(
self
):
def
test_setBody_calls_insertBase
(
self
):
response
=
self
.
_makeOne
()
response
=
self
.
_makeOne
()
lamb
=
{}
lamb
=
{}
def
_insertBase
():
def
_insertBase
():
lamb
[
'flavor'
]
=
'CURRY'
lamb
[
'flavor'
]
=
'CURRY'
response
.
insertBase
=
_insertBase
response
.
insertBase
=
_insertBase
response
.
setBody
(
'Garlic Naan'
)
response
.
setBody
(
'Garlic Naan'
)
self
.
assertEqual
(
lamb
[
'flavor'
],
'CURRY'
)
self
.
assertEqual
(
lamb
[
'flavor'
],
'CURRY'
)
#def test_setBody_w_HTTP_content_compression(self):
def
test_setBody_compression_uncompressible_mimetype
(
self
):
def
test_setBody_compression_uncompressible_mimetype
(
self
):
BEFORE
=
'foo'
*
100
# body must get smaller on compression
BEFORE
=
'foo'
*
100
# body must get smaller on compression
response
=
self
.
_makeOne
()
response
=
self
.
_makeOne
()
...
@@ -701,7 +701,7 @@ class HTTPResponseTests(unittest.TestCase):
...
@@ -701,7 +701,7 @@ class HTTPResponseTests(unittest.TestCase):
response
=
self
.
_makeOne
()
response
=
self
.
_makeOne
()
response
.
enableHTTPCompression
({
'HTTP_ACCEPT_ENCODING'
:
'gzip'
})
response
.
enableHTTPCompression
({
'HTTP_ACCEPT_ENCODING'
:
'gzip'
})
response
.
setHeader
(
'Vary'
,
PRIOR
)
response
.
setHeader
(
'Vary'
,
PRIOR
)
response
.
setBody
(
'foo'
*
100
)
response
.
setBody
(
'foo'
*
100
)
self
.
assertEqual
(
response
.
getHeader
(
'Vary'
),
PRIOR
)
self
.
assertEqual
(
response
.
getHeader
(
'Vary'
),
PRIOR
)
def
test_setBody_compression_no_prior_vary_header_but_forced
(
self
):
def
test_setBody_compression_no_prior_vary_header_but_forced
(
self
):
...
@@ -770,8 +770,8 @@ class HTTPResponseTests(unittest.TestCase):
...
@@ -770,8 +770,8 @@ class HTTPResponseTests(unittest.TestCase):
response
=
self
.
_makeOne
()
response
=
self
.
_makeOne
()
response
.
setHeader
(
'Content-Type'
,
'text/html; charset=latin1'
)
response
.
setHeader
(
'Content-Type'
,
'text/html; charset=latin1'
)
self
.
assertEqual
(
response
.
_encode_unicode
(
UNICODE
),
self
.
assertEqual
(
response
.
_encode_unicode
(
UNICODE
),
'<?xml version="1.0" encoding="latin1" ?>
\
n
'
'<?xml version="1.0" encoding="latin1" ?>
\
n
'
+
+
ELEMENT
.
encode
(
'latin1'
))
ELEMENT
.
encode
(
'latin1'
))
response
.
getHeader
(
'Content-Type'
,
'text/html; charset=latin1'
)
response
.
getHeader
(
'Content-Type'
,
'text/html; charset=latin1'
)
def
test_quoteHTML
(
self
):
def
test_quoteHTML
(
self
):
...
@@ -786,7 +786,7 @@ class HTTPResponseTests(unittest.TestCase):
...
@@ -786,7 +786,7 @@ class HTTPResponseTests(unittest.TestCase):
response
=
self
.
_makeOne
()
response
=
self
.
_makeOne
()
try
:
try
:
response
.
notFoundError
()
response
.
notFoundError
()
except
NotFound
,
raised
:
except
NotFound
as
raised
:
self
.
assertEqual
(
response
.
status
,
404
)
self
.
assertEqual
(
response
.
status
,
404
)
self
.
assertTrue
(
"<p><b>Resource:</b> Unknown</p>"
in
str
(
raised
))
self
.
assertTrue
(
"<p><b>Resource:</b> Unknown</p>"
in
str
(
raised
))
else
:
else
:
...
@@ -797,7 +797,7 @@ class HTTPResponseTests(unittest.TestCase):
...
@@ -797,7 +797,7 @@ class HTTPResponseTests(unittest.TestCase):
response
=
self
.
_makeOne
()
response
=
self
.
_makeOne
()
try
:
try
:
response
.
notFoundError
(
'ENTRY'
)
response
.
notFoundError
(
'ENTRY'
)
except
NotFound
,
raised
:
except
NotFound
as
raised
:
self
.
assertEqual
(
response
.
status
,
404
)
self
.
assertEqual
(
response
.
status
,
404
)
self
.
assertTrue
(
"<p><b>Resource:</b> ENTRY</p>"
in
str
(
raised
))
self
.
assertTrue
(
"<p><b>Resource:</b> ENTRY</p>"
in
str
(
raised
))
else
:
else
:
...
@@ -808,7 +808,7 @@ class HTTPResponseTests(unittest.TestCase):
...
@@ -808,7 +808,7 @@ class HTTPResponseTests(unittest.TestCase):
response
=
self
.
_makeOne
()
response
=
self
.
_makeOne
()
try
:
try
:
response
.
forbiddenError
()
response
.
forbiddenError
()
except
NotFound
,
raised
:
except
NotFound
as
raised
:
self
.
assertEqual
(
response
.
status
,
404
)
self
.
assertEqual
(
response
.
status
,
404
)
self
.
assertTrue
(
"<p><b>Resource:</b> Unknown</p>"
in
str
(
raised
))
self
.
assertTrue
(
"<p><b>Resource:</b> Unknown</p>"
in
str
(
raised
))
else
:
else
:
...
@@ -819,7 +819,7 @@ class HTTPResponseTests(unittest.TestCase):
...
@@ -819,7 +819,7 @@ class HTTPResponseTests(unittest.TestCase):
response
=
self
.
_makeOne
()
response
=
self
.
_makeOne
()
try
:
try
:
response
.
forbiddenError
(
'ENTRY'
)
response
.
forbiddenError
(
'ENTRY'
)
except
NotFound
,
raised
:
except
NotFound
as
raised
:
self
.
assertEqual
(
response
.
status
,
404
)
self
.
assertEqual
(
response
.
status
,
404
)
self
.
assertTrue
(
"<p><b>Resource:</b> ENTRY</p>"
in
str
(
raised
))
self
.
assertTrue
(
"<p><b>Resource:</b> ENTRY</p>"
in
str
(
raised
))
else
:
else
:
...
@@ -830,7 +830,7 @@ class HTTPResponseTests(unittest.TestCase):
...
@@ -830,7 +830,7 @@ class HTTPResponseTests(unittest.TestCase):
response
=
self
.
_makeOne
()
response
=
self
.
_makeOne
()
try
:
try
:
response
.
debugError
(
'testing'
)
response
.
debugError
(
'testing'
)
except
NotFound
,
raised
:
except
NotFound
as
raised
:
self
.
assertEqual
(
response
.
status
,
200
)
self
.
assertEqual
(
response
.
status
,
200
)
self
.
assertTrue
(
"Zope has encountered a problem publishing "
self
.
assertTrue
(
"Zope has encountered a problem publishing "
"your object.<p>
\
n
testing</p>"
in
str
(
raised
))
"your object.<p>
\
n
testing</p>"
in
str
(
raised
))
...
@@ -842,7 +842,7 @@ class HTTPResponseTests(unittest.TestCase):
...
@@ -842,7 +842,7 @@ class HTTPResponseTests(unittest.TestCase):
response
=
self
.
_makeOne
()
response
=
self
.
_makeOne
()
try
:
try
:
response
.
badRequestError
(
'some_parameter'
)
response
.
badRequestError
(
'some_parameter'
)
except
BadRequest
,
raised
:
except
BadRequest
as
raised
:
self
.
assertEqual
(
response
.
status
,
400
)
self
.
assertEqual
(
response
.
status
,
400
)
self
.
assertTrue
(
"The parameter, <em>some_parameter</em>, "
self
.
assertTrue
(
"The parameter, <em>some_parameter</em>, "
"was omitted from the request."
in
str
(
raised
))
"was omitted from the request."
in
str
(
raised
))
...
@@ -854,7 +854,7 @@ class HTTPResponseTests(unittest.TestCase):
...
@@ -854,7 +854,7 @@ class HTTPResponseTests(unittest.TestCase):
response
=
self
.
_makeOne
()
response
=
self
.
_makeOne
()
try
:
try
:
response
.
badRequestError
(
'URL1'
)
response
.
badRequestError
(
'URL1'
)
except
InternalError
,
raised
:
except
InternalError
as
raised
:
self
.
assertEqual
(
response
.
status
,
400
)
self
.
assertEqual
(
response
.
status
,
400
)
self
.
assertTrue
(
"Sorry, an internal error occurred in this "
self
.
assertTrue
(
"Sorry, an internal error occurred in this "
"resource."
in
str
(
raised
))
"resource."
in
str
(
raised
))
...
@@ -870,7 +870,7 @@ class HTTPResponseTests(unittest.TestCase):
...
@@ -870,7 +870,7 @@ class HTTPResponseTests(unittest.TestCase):
def
test__unauthorized_w_default_realm
(
self
):
def
test__unauthorized_w_default_realm
(
self
):
response
=
self
.
_makeOne
()
response
=
self
.
_makeOne
()
response
.
_unauthorized
()
response
.
_unauthorized
()
self
.
assertTrue
(
'WWW-Authenticate'
in
response
.
headers
)
#
literal
self
.
assertTrue
(
'WWW-Authenticate'
in
response
.
headers
)
#
literal
self
.
assertEqual
(
response
.
headers
[
'WWW-Authenticate'
],
self
.
assertEqual
(
response
.
headers
[
'WWW-Authenticate'
],
'basic realm="Zope"'
)
'basic realm="Zope"'
)
...
@@ -878,7 +878,7 @@ class HTTPResponseTests(unittest.TestCase):
...
@@ -878,7 +878,7 @@ class HTTPResponseTests(unittest.TestCase):
response
=
self
.
_makeOne
()
response
=
self
.
_makeOne
()
response
.
realm
=
'Folly'
response
.
realm
=
'Folly'
response
.
_unauthorized
()
response
.
_unauthorized
()
self
.
assertTrue
(
'WWW-Authenticate'
in
response
.
headers
)
#
literal
self
.
assertTrue
(
'WWW-Authenticate'
in
response
.
headers
)
#
literal
self
.
assertEqual
(
response
.
headers
[
'WWW-Authenticate'
],
self
.
assertEqual
(
response
.
headers
[
'WWW-Authenticate'
],
'basic realm="Folly"'
)
'basic realm="Folly"'
)
...
@@ -887,7 +887,7 @@ class HTTPResponseTests(unittest.TestCase):
...
@@ -887,7 +887,7 @@ class HTTPResponseTests(unittest.TestCase):
response
=
self
.
_makeOne
()
response
=
self
.
_makeOne
()
try
:
try
:
response
.
unauthorized
()
response
.
unauthorized
()
except
Unauthorized
,
raised
:
except
Unauthorized
as
raised
:
self
.
assertEqual
(
response
.
status
,
200
)
# publisher sets 401 later
self
.
assertEqual
(
response
.
status
,
200
)
# publisher sets 401 later
self
.
assertTrue
(
"You are not authorized "
self
.
assertTrue
(
"You are not authorized "
"to access this resource."
in
str
(
raised
))
"to access this resource."
in
str
(
raised
))
...
@@ -900,7 +900,7 @@ class HTTPResponseTests(unittest.TestCase):
...
@@ -900,7 +900,7 @@ class HTTPResponseTests(unittest.TestCase):
response
.
debug_mode
=
True
response
.
debug_mode
=
True
try
:
try
:
response
.
unauthorized
()
response
.
unauthorized
()
except
Unauthorized
,
raised
:
except
Unauthorized
as
raised
:
self
.
assertTrue
(
"
\
n
No Authorization header found."
self
.
assertTrue
(
"
\
n
No Authorization header found."
in
str
(
raised
))
in
str
(
raised
))
else
:
else
:
...
@@ -913,7 +913,7 @@ class HTTPResponseTests(unittest.TestCase):
...
@@ -913,7 +913,7 @@ class HTTPResponseTests(unittest.TestCase):
response
.
_auth
=
'bogus'
response
.
_auth
=
'bogus'
try
:
try
:
response
.
unauthorized
()
response
.
unauthorized
()
except
Unauthorized
,
raised
:
except
Unauthorized
as
raised
:
self
.
assertTrue
(
"
\
n
Username and password are not correct."
self
.
assertTrue
(
"
\
n
Username and password are not correct."
in
str
(
raised
))
in
str
(
raised
))
else
:
else
:
...
@@ -1058,9 +1058,9 @@ class HTTPResponseTests(unittest.TestCase):
...
@@ -1058,9 +1058,9 @@ class HTTPResponseTests(unittest.TestCase):
response
=
self
.
_makeOne
()
response
=
self
.
_makeOne
()
response
.
expireCookie
(
'qux'
,
path
=
'/'
)
response
.
expireCookie
(
'qux'
,
path
=
'/'
)
headers
=
response
.
listHeaders
()
headers
=
response
.
listHeaders
()
self
.
assertEqual
(
headers
,
self
.
assertEqual
(
[(
'X-Powered-By'
,
'Zope (www.zope.org), '
headers
,
'
Python (www.python.org)'
),
[(
'X-Powered-By'
,
'Zope (www.zope.org),
Python (www.python.org)'
),
(
'Set-Cookie'
,
'qux="deleted"; '
(
'Set-Cookie'
,
'qux="deleted"; '
'Path=/; '
'Path=/; '
'Expires=Wed, 31-Dec-97 23:59:59 GMT; '
'Expires=Wed, 31-Dec-97 23:59:59 GMT; '
...
@@ -1300,12 +1300,3 @@ class HTTPResponseTests(unittest.TestCase):
...
@@ -1300,12 +1300,3 @@ class HTTPResponseTests(unittest.TestCase):
'See the server error log for details'
)
'See the server error log for details'
)
self
.
assertTrue
(
'bobo-exception-file'
in
response
.
headers
)
self
.
assertTrue
(
'bobo-exception-file'
in
response
.
headers
)
self
.
assertTrue
(
'bobo-exception-line'
in
response
.
headers
)
self
.
assertTrue
(
'bobo-exception-line'
in
response
.
headers
)
#TODO
# def test_exception_* WAAAAAA!
def
test_suite
():
suite
=
unittest
.
TestSuite
()
suite
.
addTest
(
unittest
.
makeSuite
(
HTTPResponseTests
,
'test'
))
return
suite
src/ZPublisher/tests/testIterators.py
View file @
efe61189
...
@@ -2,11 +2,8 @@ import unittest
...
@@ -2,11 +2,8 @@ import unittest
from
zope.interface.verify
import
verifyClass
from
zope.interface.verify
import
verifyClass
from
ZPublisher.Iterators
import
IStreamIterator
,
filestream_iterator
from
ZPublisher.Iterators
import
IStreamIterator
,
filestream_iterator
class
TestFileStreamIterator
(
unittest
.
TestCase
):
class
TestFileStreamIterator
(
unittest
.
TestCase
):
def
testInterface
(
self
):
def
testInterface
(
self
):
verifyClass
(
IStreamIterator
,
filestream_iterator
)
verifyClass
(
IStreamIterator
,
filestream_iterator
)
def
test_suite
():
suite
=
unittest
.
TestSuite
()
suite
.
addTest
(
unittest
.
makeSuite
(
TestFileStreamIterator
)
)
return
suite
src/ZPublisher/tests/testPostTraversal.py
View file @
efe61189
from
unittest
import
TestCase
,
TestSuite
,
makeSuite
,
main
from
unittest
import
TestCase
import
Testing
import
Zope2
Zope2
.
startup
()
from
Acquisition
import
Implicit
from
Acquisition
import
Implicit
from
ZPublisher.BaseRequest
import
BaseRequest
from
ZPublisher.BaseRequest
import
BaseRequest
from
ZPublisher.HTTPResponse
import
HTTPResponse
from
ZPublisher.HTTPResponse
import
HTTPResponse
import
Zope2
Zope2
.
startup
()
# Various post traversal methods
pt_simple_was_run
=
0
pt_simple_was_run
=
0
def
pt_simple
():
def
pt_simple
():
global
pt_simple_was_run
global
pt_simple_was_run
pt_simple_was_run
=
1
pt_simple_was_run
=
1
pass
pass
def
pt_static_arg
(
request
,
b
):
def
pt_static_arg
(
request
,
b
):
request
.
set
(
'b'
,
b
)
request
.
set
(
'b'
,
b
)
pass
pass
def
pt_simple_redirect
(
a
):
def
pt_simple_redirect
(
a
):
return
a
return
a
def
pt_chain_test
(
request
,
string
):
def
pt_chain_test
(
request
,
string
):
request
.
set
(
'a'
,
request
.
get
(
'a'
,
''
)
+
string
)
request
.
set
(
'a'
,
request
.
get
(
'a'
,
''
)
+
string
)
class
DummyObjectBasic
(
Implicit
):
class
DummyObjectBasic
(
Implicit
):
""" Dummy class with docstring.
""" Dummy class with docstring.
"""
"""
...
@@ -41,6 +42,7 @@ class DummyObjectBasic(Implicit):
...
@@ -41,6 +42,7 @@ class DummyObjectBasic(Implicit):
"""
"""
return
'view content'
return
'view content'
class
DummyObjectWithPTHook
(
DummyObjectBasic
):
class
DummyObjectWithPTHook
(
DummyObjectBasic
):
""" Dummy class with docstring.
""" Dummy class with docstring.
"""
"""
...
@@ -51,21 +53,24 @@ class DummyObjectWithPTHook(DummyObjectBasic):
...
@@ -51,21 +53,24 @@ class DummyObjectWithPTHook(DummyObjectBasic):
for
x
in
self
.
traversal
:
for
x
in
self
.
traversal
:
REQUEST
.
post_traverse
(
*
x
)
REQUEST
.
post_traverse
(
*
x
)
class
TestBaseRequestPT
(
TestCase
):
class
TestBaseRequestPT
(
TestCase
):
def
setUp
(
self
):
def
setUp
(
self
):
self
.
root
=
DummyObjectBasic
()
self
.
root
=
DummyObjectBasic
()
self
.
f1
=
self
.
root
.
_setObject
(
'folder'
,
DummyObjectBasic
()
)
self
.
f1
=
self
.
root
.
_setObject
(
'folder'
,
DummyObjectBasic
())
self
.
f1
.
_setObject
(
'objBasic'
,
DummyObjectWithPTHook
()
)
self
.
f1
.
_setObject
(
'objBasic'
,
DummyObjectWithPTHook
())
def
makeBaseRequest
(
self
):
def
makeBaseRequest
(
self
):
response
=
HTTPResponse
()
response
=
HTTPResponse
()
environment
=
{
'URL'
:
''
,
environment
=
{
'URL'
:
''
,
'PARENTS'
:
[
self
.
root
],
'PARENTS'
:
[
self
.
root
],
'steps'
:
[],
'steps'
:
[],
'_hacked_path'
:
0
,
'_hacked_path'
:
0
,
'_test_counter'
:
0
,
'_test_counter'
:
0
,
'response'
:
response
}
'response'
:
response
,
}
return
BaseRequest
(
environment
)
return
BaseRequest
(
environment
)
def
test_post_basic
(
self
):
def
test_post_basic
(
self
):
...
@@ -101,13 +106,15 @@ class TestBaseRequestPT(TestCase):
...
@@ -101,13 +106,15 @@ class TestBaseRequestPT(TestCase):
r
=
self
.
makeBaseRequest
()
r
=
self
.
makeBaseRequest
()
self
.
f1
.
objBasic
.
traversal
=
[
(
pt_chain_test
,
(
r
,
'a'
)),
self
.
f1
.
objBasic
.
traversal
=
[
(
pt_chain_test
,
(
r
,
'a'
)),
(
pt_chain_test
,
(
r
,
'b'
)),
(
pt_chain_test
,
(
r
,
'b'
)),
(
pt_chain_test
,
(
r
,
'c'
)),
(
pt_chain_test
,
(
r
,
'c'
)),
(
pt_chain_test
,
(
r
,
'd'
))]
(
pt_chain_test
,
(
r
,
'd'
)),
]
x
=
r
.
traverse
(
'folder/objBasic'
)
r
.
traverse
(
'folder/objBasic'
)
self
.
assertEqual
(
r
.
get
(
'a'
,
''
),
'abcd'
)
self
.
assertEqual
(
r
.
get
(
'a'
,
''
),
'abcd'
)
self
.
f1
.
objBasic
.
traversal
=
[]
self
.
f1
.
objBasic
.
traversal
=
[]
...
@@ -123,17 +130,16 @@ class TestBaseRequestPT(TestCase):
...
@@ -123,17 +130,16 @@ class TestBaseRequestPT(TestCase):
def
test_hook_chain_redirect
(
self
):
def
test_hook_chain_redirect
(
self
):
r
=
self
.
makeBaseRequest
()
r
=
self
.
makeBaseRequest
()
check
=
[]
check
=
[]
self
.
f1
.
objBasic
.
traversal
=
[
(
pt_chain_test
,
(
r
,
'a'
)),
self
.
f1
.
objBasic
.
traversal
=
[
(
pt_chain_test
,
(
r
,
'a'
)),
(
pt_chain_test
,
(
r
,
'b'
)),
(
pt_chain_test
,
(
r
,
'b'
)),
(
pt_chain_test
,
(
r
,
'c'
)),
(
pt_chain_test
,
(
r
,
'c'
)),
(
pt_simple_redirect
,
(
check
,)),
(
pt_simple_redirect
,
(
check
,)),
(
pt_simple_redirect
,
(
1
,)),
(
pt_simple_redirect
,
(
1
,)),
(
pt_chain_test
,
(
r
,
'd'
))]
(
pt_chain_test
,
(
r
,
'd'
)),
]
x
=
r
.
traverse
(
'folder/objBasic'
)
x
=
r
.
traverse
(
'folder/objBasic'
)
self
.
assertEqual
(
r
.
get
(
'a'
,
''
),
'abc'
)
self
.
assertEqual
(
r
.
get
(
'a'
,
''
),
'abc'
)
self
.
assertEqual
(
x
,
check
)
self
.
assertEqual
(
x
,
check
)
def
test_suite
():
return
TestSuite
(
(
makeSuite
(
TestBaseRequestPT
),
)
)
src/ZPublisher/tests/testPublish.py
View file @
efe61189
import
doctest
from
zope.interface
import
implements
from
zope.interface
import
implements
from
zope.publisher.interfaces.browser
import
IDefaultBrowserLayer
from
zope.publisher.interfaces.browser
import
IDefaultBrowserLayer
from
zope.publisher.interfaces.browser
import
IBrowserRequest
from
zope.publisher.interfaces.browser
import
IBrowserRequest
...
@@ -5,6 +7,7 @@ from zope.publisher.skinnable import setDefaultSkin
...
@@ -5,6 +7,7 @@ from zope.publisher.skinnable import setDefaultSkin
from
ZPublisher
import
Retry
from
ZPublisher
import
Retry
from
ZODB.POSException
import
ConflictError
from
ZODB.POSException
import
ConflictError
class
Tracer
:
class
Tracer
:
"""Trace used to record pathway taken through the publisher
"""Trace used to record pathway taken through the publisher
machinery. And provide framework for spewing out exceptions at
machinery. And provide framework for spewing out exceptions at
...
@@ -23,7 +26,7 @@ class Tracer:
...
@@ -23,7 +26,7 @@ class Tracer:
def
showTracedPath
(
self
):
def
showTracedPath
(
self
):
for
arg
in
self
.
tracedPath
:
for
arg
in
self
.
tracedPath
:
print
arg
print
(
arg
)
def
possiblyRaiseException
(
self
,
context
):
def
possiblyRaiseException
(
self
,
context
):
exceptions
=
tracer
.
exceptions
.
get
(
context
,
None
)
exceptions
=
tracer
.
exceptions
.
get
(
context
,
None
)
...
@@ -35,9 +38,9 @@ class Tracer:
...
@@ -35,9 +38,9 @@ class Tracer:
self
.
append
(
'raising %s from %s'
%
(
exceptionShortName
,
context
))
self
.
append
(
'raising %s from %s'
%
(
exceptionShortName
,
context
))
raise
exception
raise
exception
tracer
=
Tracer
()
tracer
=
Tracer
()
class
TransactionsManager
:
class
TransactionsManager
:
"""Mock TransactionManager to replace
"""Mock TransactionManager to replace
Zope2.App.startup.TransactionsManager.
Zope2.App.startup.TransactionsManager.
...
@@ -58,6 +61,7 @@ class TransactionsManager:
...
@@ -58,6 +61,7 @@ class TransactionsManager:
zpublisher_transactions_manager
=
TransactionsManager
()
zpublisher_transactions_manager
=
TransactionsManager
()
def
zpublisher_exception_hook
(
published
,
request
,
t
,
v
,
traceback
):
def
zpublisher_exception_hook
(
published
,
request
,
t
,
v
,
traceback
):
"""Mock zpublisher_exception_hook to replace
"""Mock zpublisher_exception_hook to replace
Zope2.App.startup.zpublisher_exception_hook
Zope2.App.startup.zpublisher_exception_hook
...
@@ -71,6 +75,7 @@ def zpublisher_exception_hook(published, request, t, v, traceback):
...
@@ -71,6 +75,7 @@ def zpublisher_exception_hook(published, request, t, v, traceback):
tracer
.
possiblyRaiseException
(
'zpublisher_exception_hook'
)
tracer
.
possiblyRaiseException
(
'zpublisher_exception_hook'
)
return
'zpublisher_exception_hook'
return
'zpublisher_exception_hook'
class
Object
:
class
Object
:
"""Mock object for traversing to.
"""Mock object for traversing to.
"""
"""
...
@@ -80,6 +85,7 @@ class Object:
...
@@ -80,6 +85,7 @@ class Object:
tracer
.
possiblyRaiseException
(
'__call__'
)
tracer
.
possiblyRaiseException
(
'__call__'
)
return
'__call__'
return
'__call__'
class
Response
:
class
Response
:
"""Mock Response to replace ZPublisher.HTTPResponse.HTTPResponse.
"""Mock Response to replace ZPublisher.HTTPResponse.HTTPResponse.
"""
"""
...
@@ -87,6 +93,7 @@ class Response:
...
@@ -87,6 +93,7 @@ class Response:
def
setBody
(
self
,
a
):
def
setBody
(
self
,
a
):
pass
pass
class
Request
:
class
Request
:
"""Mock Request to replace ZPublisher.HTTPRequest.HTTPRequest.
"""Mock Request to replace ZPublisher.HTTPRequest.HTTPRequest.
"""
"""
...
@@ -125,6 +132,7 @@ class Request:
...
@@ -125,6 +132,7 @@ class Request:
r
.
retry_count
=
self
.
retry_count
r
.
retry_count
=
self
.
retry_count
return
r
return
r
class
RequestWithSkinCheck
(
Request
):
class
RequestWithSkinCheck
(
Request
):
def
traverse
(
self
,
path
,
validated_hook
):
def
traverse
(
self
,
path
,
validated_hook
):
if
IDefaultBrowserLayer
.
providedBy
(
self
):
if
IDefaultBrowserLayer
.
providedBy
(
self
):
...
@@ -331,6 +339,7 @@ def testPublisher():
...
@@ -331,6 +339,7 @@ def testPublisher():
"""
"""
pass
pass
class
ObjectNotFound
:
class
ObjectNotFound
:
"""Mock object for traversing to.
"""Mock object for traversing to.
"""
"""
...
@@ -357,6 +366,7 @@ class PathRequest(Request):
...
@@ -357,6 +366,7 @@ class PathRequest(Request):
else
:
else
:
return
ObjectNotFound
()
return
ObjectNotFound
()
def
testPublishPath
():
def
testPublishPath
():
"""
"""
Tests to ensure that publish passes paths through to the request without
Tests to ensure that publish passes paths through to the request without
...
@@ -388,10 +398,7 @@ def testPublishPath():
...
@@ -388,10 +398,7 @@ def testPublishPath():
commit
commit
"""
"""
pass
import
doctest
def
test_suite
():
def
test_suite
():
return
doctest
.
DocTestSuite
()
return
doctest
.
DocTestSuite
()
src/ZPublisher/tests/test_Converters.py
View file @
efe61189
...
@@ -13,6 +13,7 @@
...
@@ -13,6 +13,7 @@
import
unittest
import
unittest
class
ConvertersTests
(
unittest
.
TestCase
):
class
ConvertersTests
(
unittest
.
TestCase
):
def
test_field2string_with_string
(
self
):
def
test_field2string_with_string
(
self
):
...
@@ -29,21 +30,12 @@ class ConvertersTests(unittest.TestCase):
...
@@ -29,21 +30,12 @@ class ConvertersTests(unittest.TestCase):
def
test_field2string_with_filelike_object
(
self
):
def
test_field2string_with_filelike_object
(
self
):
from
ZPublisher.Converters
import
field2string
from
ZPublisher.Converters
import
field2string
to_convert
=
'to_convert'
to_convert
=
'to_convert'
class
Filelike
:
class
Filelike
:
def
read
(
self
):
def
read
(
self
):
return
to_convert
return
to_convert
self
.
assertEqual
(
field2string
(
Filelike
()),
to_convert
)
self
.
assertEqual
(
field2string
(
Filelike
()),
to_convert
)
#TODO def test_field2text....
#TODO def test_field2required....
#TODO def test_field2int....
#TODO def test_field2float....
#TODO def test_field2tokens....
def
test_field2lines_with_list
(
self
):
def
test_field2lines_with_list
(
self
):
from
ZPublisher.Converters
import
field2lines
from
ZPublisher.Converters
import
field2lines
to_convert
=
[
'one'
,
'two'
]
to_convert
=
[
'one'
,
'two'
]
...
@@ -69,19 +61,6 @@ class ConvertersTests(unittest.TestCase):
...
@@ -69,19 +61,6 @@ class ConvertersTests(unittest.TestCase):
to_convert
=
'abc
\
n
def
\
n
ghi'
to_convert
=
'abc
\
n
def
\
n
ghi'
self
.
assertEqual
(
field2lines
(
to_convert
),
to_convert
.
splitlines
())
self
.
assertEqual
(
field2lines
(
to_convert
),
to_convert
.
splitlines
())
#TODO def test_field2date....
#TODO def test_field2date_international....
#TODO def test_field2boolean....
#TODO def test_field2ustring....
#TODO def test_field2utokens....
#TODO def test_field2utext....
def
test_field2ulines_with_list
(
self
):
def
test_field2ulines_with_list
(
self
):
from
ZPublisher.Converters
import
field2ulines
from
ZPublisher.Converters
import
field2ulines
to_convert
=
[
u'one'
,
'two'
]
to_convert
=
[
u'one'
,
'two'
]
...
@@ -108,7 +87,3 @@ class ConvertersTests(unittest.TestCase):
...
@@ -108,7 +87,3 @@ class ConvertersTests(unittest.TestCase):
from
ZPublisher.Converters
import
field2ulines
from
ZPublisher.Converters
import
field2ulines
to_convert
=
u'abc
\
n
def
\
n
ghi'
to_convert
=
u'abc
\
n
def
\
n
ghi'
self
.
assertEqual
(
field2ulines
(
to_convert
),
to_convert
.
splitlines
())
self
.
assertEqual
(
field2ulines
(
to_convert
),
to_convert
.
splitlines
())
def
test_suite
():
return
unittest
.
TestSuite
((
unittest
.
makeSuite
(
ConvertersTests
),))
src/ZPublisher/tests/test_exception_handling.py
View file @
efe61189
...
@@ -40,8 +40,11 @@ class ExceptionRaiser3(SimpleItem):
...
@@ -40,8 +40,11 @@ class ExceptionRaiser3(SimpleItem):
def
test_suite
():
def
test_suite
():
return
unittest
.
TestSuite
([
return
unittest
.
TestSuite
([
FunctionalDocFileSuite
(
'exception_handling.txt'
,
FunctionalDocFileSuite
(
globs
=
{
'ExceptionRaiser1'
:
ExceptionRaiser1
,
'exception_handling.txt'
,
globs
=
{
'ExceptionRaiser1'
:
ExceptionRaiser1
,
'ExceptionRaiser2'
:
ExceptionRaiser2
,
'ExceptionRaiser2'
:
ExceptionRaiser2
,
'ExceptionRaiser3'
:
ExceptionRaiser3
,}),
'ExceptionRaiser3'
:
ExceptionRaiser3
,
}),
])
])
src/ZPublisher/tests/test_mapply.py
View file @
efe61189
...
@@ -11,19 +11,21 @@
...
@@ -11,19 +11,21 @@
# FOR A PARTICULAR PURPOSE.
# FOR A PARTICULAR PURPOSE.
#
#
##############################################################################
##############################################################################
"""Test mapply() function
"""
import
unittest
import
unittest
import
ExtensionClass
import
ExtensionClass
import
Acquisition
import
Acquisition
from
ZPublisher.mapply
import
mapply
from
ZPublisher.mapply
import
mapply
class
MapplyTests
(
unittest
.
TestCase
):
class
MapplyTests
(
unittest
.
TestCase
):
def
testMethod
(
self
):
def
testMethod
(
self
):
def
compute
(
a
,
b
,
c
=
4
):
def
compute
(
a
,
b
,
c
=
4
):
return
'%d%d%d'
%
(
a
,
b
,
c
)
return
'%d%d%d'
%
(
a
,
b
,
c
)
values
=
{
'a'
:
2
,
'b'
:
3
,
'c'
:
5
}
values
=
{
'a'
:
2
,
'b'
:
3
,
'c'
:
5
}
v
=
mapply
(
compute
,
(),
values
)
v
=
mapply
(
compute
,
(),
values
)
self
.
assertEqual
(
v
,
'235'
)
self
.
assertEqual
(
v
,
'235'
)
...
@@ -31,12 +33,16 @@ class MapplyTests(unittest.TestCase):
...
@@ -31,12 +33,16 @@ class MapplyTests(unittest.TestCase):
self
.
assertEqual
(
v
,
'735'
)
self
.
assertEqual
(
v
,
'735'
)
def
testClass
(
self
):
def
testClass
(
self
):
values
=
{
'a'
:
2
,
'b'
:
3
,
'c'
:
5
}
values
=
{
'a'
:
2
,
'b'
:
3
,
'c'
:
5
}
class
c
(
object
):
class
c
(
object
):
a
=
3
a
=
3
def
__call__
(
self
,
b
,
c
=
4
):
def
__call__
(
self
,
b
,
c
=
4
):
return
'%d%d%d'
%
(
self
.
a
,
b
,
c
)
return
'%d%d%d'
%
(
self
.
a
,
b
,
c
)
compute
=
__call__
compute
=
__call__
cc
=
c
()
cc
=
c
()
v
=
mapply
(
cc
,
(),
values
)
v
=
mapply
(
cc
,
(),
values
)
self
.
assertEqual
(
v
,
'335'
)
self
.
assertEqual
(
v
,
'335'
)
...
@@ -91,8 +97,3 @@ class MapplyTests(unittest.TestCase):
...
@@ -91,8 +97,3 @@ class MapplyTests(unittest.TestCase):
ob
=
NoCallButAcquisition
().
__of__
(
Root
())
ob
=
NoCallButAcquisition
().
__of__
(
Root
())
self
.
assertRaises
(
TypeError
,
mapply
,
ob
,
(),
{})
self
.
assertRaises
(
TypeError
,
mapply
,
ob
,
(),
{})
def
test_suite
():
suite
=
unittest
.
TestSuite
()
suite
.
addTest
(
unittest
.
makeSuite
(
MapplyTests
))
return
suite
src/ZPublisher/tests/test_xmlrpc.py
View file @
efe61189
import
unittest
import
unittest
from
DateTime
import
DateTime
from
DateTime
import
DateTime
class
FauxResponse
:
class
FauxResponse
:
def
__init__
(
self
):
def
__init__
(
self
):
...
@@ -16,10 +17,12 @@ class FauxResponse:
...
@@ -16,10 +17,12 @@ class FauxResponse:
def
setStatus
(
self
,
status
):
def
setStatus
(
self
,
status
):
self
.
_status
=
status
self
.
_status
=
status
class
FauxInstance
:
class
FauxInstance
:
def
__init__
(
self
,
**
kw
):
def
__init__
(
self
,
**
kw
):
self
.
__dict__
.
update
(
kw
)
self
.
__dict__
.
update
(
kw
)
class
XMLRPCResponseTests
(
unittest
.
TestCase
):
class
XMLRPCResponseTests
(
unittest
.
TestCase
):
def
_getTargetClass
(
self
):
def
_getTargetClass
(
self
):
...
@@ -87,7 +90,8 @@ class XMLRPCResponseTests(unittest.TestCase):
...
@@ -87,7 +90,8 @@ class XMLRPCResponseTests(unittest.TestCase):
def
test_instanceattribute_recursive
(
self
):
def
test_instanceattribute_recursive
(
self
):
# Instance "flattening" should work recursively, ad infinitum
# Instance "flattening" should work recursively, ad infinitum
import
xmlrpclib
import
xmlrpclib
body
=
FauxInstance
(
public
=
FauxInstance
(
public
=
FauxInstance
(
_secret
=
'abc'
,
public
=
'def'
)))
body
=
FauxInstance
(
public
=
FauxInstance
(
public
=
FauxInstance
(
_secret
=
'abc'
,
public
=
'def'
)))
faux
=
FauxResponse
()
faux
=
FauxResponse
()
response
=
self
.
_makeOne
(
faux
)
response
=
self
.
_makeOne
(
faux
)
response
.
setBody
(
body
)
response
.
setBody
(
body
)
...
@@ -148,7 +152,8 @@ class XMLRPCResponseTests(unittest.TestCase):
...
@@ -148,7 +152,8 @@ class XMLRPCResponseTests(unittest.TestCase):
def
test_zopedatetimeattribute_recursive
(
self
):
def
test_zopedatetimeattribute_recursive
(
self
):
# DateTime encoding should work recursively
# DateTime encoding should work recursively
import
xmlrpclib
import
xmlrpclib
body
=
FauxInstance
(
public
=
FauxInstance
(
public
=
DateTime
(
'2006-05-24 07:00:00 GMT+0'
)))
body
=
FauxInstance
(
public
=
FauxInstance
(
public
=
DateTime
(
'2006-05-24 07:00:00 GMT+0'
)))
faux
=
FauxResponse
()
faux
=
FauxResponse
()
response
=
self
.
_makeOne
(
faux
)
response
=
self
.
_makeOne
(
faux
)
response
.
setBody
(
body
)
response
.
setBody
(
body
)
...
@@ -185,7 +190,10 @@ class XMLRPCResponseTests(unittest.TestCase):
...
@@ -185,7 +190,10 @@ class XMLRPCResponseTests(unittest.TestCase):
# Cannot marshal functions or methods, obviously
# Cannot marshal functions or methods, obviously
import
sys
import
sys
import
xmlrpclib
import
xmlrpclib
def
foo
():
pass
def
foo
():
pass
body
=
FauxInstance
(
public
=
foo
)
body
=
FauxInstance
(
public
=
foo
)
faux
=
FauxResponse
()
faux
=
FauxResponse
()
response
=
self
.
_makeOne
(
faux
)
response
=
self
.
_makeOne
(
faux
)
...
@@ -208,7 +216,3 @@ class XMLRPCResponseTests(unittest.TestCase):
...
@@ -208,7 +216,3 @@ class XMLRPCResponseTests(unittest.TestCase):
data
,
method
=
xmlrpclib
.
loads
(
faux
.
_body
)
data
,
method
=
xmlrpclib
.
loads
(
faux
.
_body
)
data
=
data
[
0
]
data
=
data
[
0
]
self
.
assertEqual
(
data
,
{
''
:
True
})
self
.
assertEqual
(
data
,
{
''
:
True
})
def
test_suite
():
return
unittest
.
TestSuite
((
unittest
.
makeSuite
(
XMLRPCResponseTests
),))
src/ZPublisher/tests/testpubevents.py
View file @
efe61189
from
StringIO
import
StringIO
from
StringIO
import
StringIO
from
sys
import
modules
,
exc_info
from
sys
import
modules
,
exc_info
from
unittest
import
TestCase
,
TestSuite
,
makeSuite
,
main
from
unittest
import
TestCase
from
ZODB.POSException
import
ConflictError
from
ZODB.POSException
import
ConflictError
from
zope.interface.verify
import
verifyObject
from
zope.interface.verify
import
verifyObject
...
@@ -9,19 +9,24 @@ from zope.event import subscribers
...
@@ -9,19 +9,24 @@ from zope.event import subscribers
from
ZPublisher.Publish
import
publish
,
Retry
from
ZPublisher.Publish
import
publish
,
Retry
from
ZPublisher.BaseRequest
import
BaseRequest
from
ZPublisher.BaseRequest
import
BaseRequest
from
ZPublisher.HTTPResponse
import
HTTPResponse
from
ZPublisher.HTTPResponse
import
HTTPResponse
from
ZPublisher.pubevents
import
PubStart
,
PubSuccess
,
PubFailure
,
\
from
ZPublisher.pubevents
import
(
PubAfterTraversal
,
PubBeforeCommit
,
PubBeforeAbort
,
\
PubStart
,
PubSuccess
,
PubFailure
,
PubBeforeStreaming
PubAfterTraversal
,
PubBeforeCommit
,
PubBeforeAbort
,
from
ZPublisher.interfaces
import
\
PubBeforeStreaming
,
IPubStart
,
IPubEnd
,
IPubSuccess
,
IPubFailure
,
\
)
IPubAfterTraversal
,
IPubBeforeCommit
,
\
from
ZPublisher.interfaces
import
(
IPubBeforeStreaming
IPubStart
,
IPubEnd
,
IPubSuccess
,
IPubFailure
,
IPubAfterTraversal
,
IPubBeforeCommit
,
IPubBeforeStreaming
,
)
PUBMODULE
=
'TEST_testpubevents'
PUBMODULE
=
'TEST_testpubevents'
_g
=
globals
()
_g
=
globals
()
class
TestInterface
(
TestCase
):
class
TestInterface
(
TestCase
):
def
testPubStart
(
self
):
def
testPubStart
(
self
):
verifyObject
(
IPubStart
,
PubStart
(
_Request
()))
verifyObject
(
IPubStart
,
PubStart
(
_Request
()))
...
@@ -32,8 +37,10 @@ class TestInterface(TestCase):
...
@@ -32,8 +37,10 @@ class TestInterface(TestCase):
def
testPubFailure
(
self
):
def
testPubFailure
(
self
):
# get some exc info
# get some exc info
try
:
raise
ValueError
()
try
:
except
:
exc
=
exc_info
()
raise
ValueError
()
except
Exception
:
exc
=
exc_info
()
e
=
PubFailure
(
_Request
(),
exc
,
False
)
e
=
PubFailure
(
_Request
(),
exc
,
False
)
verifyObject
(
IPubFailure
,
e
)
verifyObject
(
IPubFailure
,
e
)
verifyObject
(
IPubEnd
,
e
)
verifyObject
(
IPubEnd
,
e
)
...
@@ -50,6 +57,7 @@ class TestInterface(TestCase):
...
@@ -50,6 +57,7 @@ class TestInterface(TestCase):
e
=
PubBeforeStreaming
(
_Response
())
e
=
PubBeforeStreaming
(
_Response
())
verifyObject
(
IPubBeforeStreaming
,
e
)
verifyObject
(
IPubBeforeStreaming
,
e
)
class
TestPubEvents
(
TestCase
):
class
TestPubEvents
(
TestCase
):
def
setUp
(
self
):
def
setUp
(
self
):
self
.
_saved_subscribers
=
subscribers
[:]
self
.
_saved_subscribers
=
subscribers
[:]
...
@@ -59,11 +67,13 @@ class TestPubEvents(TestCase):
...
@@ -59,11 +67,13 @@ class TestPubEvents(TestCase):
self
.
request
=
_Request
()
self
.
request
=
_Request
()
def
tearDown
(
self
):
def
tearDown
(
self
):
if
PUBMODULE
in
modules
:
del
modules
[
PUBMODULE
]
if
PUBMODULE
in
modules
:
del
modules
[
PUBMODULE
]
subscribers
[:]
=
self
.
_saved_subscribers
subscribers
[:]
=
self
.
_saved_subscribers
def
testSuccess
(
self
):
def
testSuccess
(
self
):
r
=
self
.
request
;
r
.
action
=
'succeed'
r
=
self
.
request
r
.
action
=
'succeed'
publish
(
r
,
PUBMODULE
,
[
None
])
publish
(
r
,
PUBMODULE
,
[
None
])
events
=
self
.
reporter
.
events
events
=
self
.
reporter
.
events
self
.
assertEqual
(
len
(
events
),
4
)
self
.
assertEqual
(
len
(
events
),
4
)
...
@@ -78,7 +88,8 @@ class TestPubEvents(TestCase):
...
@@ -78,7 +88,8 @@ class TestPubEvents(TestCase):
self
.
assertEqual
(
events
[
2
].
request
,
r
)
self
.
assertEqual
(
events
[
2
].
request
,
r
)
def
testFailureReturn
(
self
):
def
testFailureReturn
(
self
):
r
=
self
.
request
;
r
.
action
=
'fail_return'
r
=
self
.
request
r
.
action
=
'fail_return'
publish
(
r
,
PUBMODULE
,
[
None
])
publish
(
r
,
PUBMODULE
,
[
None
])
events
=
self
.
reporter
.
events
events
=
self
.
reporter
.
events
self
.
assertEqual
(
len
(
events
),
3
)
self
.
assertEqual
(
len
(
events
),
3
)
...
@@ -93,7 +104,8 @@ class TestPubEvents(TestCase):
...
@@ -93,7 +104,8 @@ class TestPubEvents(TestCase):
self
.
assertEqual
(
len
(
events
[
2
].
exc_info
),
3
)
self
.
assertEqual
(
len
(
events
[
2
].
exc_info
),
3
)
def
testFailureException
(
self
):
def
testFailureException
(
self
):
r
=
self
.
request
;
r
.
action
=
'fail_exception'
r
=
self
.
request
r
.
action
=
'fail_exception'
self
.
assertRaises
(
Exception
,
publish
,
r
,
PUBMODULE
,
[
None
])
self
.
assertRaises
(
Exception
,
publish
,
r
,
PUBMODULE
,
[
None
])
events
=
self
.
reporter
.
events
events
=
self
.
reporter
.
events
self
.
assertEqual
(
len
(
events
),
3
)
self
.
assertEqual
(
len
(
events
),
3
)
...
@@ -109,7 +121,8 @@ class TestPubEvents(TestCase):
...
@@ -109,7 +121,8 @@ class TestPubEvents(TestCase):
self
.
assertEqual
(
len
(
events
[
2
].
exc_info
),
3
)
self
.
assertEqual
(
len
(
events
[
2
].
exc_info
),
3
)
def
testFailureConflict
(
self
):
def
testFailureConflict
(
self
):
r
=
self
.
request
;
r
.
action
=
'conflict'
r
=
self
.
request
r
.
action
=
'conflict'
publish
(
r
,
PUBMODULE
,
[
None
])
publish
(
r
,
PUBMODULE
,
[
None
])
events
=
self
.
reporter
.
events
events
=
self
.
reporter
.
events
self
.
assertEqual
(
len
(
events
),
7
)
self
.
assertEqual
(
len
(
events
),
7
)
...
@@ -135,7 +148,6 @@ class TestPubEvents(TestCase):
...
@@ -135,7 +148,6 @@ class TestPubEvents(TestCase):
self
.
assert_
(
isinstance
(
events
[
6
],
PubSuccess
))
self
.
assert_
(
isinstance
(
events
[
6
],
PubSuccess
))
def
testStreaming
(
self
):
def
testStreaming
(
self
):
out
=
StringIO
()
out
=
StringIO
()
response
=
HTTPResponse
(
stdout
=
out
)
response
=
HTTPResponse
(
stdout
=
out
)
response
.
write
(
'datachunk1'
)
response
.
write
(
'datachunk1'
)
...
@@ -149,19 +161,26 @@ class TestPubEvents(TestCase):
...
@@ -149,19 +161,26 @@ class TestPubEvents(TestCase):
self
.
assertTrue
(
'datachunk1datachunk2'
in
out
.
getvalue
())
self
.
assertTrue
(
'datachunk1datachunk2'
in
out
.
getvalue
())
# Auxiliaries
def
_succeed
():
def
_succeed
():
''' '''
''' '''
return
'success'
return
'success'
class
_Application
(
object
):
pass
class
_Application
(
object
):
pass
class
_Reporter
(
object
):
class
_Reporter
(
object
):
def
__init__
(
self
):
self
.
events
=
[]
def
__init__
(
self
):
def
__call__
(
self
,
event
):
self
.
events
.
append
(
event
)
self
.
events
=
[]
def
__call__
(
self
,
event
):
self
.
events
.
append
(
event
)
class
_Response
(
object
):
class
_Response
(
object
):
def
setBody
(
*
unused
):
pass
def
setBody
(
*
unused
):
pass
class
_Request
(
BaseRequest
):
class
_Request
(
BaseRequest
):
...
@@ -174,7 +193,9 @@ class _Request(BaseRequest):
...
@@ -174,7 +193,9 @@ class _Request(BaseRequest):
self
[
'PATH_INFO'
]
=
self
[
'URL'
]
=
''
self
[
'PATH_INFO'
]
=
self
[
'URL'
]
=
''
self
.
steps
=
[]
self
.
steps
=
[]
def
supports_retry
(
self
):
return
True
def
supports_retry
(
self
):
return
True
def
retry
(
self
):
def
retry
(
self
):
r
=
self
.
__class__
()
r
=
self
.
__class__
()
r
.
action
=
'succeed'
r
.
action
=
'succeed'
...
@@ -182,25 +203,29 @@ class _Request(BaseRequest):
...
@@ -182,25 +203,29 @@ class _Request(BaseRequest):
def
traverse
(
self
,
*
unused
,
**
unused_kw
):
def
traverse
(
self
,
*
unused
,
**
unused_kw
):
action
=
self
.
action
action
=
self
.
action
if
action
.
startswith
(
'fail'
):
raise
Exception
(
action
)
if
action
.
startswith
(
'fail'
):
if
action
==
'conflict'
:
raise
ConflictError
()
raise
Exception
(
action
)
if
action
==
'succeed'
:
return
_succeed
if
action
==
'conflict'
:
else
:
raise
ValueError
(
'unknown action: %s'
%
action
)
raise
ConflictError
()
if
action
==
'succeed'
:
return
_succeed
else
:
raise
ValueError
(
'unknown action: %s'
%
action
)
def
close
(
self
):
# override to get rid of the 'EndRequestEvent' notification
# override to get rid of the 'EndRequestEvent' notification
def
close
(
self
):
pass
pass
# define things necessary for publication
# define things necessary for publication
bobo_application
=
_Application
()
bobo_application
=
_Application
()
def
zpublisher_exception_hook
(
parent
,
request
,
*
unused
):
def
zpublisher_exception_hook
(
parent
,
request
,
*
unused
):
action
=
request
.
action
action
=
request
.
action
if
action
==
'fail_return'
:
return
0
if
action
==
'fail_return'
:
if
action
==
'fail_exception'
:
raise
Exception
()
return
0
if
action
==
'conflict'
:
raise
Retry
()
if
action
==
'fail_exception'
:
raise
Exception
()
if
action
==
'conflict'
:
raise
Retry
()
raise
ValueError
(
'unknown action: %s'
%
action
)
raise
ValueError
(
'unknown action: %s'
%
action
)
def
test_suite
():
return
TestSuite
((
makeSuite
(
c
)
for
c
in
(
TestPubEvents
,
TestInterface
)))
src/ZPublisher/xmlrpc.py
View file @
efe61189
...
@@ -33,6 +33,7 @@ from ZODB.POSException import ConflictError
...
@@ -33,6 +33,7 @@ from ZODB.POSException import ConflictError
from
DateTime.DateTime
import
DateTime
from
DateTime.DateTime
import
DateTime
WRAPPERS
=
xmlrpclib
.
WRAPPERS
+
(
DateTime
,
)
WRAPPERS
=
xmlrpclib
.
WRAPPERS
+
(
DateTime
,
)
def
dump_instance
(
self
,
value
,
write
):
def
dump_instance
(
self
,
value
,
write
):
# Check for special wrappers
# Check for special wrappers
if
value
.
__class__
in
WRAPPERS
:
if
value
.
__class__
in
WRAPPERS
:
...
@@ -95,6 +96,7 @@ def parse_input(data):
...
@@ -95,6 +96,7 @@ def parse_input(data):
########################################################################
########################################################################
# Possible implementation helpers:
# Possible implementation helpers:
class
Response
:
class
Response
:
"""Customized Response that handles XML-RPC-specific details.
"""Customized Response that handles XML-RPC-specific details.
...
@@ -115,16 +117,22 @@ class Response:
...
@@ -115,16 +117,22 @@ class Response:
# we have to use delegation, rather than inheritance to do the
# we have to use delegation, rather than inheritance to do the
# customization.
# customization.
def
__init__
(
self
,
real
):
self
.
__dict__
[
'_real'
]
=
real
def
__init__
(
self
,
real
):
self
.
__dict__
[
'_real'
]
=
real
def
__getattr__
(
self
,
name
):
return
getattr
(
self
.
_real
,
name
)
def
__getattr__
(
self
,
name
):
return
getattr
(
self
.
_real
,
name
)
def
__setattr__
(
self
,
name
,
v
):
def
__setattr__
(
self
,
name
,
v
):
return
setattr
(
self
.
_real
,
name
,
v
)
return
setattr
(
self
.
_real
,
name
,
v
)
def
__delattr__
(
self
,
name
):
return
delattr
(
self
.
_real
,
name
)
def
__delattr__
(
self
,
name
):
return
delattr
(
self
.
_real
,
name
)
def
setBody
(
self
,
body
,
title
=
''
,
is_error
=
0
,
bogus_str_search
=
None
):
def
setBody
(
self
,
body
,
title
=
''
,
is_error
=
0
,
bogus_str_search
=
None
):
if
isinstance
(
body
,
xmlrpclib
.
Fault
):
if
isinstance
(
body
,
xmlrpclib
.
Fault
):
# Convert Fault object to XML-RPC response.
# Convert Fault object to XML-RPC response.
body
=
xmlrpclib
.
dumps
(
body
,
methodresponse
=
1
,
allow_none
=
True
)
body
=
xmlrpclib
.
dumps
(
body
,
methodresponse
=
1
,
allow_none
=
True
)
else
:
else
:
# Marshall our body as an XML-RPC response. Strings will be sent
# Marshall our body as an XML-RPC response. Strings will be sent
# strings, integers as integers, etc. We do *not* convert
# strings, integers as integers, etc. We do *not* convert
...
@@ -161,8 +169,8 @@ class Response:
...
@@ -161,8 +169,8 @@ class Response:
return
self
.
_real
.
exception
(
fatal
=
fatal
,
info
=
info
)
return
self
.
_real
.
exception
(
fatal
=
fatal
,
info
=
info
)
# Create an appropriate Fault object. Containing error information
# Create an appropriate Fault object. Containing error information
Fault
=
xmlrpclib
.
Fault
Fault
=
xmlrpclib
.
Fault
f
=
None
f
=
None
try
:
try
:
# Strip HTML tags from the error value
# Strip HTML tags from the error value
vstr
=
str
(
v
)
vstr
=
str
(
v
)
...
@@ -175,15 +183,15 @@ class Response:
...
@@ -175,15 +183,15 @@ class Response:
else
:
else
:
value
=
'%s - %s'
%
(
t
,
vstr
)
value
=
'%s - %s'
%
(
t
,
vstr
)
if
isinstance
(
v
,
Fault
):
if
isinstance
(
v
,
Fault
):
f
=
v
f
=
v
elif
isinstance
(
v
,
Exception
):
elif
isinstance
(
v
,
Exception
):
f
=
Fault
(
-
1
,
'Unexpected Zope exception: %s'
%
value
)
f
=
Fault
(
-
1
,
'Unexpected Zope exception: %s'
%
value
)
else
:
else
:
f
=
Fault
(
-
2
,
'Unexpected Zope error value: %s'
%
value
)
f
=
Fault
(
-
2
,
'Unexpected Zope error value: %s'
%
value
)
except
ConflictError
:
except
ConflictError
:
raise
raise
except
:
except
Exception
:
f
=
Fault
(
-
3
,
"Unknown Zope fault type"
)
f
=
Fault
(
-
3
,
"Unknown Zope fault type"
)
# Do the damage.
# Do the damage.
self
.
setBody
(
f
)
self
.
setBody
(
f
)
...
@@ -191,4 +199,4 @@ class Response:
...
@@ -191,4 +199,4 @@ class Response:
return
tb
return
tb
response
=
Response
response
=
Response
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