Commit 3383137a authored by Bryton Lacquement's avatar Bryton Lacquement 🚪 Committed by Julien Muchembled

Localizer: replace the 'Global Request' monkey-patch with zope.globalrequest

zope.globalrequest is a new dependency of Zope 4
and it is already used by the backported WSGIPublisher.
parent f33ea934
......@@ -60,12 +60,7 @@ import transaction
from App.config import getConfiguration
from Shared.DC.ZRDB.Results import Results
import Products.Localizer.patches
localizer_lock = Products.Localizer.patches._requests_lock
localizer_contexts = Products.Localizer.patches._requests
LocalizerContext = lambda request: request
from zope.globalrequest import getRequest, setRequest
from Products.MailHost.MailHost import MailHostError
from zLOG import LOG, INFO, WARNING, ERROR
......@@ -1464,7 +1459,7 @@ class ActivityTool (BaseTool):
def invoke(self, message):
if self.activity_tracking:
activity_tracking_logger.info('invoking message: object_path=%s, method_id=%s, args=%r, kw=%r, activity_kw=%r, user_name=%s' % ('/'.join(message.object_path), message.method_id, message.args, message.kw, message.activity_kw, message.user_name))
old_localizer_context = False
old_request = None
if getattr(self, 'aq_chain', None) is not None:
# Grab existing acquisition chain and extrach base objects.
base_chain = [aq_base(x) for x in self.aq_chain]
......@@ -1500,16 +1495,8 @@ class ActivityTool (BaseTool):
new_request.other['VirtualRootPhysicalPath'] = request_info['VirtualRootPhysicalPath']
if 'HTTP_ACCEPT_LANGUAGE' in request_info:
new_request.environ['HTTP_ACCEPT_LANGUAGE'] = request_info['HTTP_ACCEPT_LANGUAGE']
# Replace Localizer/iHotfix Context, saving existing one
localizer_context = LocalizerContext(new_request)
id = get_ident()
localizer_lock.acquire()
try:
old_localizer_context = localizer_contexts.get(id)
localizer_contexts[id] = localizer_context
finally:
localizer_lock.release()
# Execute Localizer/iHotfix "patch 2"
old_request = getRequest()
setRequest(new_request)
new_request.processInputs()
new_request_container = request_container.__class__(REQUEST=new_request)
......@@ -1528,17 +1515,7 @@ class ActivityTool (BaseTool):
# Restore default skin selection
skinnable = self.getPortalObject()
skinnable.changeSkin(skinnable.getSkinNameFromRequest(request))
if old_localizer_context is not False:
# Restore Localizer/iHotfix context
id = get_ident()
localizer_lock.acquire()
try:
if old_localizer_context is None:
del localizer_contexts[id]
else:
localizer_contexts[id] = old_localizer_context
finally:
localizer_lock.release()
setRequest(old_request)
if self.activity_tracking:
activity_tracking_logger.info('invoked message')
if my_self is not self: # We rewrapped self
......
......@@ -38,19 +38,7 @@ from App.class_init import default__class_init__, ApplicationDefaultPermissions
# Nicer alias for class initializer.
InitializeClass = default__class_init__
##########################################
# Localizer is not always loaded prior to ERP5 products,
# thus, as Localizer is supposed to patch Global to add get_request to it,
# we prefer to redefine get_request inside ERP5Type/Utils,
# to avoid the case when Global wasn't patched and get_request is not available.
# This is specially important on Zope 2.12 where Globals doesn't even exist.
##########################################
try:
import Products.iHotfix
get_request = Products.iHotfix.get_request
except (ImportError, AttributeError):
import Products.Localizer
get_request = Products.Localizer.get_request
from zope.globalrequest import getRequest as get_request
# Persistency stuff also hasn't moved much from Zope 2.8, although the old
# "Persistence" module remains there for ancient backward compatibility.
......
......@@ -30,7 +30,7 @@
ERP5Type is provides a RAD environment for Zope / CMF
All ERP5 classes derive from ERP5Type
"""
from patches import python, pylint
from patches import python, pylint, globalrequest
from zLOG import LOG, INFO
DISPLAY_BOOT_PROCESS = False
......
try:
import zope.globalrequest
except ImportError:
import sys
sys.modules['zope.globalrequest'] = sys.modules[__name__]
from threading import local
localData = local()
def getRequest():
return getattr(localData, 'request', None)
def setRequest(request):
localData.request = request
def clearRequest():
setRequest(None)
......@@ -31,7 +31,6 @@ import os
import sys
import imp
import re
import thread
from Testing import ZopeTestCase
from Testing.ZopeTestCase import PortalTestCase, user_name
......@@ -97,10 +96,9 @@ class ERP5TypeLiveTestCase(ERP5TypeTestCaseMixin):
registry._conns[-1] = portal
# This is for Localizer patch
from Products.Localizer import patches
from zope.globalrequest import setRequest
request = portal.REQUEST
with patches._requests_lock:
patches._requests[thread.get_ident()] = request
setRequest(request)
# Make live tests run under the same server URL than the host instance.
if _request_server_url:
......
......@@ -21,7 +21,6 @@ This is a hotfix, it dynamically applies several patches to Zope.
# Import from the Standard Library
import logging
import os
from thread import allocate_lock, get_ident
# Import from itools
from .itools.i18n import AcceptLanguageType
......@@ -30,7 +29,8 @@ from .itools.i18n import AcceptLanguageType
import Globals
from ZPublisher import Publish
from ZPublisher.HTTPRequest import HTTPRequest
from zope.globalrequest import clearRequest, setRequest
from zope.globalrequest import getRequest as get_request
# Flag
patch = False
......@@ -57,56 +57,21 @@ logger = logging.getLogger('Localizer')
# Also, we keep the get_request method in the Globals module for backwards
# compatibility (with TranslationService for example).
_requests = {}
_requests_lock = allocate_lock()
def get_request():
"""Get a request object"""
return _requests.get(get_ident(), None)
def new_publish(request, module_name, after_list, debug=0,
zope_publish=Publish.publish):
# Get the process id
ident = get_ident()
# Add the request object to the global dictionnary
_requests_lock.acquire()
try:
_requests[ident] = request
finally:
_requests_lock.release()
# Call the old publish
try:
# Publish
x = zope_publish(request, module_name, after_list, debug)
finally:
# Remove the request object.
# When conflicts occur the "publish" method is called again,
# recursively. In this situation the "_requests dictionary would
# be cleaned in the innermost call, hence outer calls find the
# request does not exist anymore. For this reason we check first
# wether the request is there or not.
if ident in _requests:
_requests_lock.acquire()
try:
del _requests[ident]
finally:
_requests_lock.release()
return x
def get_new_publish(zope_publish):
def publish(request, *args, **kwargs):
try:
setRequest(request)
return zope_publish(request, *args, **kwargs)
finally:
clearRequest()
return publish
if patch is False:
logger.info('Install "Globals.get_request".')
# Apply the patch
Publish.publish = new_publish
# First import (it's not a refresh operation).
# We need to apply the patches.
Publish.publish = get_new_publish(Publish.publish)
patch = True
# Add to Globals for backwards compatibility
......
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