Skip to content

Commit

Permalink
Merge elro-remove-request-container branch into elro-parent-pointers …
Browse files Browse the repository at this point in the history
…branch
  • Loading branch information
lrowe committed Oct 31, 2011
1 parent 0800e7f commit c805474
Show file tree
Hide file tree
Showing 13 changed files with 115 additions and 57 deletions.
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@
'zope.deferredimport',
'zope.event',
'zope.exceptions',
'zope.globalrequest',
'zope.i18n [zcml]',
'zope.i18nmessageid',
'zope.interface',
Expand Down
1 change: 1 addition & 0 deletions sources.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ tempstorage = svn ${buildout:svn-zope-org}/tempstorage/trunk
zExceptions = svn ${buildout:svn-zope-org}/zExceptions/trunk
zLOG = svn ${buildout:svn-zope-org}/zLOG/trunk
ZopeUndo = svn ${buildout:svn-zope-org}/ZopeUndo/trunk
zope.globalrequest = svn ^/zope.globalrequest/trunk

# Deprecated / CMF dependencies
Products.BTreeFolder2 = svn ${buildout:svn-zope-org}/Products.BTreeFolder2/trunk
Expand Down
30 changes: 29 additions & 1 deletion src/OFS/Application.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
from webdav.NullResource import NullResource
from zExceptions import Redirect as RedirectException, Forbidden

from zope.globalrequest import getRequest
from zope.interface import implements

import Folder
Expand Down Expand Up @@ -85,7 +86,7 @@ def __init__(self):
def getId(self):
try:
return self.REQUEST['SCRIPT_NAME'][1:]
except (KeyError, TypeError):
except (KeyError, TypeError, AttributeError):
return self.title

def title_and_id(self):
Expand Down Expand Up @@ -184,6 +185,33 @@ def getPhysicalPath(self):
# We're at the base of the path.
return ('', )

@property
def REQUEST(self):
# Return the current request
request = self.__dict__.get('REQUEST', None)
if request is None:
request = getRequest()
if request is None:
raise AttributeError('REQUEST')
return request

@REQUEST.setter
def REQUEST(self, value):
# Set the current request as an attribute (used in tests)
self.__dict__['REQUEST'] = value

@REQUEST.deleter
def REQUEST(self):
del self.__dict__['REQUEST']

@property
def aq_explicit(self):
# aq_explict is a property of acquisition wrappers. As the Application
# object is no longer wrapped in a RequestContainer, it must be
# supported directly.
return self


InitializeClass(Application)


Expand Down
6 changes: 2 additions & 4 deletions src/Products/Five/browser/tests/aqlegacy_ftest.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,15 @@ views still works (the printed output is the aq_chain of the view):
>>> print browser.contents
[<Products.Five.metaclass.LegacyAttributes object at ...>,
<Folder at /test_folder_1_>,
<Application at >,
<ZPublisher.BaseRequest.RequestContainer object at ...>]
<Application at >]

The same goes for browser views that just mix in Acquisition.Explicit:

>>> browser.open('http://localhost/test_folder_1_/explicitattributes')
>>> print browser.contents
[<Products.Five.metaclass.ExplicitLegacyAttributes object at ...>,
<Folder at /test_folder_1_>,
<Application at >,
<ZPublisher.BaseRequest.RequestContainer object at ...>]
<Application at >]

Let's do some more manual tests with the view object. But first we
must get it:
Expand Down
8 changes: 7 additions & 1 deletion src/Testing/ZopeTestCase/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import connections
import layer

from zope.globalrequest import setRequest, clearRequest
from zope.interface import implements
from AccessControl.SecurityManagement import noSecurityManager

Expand Down Expand Up @@ -106,7 +107,11 @@ def tearDown(self):

def _app(self):
'''Returns the app object for a test.'''
return app()
app = Zope2.app()
req = utils.newrequest()
setRequest(req)
connections.register(app)
return app

