Commit efe61189 authored by Hanno Schlichting's avatar Hanno Schlichting

flake8 ZPublisher/Testing

parent 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".
...@@ -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)
...@@ -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)
...@@ -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',
] ]
# 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__
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)
......
##############################################################################
#
# 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
...@@ -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)
...@@ -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
...@@ -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.
......
This diff is collapsed.
...@@ -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()
...@@ -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)
This diff is collapsed.
...@@ -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, TupleType)): if isinstance(v, (list, tuple)):
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, TupleType)): if isinstance(v, (list, tuple)):
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, TupleType)): if isinstance(v, (list, tuple)):
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, TupleType)): if isinstance(v, (list, tuple)):
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
...@@ -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.
""" """
This diff is collapsed.
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
This diff is collapsed.
...@@ -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',
)
...@@ -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',
)
...@@ -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)
...@@ -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.
""" """
...@@ -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)
...@@ -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
...@@ -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
""" """
......
## 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
This diff is collapsed.
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)
...@@ -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()')
This diff is collapsed.
This diff is collapsed.
...@@ -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
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), ) )
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()
...@@ -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\ndef\nghi' to_convert = 'abc\ndef\nghi'
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\ndef\nghi' to_convert = u'abc\ndef\nghi'
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),))
...@@ -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,
}),
]) ])
...@@ -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
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment