Commit 620898b8 authored by Bryton Lacquement's avatar Bryton Lacquement 🚪

Localizer: replace the 'Global Request' monkey-patch by an import of zope.globalrequest

While working on the implementation of  WSGI mode for ERP5, we discovered that
Zope4 (WSGIPublisher) depends on zope.globalrequest. Since we backported
WSGIPublisher, we decided to also replace the 'Global Request' monkey-patch.
parent 2fc6f310
...@@ -60,12 +60,7 @@ import transaction ...@@ -60,12 +60,7 @@ import transaction
from App.config import getConfiguration from App.config import getConfiguration
from Shared.DC.ZRDB.Results import Results from Shared.DC.ZRDB.Results import Results
import Products.Localizer.patches from zope.globalrequest import clearRequest, getRequest, setRequest
localizer_lock = Products.Localizer.patches._requests_lock
localizer_contexts = Products.Localizer.patches._requests
LocalizerContext = lambda request: request
from Products.MailHost.MailHost import MailHostError from Products.MailHost.MailHost import MailHostError
from zLOG import LOG, INFO, WARNING, ERROR from zLOG import LOG, INFO, WARNING, ERROR
...@@ -1464,7 +1459,7 @@ class ActivityTool (BaseTool): ...@@ -1464,7 +1459,7 @@ class ActivityTool (BaseTool):
def invoke(self, message): def invoke(self, message):
if self.activity_tracking: 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)) 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: if getattr(self, 'aq_chain', None) is not None:
# Grab existing acquisition chain and extrach base objects. # Grab existing acquisition chain and extrach base objects.
base_chain = [aq_base(x) for x in self.aq_chain] base_chain = [aq_base(x) for x in self.aq_chain]
...@@ -1500,16 +1495,8 @@ class ActivityTool (BaseTool): ...@@ -1500,16 +1495,8 @@ class ActivityTool (BaseTool):
new_request.other['VirtualRootPhysicalPath'] = request_info['VirtualRootPhysicalPath'] new_request.other['VirtualRootPhysicalPath'] = request_info['VirtualRootPhysicalPath']
if 'HTTP_ACCEPT_LANGUAGE' in request_info: if 'HTTP_ACCEPT_LANGUAGE' in request_info:
new_request.environ['HTTP_ACCEPT_LANGUAGE'] = request_info['HTTP_ACCEPT_LANGUAGE'] new_request.environ['HTTP_ACCEPT_LANGUAGE'] = request_info['HTTP_ACCEPT_LANGUAGE']
# Replace Localizer/iHotfix Context, saving existing one old_request = getRequest()
localizer_context = LocalizerContext(new_request) setRequest(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"
new_request.processInputs() new_request.processInputs()
new_request_container = request_container.__class__(REQUEST=new_request) new_request_container = request_container.__class__(REQUEST=new_request)
...@@ -1528,17 +1515,10 @@ class ActivityTool (BaseTool): ...@@ -1528,17 +1515,10 @@ class ActivityTool (BaseTool):
# Restore default skin selection # Restore default skin selection
skinnable = self.getPortalObject() skinnable = self.getPortalObject()
skinnable.changeSkin(skinnable.getSkinNameFromRequest(request)) skinnable.changeSkin(skinnable.getSkinNameFromRequest(request))
if old_localizer_context is not False: if old_request is None:
# Restore Localizer/iHotfix context clearRequest()
id = get_ident() else:
localizer_lock.acquire() setRequest(old_request)
try:
if old_localizer_context is None:
del localizer_contexts[id]
else:
localizer_contexts[id] = old_localizer_context
finally:
localizer_lock.release()
if self.activity_tracking: if self.activity_tracking:
activity_tracking_logger.info('invoked message') activity_tracking_logger.info('invoked message')
if my_self is not self: # We rewrapped self if my_self is not self: # We rewrapped self
......
...@@ -38,19 +38,7 @@ from App.class_init import default__class_init__, ApplicationDefaultPermissions ...@@ -38,19 +38,7 @@ from App.class_init import default__class_init__, ApplicationDefaultPermissions
# Nicer alias for class initializer. # Nicer alias for class initializer.
InitializeClass = default__class_init__ InitializeClass = default__class_init__
########################################## from zope.globalrequest import getRequest as get_request
# 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
# Persistency stuff also hasn't moved much from Zope 2.8, although the old # Persistency stuff also hasn't moved much from Zope 2.8, although the old
# "Persistence" module remains there for ancient backward compatibility. # "Persistence" module remains there for ancient backward compatibility.
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
ERP5Type is provides a RAD environment for Zope / CMF ERP5Type is provides a RAD environment for Zope / CMF
All ERP5 classes derive from ERP5Type All ERP5 classes derive from ERP5Type
""" """
from patches import python, pylint from patches import python, pylint, globalrequest
from zLOG import LOG, INFO from zLOG import LOG, INFO
DISPLAY_BOOT_PROCESS = False 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():
value = getattr(localData, 'request', None)
if value is None:
setattr(localData, 'request', value)
return value
def setRequest(request):
setattr(localData, 'request', request)
def clearRequest():
setRequest(None)
...@@ -21,7 +21,6 @@ This is a hotfix, it dynamically applies several patches to Zope. ...@@ -21,7 +21,6 @@ This is a hotfix, it dynamically applies several patches to Zope.
# Import from the Standard Library # Import from the Standard Library
import logging import logging
import os import os
from thread import allocate_lock, get_ident
# Import from itools # Import from itools
from .itools.i18n import AcceptLanguageType from .itools.i18n import AcceptLanguageType
...@@ -29,9 +28,9 @@ from .itools.i18n import AcceptLanguageType ...@@ -29,9 +28,9 @@ from .itools.i18n import AcceptLanguageType
# Import from Zope # Import from Zope
import Globals import Globals
from ZPublisher import Publish from ZPublisher import Publish
from Products.ERP5Type.patches import WSGIPublisher
from ZPublisher.HTTPRequest import HTTPRequest from ZPublisher.HTTPRequest import HTTPRequest
from zope.globalrequest import clearRequest, setRequest
from zope.globalrequest import getRequest as get_request
# Flag # Flag
patch = False patch = False
...@@ -58,37 +57,13 @@ logger = logging.getLogger('Localizer') ...@@ -58,37 +57,13 @@ logger = logging.getLogger('Localizer')
# Also, we keep the get_request method in the Globals module for backwards # Also, we keep the get_request method in the Globals module for backwards
# compatibility (with TranslationService for example). # compatibility (with TranslationService for example).
_requests = {}
_requests_lock = allocate_lock()
def get_request():
"""Get a request object"""
return _requests.get(get_ident(), None)
def get_new_publish(zope_publish): def get_new_publish(zope_publish):
def publish(request, *args, **kwargs): def publish(request, *args, **kwargs):
# Get the process id
ident = get_ident()
# Add the request object to the global dictionnary
with _requests_lock:
_requests[ident] = request
# Call the old publish
try: try:
# Publish setRequest(request)
return zope_publish(request, *args, **kwargs) return zope_publish(request, *args, **kwargs)
finally: finally:
# Remove the request object. clearRequest()
# 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:
with _requests_lock:
del _requests[ident]
return publish return publish
...@@ -97,16 +72,6 @@ if patch is False: ...@@ -97,16 +72,6 @@ if patch is False:
# Apply the patch # Apply the patch
Publish.publish = get_new_publish(Publish.publish) Publish.publish = get_new_publish(Publish.publish)
WSGIPublisher.publish = get_new_publish(WSGIPublisher.publish)
# Update WSGIPublisher.publish_module.__defaults__, otherwise it will use
# the unpatched WSGIPublisher.publish.
WSGIPublisher.publish_module.__defaults__ = (
WSGIPublisher.publish,
) + WSGIPublisher.publish_module.__defaults__[1:]
# First import (it's not a refresh operation).
# We need to apply the patches.
patch = True patch = True
# Add to Globals for backwards compatibility # 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