def _setup(self):
'''Sets up the fixture. Framework authors may
Expand All @@ -120,6 +125,7 @@ def _clear(self, call_close_hook=0):
self.beforeClose()
self._close()
self.logout()
clearRequest()
self.afterClear()

def _close(self):
Expand Down
27 changes: 16 additions & 11 deletions src/Testing/ZopeTestCase/connections.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,12 @@ def __init__(self):
self._conns = []

def register(self, conn):
self._conns.append(conn)
connset = self._getConnSet(conn)
self._conns.append(connset)

def contains(self, conn):
return conn in self._conns
connset = self._getConnSet(conn)
return connset in self._conns

def __len__(self):
return len(self._conns)
Expand All @@ -37,22 +39,25 @@ def count(self):
return len(self)

def close(self, conn):
connset = self._getConnSet(conn)
if self.contains(conn):
self._conns.remove(conn)
self._do_close(conn)
self._conns.remove(connset)
self._do_close(connset)

def closeAll(self):
for conn in self._conns:
self._do_close(conn)
for connset in self._conns:
self._do_close(connset)
self._conns = []

def _do_close(self, conn):
if hasattr(conn, 'close'):
def _do_close(self, connset):
for conn in connset:
conn.close()
else:
conn.REQUEST.close()
conn._p_jar.close()

def _getConnSet(self, conn):
if hasattr(conn, '_p_jar'):
return (conn.REQUEST, conn._p_jar)
else:
return (conn,)

registry = ConnectionRegistry()
register = registry.register
Expand Down
4 changes: 3 additions & 1 deletion src/Testing/ZopeTestCase/functional.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,16 @@ def savestate(func):
from AccessControl.SecurityManagement import setSecurityManager
from zope.site.hooks import getSite
from zope.site.hooks import setSite
from zope.globalrequest import getRequest, setRequest

def wrapped_func(*args, **kw):
sm, site = getSecurityManager(), getSite()
sm, site, request = getSecurityManager(), getSite(), getRequest()
try:
return func(*args, **kw)
finally:
setSecurityManager(sm)
setSite(site)
setRequest(request)
return wrapped_func


Expand Down
6 changes: 5 additions & 1 deletion src/Testing/ZopeTestCase/sandbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
import utils
import connections

from zope.globalrequest import setRequest, clearRequest


class Sandboxed:
'''Derive from this class and an xTestCase to make each test
Expand All @@ -32,7 +34,8 @@ def _app(self):
'''Returns the app object for a test.'''
app = Zope2.app(Zope2.sandbox().open())
AppZapper().set(app)
app = utils.makerequest(app)
req = utils.newrequest()
setRequest(req)
connections.register(app)
return app

Expand All @@ -41,6 +44,7 @@ def _close(self):
AppZapper().clear()
transaction.abort()
connections.closeAll()
clearRequest()


class AppZapper:
Expand Down
11 changes: 11 additions & 0 deletions src/Testing/ZopeTestCase/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,16 @@ def makerequest(app, stdout=sys.stdout):
return _makerequest(app, stdout=stdout, environ=environ)


def newrequest(stdout=sys.stdout):
'''Creates a new request for testing'''
from Testing.makerequest import newrequest as _newrequest
environ = {}
environ['SERVER_NAME'] = _Z2HOST or 'nohost'
environ['SERVER_PORT'] = '%d' % (_Z2PORT or 80)
environ['REQUEST_METHOD'] = 'GET'
return _newrequest(stdout=stdout, environ=environ)


def appcall(func, *args, **kw):
'''Calls a function passing 'app' as first argument.'''
from base import app, close
Expand Down Expand Up @@ -150,6 +160,7 @@ def makelist(arg):
'importObjectFromFile',
'appcall',
'makerequest',
'newrequest',
'makelist',
]

51 changes: 35 additions & 16 deletions src/Testing/makerequest.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,40 @@
from sys import stdin, stdout
from ZPublisher.HTTPRequest import HTTPRequest
from ZPublisher.HTTPResponse import HTTPResponse
from ZPublisher.BaseRequest import RequestContainer
from ExtensionClass import Base

class RequestContainer(Base):
__roles__=None
def __init__(self,**kw):
for k,v in kw.items(): self.__dict__[k]=v


def newrequest(stdout=stdout, environ=None):
"""
Creates a new request for testing.
*stdout* is an optional file-like object and is used by
REQUEST.RESPONSE. The default is sys.stdout.
*environ* is an optional mapping to be used in the request.
Default is a fresh dictionary. Passing os.environ is not
recommended; tests should not pollute the real os.environ.
"""
if environ is None:
environ = {}
resp = HTTPResponse(stdout=stdout)
environ.setdefault('SERVER_NAME', 'foo')
environ.setdefault('SERVER_PORT', '80')
environ.setdefault('REQUEST_METHOD', 'GET')
req = HTTPRequest(stdin, environ, resp)
req._steps = ['noobject'] # Fake a published object.
req['ACTUAL_URL'] = req.get('URL') # Zope 2.7.4

# set Zope3-style default skin so that the request is usable for
# Zope3-style view look-ups.
from zope.publisher.browser import setDefaultSkin
setDefaultSkin(req)
return req

def makerequest(app, stdout=stdout, environ=None):
"""
Expand Down Expand Up @@ -47,20 +80,6 @@ def makerequest(app, stdout=stdout, environ=None):
Default is a fresh dictionary. Passing os.environ is not
recommended; tests should not pollute the real os.environ.
"""
if environ is None:
environ = {}
resp = HTTPResponse(stdout=stdout)
environ.setdefault('SERVER_NAME', 'foo')
environ.setdefault('SERVER_PORT', '80')
environ.setdefault('REQUEST_METHOD', 'GET')
req = HTTPRequest(stdin, environ, resp)
req._steps = ['noobject'] # Fake a published object.
req['ACTUAL_URL'] = req.get('URL') # Zope 2.7.4

# set Zope3-style default skin so that the request is usable for
# Zope3-style view look-ups.
from zope.publisher.browser import setDefaultSkin
setDefaultSkin(req)

req = newrequest(stdout, environ)
requestcontainer = RequestContainer(REQUEST = req)
return app.__of__(requestcontainer)
21 changes: 0 additions & 21 deletions src/ZPublisher/BaseRequest.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,23 +40,6 @@ def quote(text):
# quote url path segments, but leave + and @ intact
return urllib_quote(text, '/+@')

try:
from ExtensionClass import Base
from ZPublisher.Converters import type_converters
class RequestContainer(Base):
__roles__=None
def __init__(self,**kw):
for k,v in kw.items(): self.__dict__[k]=v

def manage_property_types(self):
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:
Expand Down Expand Up @@ -411,10 +394,6 @@ def traverse(self, path, response=None, validated_hook=None):
return response.forbiddenError(self['URL'])

# Traverse the URL to find the object:
if hasattr(object, '__of__'):
# Try to bind the top-level object to the request
# This is how you get 'self.REQUEST'
object=object.__of__(RequestContainer(REQUEST=request))
parents.append(object)

steps=self.steps
Expand Down
5 changes: 4 additions & 1 deletion src/ZPublisher/Publish.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from zope.publisher.interfaces.browser import IBrowserPage
from zope.publisher.skinnable import setDefaultSkin
from zope.security.management import newInteraction, endInteraction
from zope.globalrequest import setRequest, clearRequest

from .mapply import mapply
from .maybe_lock import allocate_lock
Expand Down Expand Up @@ -237,13 +238,14 @@ def publish_module_standard(module_name,

if request is None:
request=Request(stdin, environ, response)

# make sure that the request we hand over has the
# default layer/skin set on it; subsequent code that
# wants to look up views will likely depend on it
if ISkinnable.providedBy(request):
setDefaultSkin(request)

setRequest(request)
response = publish(request, module_name, after_list, debug=debug)
except (SystemExit, ImportError):
# XXX: Rendered ImportErrors were never caught here because they
Expand Down Expand Up @@ -271,6 +273,7 @@ def publish_module_standard(module_name,
if after_list[0] is not None: after_list[0]()

finally:
clearRequest()
if request is not None: request.close()

if must_die:
Expand Down
1 change: 1 addition & 0 deletions versions.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,5 @@ python-gettext = 1.1.1
repoze.retry = 1.0
repoze.tm2 = 1.0b1
repoze.who = 2.0b1
zope.globalrequest = 1.0
zope.testbrowser = 3.11.1

0 comments on commit c805474

Please sign in to comment.