Commit 57b75fe0 authored by Kazuhiko Shiozaki's avatar Kazuhiko Shiozaki

Zope2: revive patches for Zope2.

parent be6c0474
......@@ -25,7 +25,7 @@ try:
from ZPublisher.WSGIPublisher import publish_module
except ImportError:
# BBB Zope2
from Products.ERP5Type.patches.WSGIPublisher import publish_module
from Products.ERP5Type.patches.WSGIPublisherZope2 import publish_module
# this class licensed under the MIT license (stolen from pyramid_translogger)
class TransLogger(object):
......
......@@ -21,16 +21,21 @@
##############################################################################
import six
from Products.ERP5Type import WITH_LEGACY_WORKFLOW
from Products.ERP5Type import WITH_LEGACY_WORKFLOW, IS_ZOPE2
# Load all monkey patches
from Products.ERP5Type.patches import WSGIPublisher
if IS_ZOPE2: # BBB Zope2
from Products.ERP5Type.patches import WSGIPublisherZope2
else:
from Products.ERP5Type.patches import WSGIPublisher
from Products.ERP5Type.patches import HTTPRequest
from Products.ERP5Type.patches import AccessControl_patch
from Products.ERP5Type.patches import Restricted
from Products.ERP5Type.patches import m2crypto
from Products.ERP5Type.patches import ObjectManager
from Products.ERP5Type.patches import PropertyManager
if IS_ZOPE2: # BBB Zope2
from Products.ERP5Type.patches import TM
from Products.ERP5Type.patches import DA
if WITH_LEGACY_WORKFLOW:
from Products.ERP5Type.patches import DCWorkflow
......@@ -90,6 +95,8 @@ from Products.ERP5Type.patches import OFSFile
from Products.ERP5Type.patches import ZSQLMethod
from Products.ERP5Type.patches import MimetypesRegistry
from Products.ERP5Type.patches import users
if IS_ZOPE2: # BBB Zope2
from Products.ERP5Type.patches import Publish
from Products.ERP5Type.patches import WSGITask
if six.PY2:
# XXX-zope4py3: urllib2 removed (see future/backports/urllib/request.py)
......
......@@ -45,6 +45,13 @@ if six.PY3:
else:
WITH_LEGACY_WORKFLOW = True
try:
from ZPublisher.HTTPResponse import WSGIResponse
except ImportError: # BBB Zope2
IS_ZOPE2 = True
else:
IS_ZOPE2 = False
# We have a name conflict with source_reference and destination_reference,
# which are at the same time property accessors for 'source_reference'
# property, and category accessors (similar to getSourceValue().getReference())
......
......@@ -17,9 +17,13 @@ import re
try: from IOBTree import Bucket
except: Bucket=lambda:{}
from Shared.DC.ZRDB.Aqueduct import decodestring, parse
from Shared.DC.ZRDB.DA import DA, DatabaseError, SQLMethodTracebackSupplement, getBrain
from Shared.DC.ZRDB.DA import DA, DatabaseError, SQLMethodTracebackSupplement
from Shared.DC.ZRDB import RDB
from Shared.DC.ZRDB.Results import Results
try: # BBB Zope 2.12
from App.Extensions import getBrain
except ImportError:
from Shared.DC.ZRDB.DA import getBrain
from AccessControl import ClassSecurityInfo, getSecurityManager
from Products.ERP5Type.Globals import InitializeClass
from Acquisition import aq_base, aq_parent
......
from App.special_dtml import DTMLFile
from OFS.Image import File
from Products.ERP5Type import _dtmldir
from Products.ERP5Type import IS_ZOPE2, _dtmldir
def _setData(self, data):
......@@ -18,3 +18,19 @@ def _setData(self, data):
# We call this method to make sure size is set and caches reset
self.update_data(data, size=size)
File._setData = _setData
if IS_ZOPE2: # BBB Zope2
from OFS.SimpleItem import Item
# Patch for displaying textearea in full window instead of
# remembering a quantity of lines to display in a cookie
manage_editForm = DTMLFile("fileEdit", _dtmldir)
manage_editForm._setName('manage_editForm')
File.manage_editForm = manage_editForm
File.manage = manage_editForm
File.manage_main = manage_editForm
File.manage_editDocument = manage_editForm
File.manage_editForm = manage_editForm
# restore __repr__ after persistent > 4.4
# https://github.com/zopefoundation/Zope/issues/379
File.__repr__ = Item.__repr__
......@@ -15,7 +15,7 @@
from AccessControl import ClassSecurityInfo
from Products.ERP5Type.Globals import InitializeClass
from OFS.Folder import Folder
from Products.ERP5Type import Permissions
from Products.ERP5Type import IS_ZOPE2, Permissions
"""
This patch modifies OFS.Folder._setOb to update portal_skins cache when
......@@ -59,16 +59,25 @@ def Folder_isERP5SitePresent(self):
Folder.isERP5SitePresent = Folder_isERP5SitePresent
def Folder_zope_quick_start(self):
"""Compatibility for old `zope_quick_start` that is referenced in
/index_html (at the root)
"""
return 'OK'
Folder.zope_quick_start = Folder_zope_quick_start
security = ClassSecurityInfo()
security.declareProtected(Permissions.ManagePortal, 'isERP5SitePresent')
security.declarePublic('zope_quick_start')
if not IS_ZOPE2:
def Folder_zope_quick_start(self):
"""Compatibility for old `zope_quick_start` that is referenced in
/index_html (at the root)
"""
return 'OK'
Folder.zope_quick_start = Folder_zope_quick_start
security.declarePublic('zope_quick_start')
Folder.security = security
InitializeClass(Folder)
if IS_ZOPE2: # BBB Zope2
from OFS.SimpleItem import Item
# restore __repr__ after persistent > 4.4
# https://github.com/zopefoundation/Zope/issues/379
Folder.__repr__ = Item.__repr__
from AccessControl import ClassSecurityInfo
from OFS.SimpleItem import SimpleItem
from Products.ERP5Type import IS_ZOPE2
"""
Very simple volatile-attribute-based caching.
......@@ -44,7 +45,10 @@ def volatileCached(self, func):
self._v_SimpleItem_Item_vCache = cache_dict = {}
# Use whole func_code as a key, as it is the only reliable way to identify a
# function.
key = func.__code__
if IS_ZOPE2: # BBB Zope2
key = func.func_code
else:
key = func.__code__
try:
return cache_dict[key]
except KeyError:
......
##############################################################################
#
# 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
#
##############################################################################
from Products.ERP5Type.Timeout import getPublisherDeadlineValue
from ZPublisher import Publish
from ZPublisher.Publish import (
# Produced using:
# dis.dis(
# compile(open(<this_file>, 'r').read(), 'foo', 'exec').co_consts[
# <index of publish code object in co_consts>
# ]
# )
# and checking all uniques LOAD_GLOBAL names, excluding builtins and
# getPublisherDeadlineValue, and including publish parameter default
# values.
ISkinnable,
PubAfterTraversal,
PubBeforeAbort,
PubBeforeCommit,
PubFailure,
PubStart,
PubSuccess,
Redirect,
Retry,
call_object,
dont_publish_class,
endInteraction,
get_module_info,
mapply,
missing_name,
newInteraction,
notify,
publish,
setDefaultSkin,
sys,
urlparse,
)
def publish(request, module_name, after_list, debug=0,
# Optimize:
call_object=call_object,
missing_name=missing_name,
dont_publish_class=dont_publish_class,
mapply=mapply,
):
(bobo_before, bobo_after, object, realm, debug_mode, err_hook,
validated_hook, transactions_manager)= get_module_info(module_name)
parents=None
response=None
try:
with getPublisherDeadlineValue(request):
notify(PubStart(request))
# TODO pass request here once BaseRequest implements IParticipation
newInteraction()
request.processInputs()
request_get=request.get
response=request.response
# First check for "cancel" redirect:
if request_get('SUBMIT', '').strip().lower() == 'cancel':
cancel = request_get('CANCEL_ACTION', '')
if cancel:
# Relative URLs aren't part of the spec, but are accepted by
# some browsers.
for part, base in zip(urlparse(cancel)[:3],
urlparse(request['BASE1'])[:3]):
if not part:
continue
if not part.startswith(base):
cancel = ''
break
if cancel:
raise Redirect(cancel)
after_list[0]=bobo_after
if debug_mode:
response.debug_mode=debug_mode
if realm and not request.get('REMOTE_USER',None):
response.realm=realm
if bobo_before is not None:
bobo_before()
# Get the path list.
# According to RFC1738 a trailing space in the path is valid.
path=request_get('PATH_INFO')
request['PARENTS']=parents=[object]
if transactions_manager:
transactions_manager.begin()
object=request.traverse(path, validated_hook=validated_hook)
notify(PubAfterTraversal(request))
if transactions_manager:
transactions_manager.recordMetaData(object, request)
result=mapply(object, request.args, request,
call_object,1,
missing_name,
dont_publish_class,
request, bind=1)
if result is not response:
response.setBody(result)
notify(PubBeforeCommit(request))
if transactions_manager:
transactions_manager.commit()
endInteraction()
notify(PubSuccess(request))
return response
except:
# save in order to give 'PubFailure' the original exception info
exc_info = sys.exc_info()
# DM: provide nicer error message for FTP
sm = None
if response is not None:
sm = getattr(response, "setMessage", None)
if sm is not None:
from asyncore import compact_traceback
cl,val= sys.exc_info()[:2]
sm('%s: %s %s' % (
getattr(cl,'__name__',cl), val,
debug_mode and compact_traceback()[-1] or ''))
# debug is just used by tests (has nothing to do with debug_mode!)
if not debug and err_hook is not None:
retry = False
if parents:
parents=parents[0]
try:
try:
with getPublisherDeadlineValue(request):
return err_hook(parents, request,
sys.exc_info()[0],
sys.exc_info()[1],
sys.exc_info()[2],
)
except Retry:
if not request.supports_retry():
with getPublisherDeadlineValue(request):
return err_hook(parents, request,
sys.exc_info()[0],
sys.exc_info()[1],
sys.exc_info()[2],
)
retry = True
finally:
# Note: 'abort's can fail. Nevertheless, we want end request handling
try:
try:
notify(PubBeforeAbort(request, exc_info, retry))
finally:
if transactions_manager:
transactions_manager.abort()
finally:
endInteraction()
notify(PubFailure(request, exc_info, retry))
# Only reachable if Retry is raised and request supports retry.
newrequest=request.retry()
request.close() # Free resources held by the request.
# Set the default layer/skin on the newly generated request
if ISkinnable.providedBy(newrequest):
setDefaultSkin(newrequest)
try:
return publish(newrequest, module_name, after_list, debug)
finally:
newrequest.close()
else:
# Note: 'abort's can fail. Nevertheless, we want end request handling
try:
try:
notify(PubBeforeAbort(request, exc_info, False))
finally:
if transactions_manager:
transactions_manager.abort()
finally:
endInteraction()
notify(PubFailure(request, exc_info, False))
raise
Publish.publish = publish
##############################################################################
#
# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
# Copyright (c) 2009 Nexedi SARL and Contributors. All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (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
#
##############################################################################
import transaction
from Shared.DC.ZRDB.TM import TM, Surrogate
# ZPublisher error path can aggravate error:
# https://bugs.launchpad.net/bugs/229863
def TM__register(self):
if not self._registered:
#try:
transaction.get().register(Surrogate(self))
self._begin()
self._registered = 1
self._finalize = 0
#except: pass
TM._register = TM__register
# sortKey should return str in transaction 1.4.1 or later.
TM._sort_key = '1'
This diff is collapsed.
##############################################################################
#
# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (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
#
##############################################################################
from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate
from Products.PageTemplates.PageTemplateFile import PageTemplateFile
from Products.ERP5Type import _dtmldir
import os
# Patch for displaying textearea in full window instead of
# remembering a quantity of lines to display in a cookie
pt_editForm = PageTemplateFile(os.path.join(_dtmldir, "ptEdit"), globals(),
__name__='pt_editForm' )
pt_editForm._owner = None
ZopePageTemplate.pt_editForm = pt_editForm
ZopePageTemplate.manage = pt_editForm
ZopePageTemplate.manage_main = pt_editForm
......@@ -13,10 +13,100 @@
from Shared.DC.ZRDB.sqltest import *
from Shared.DC.ZRDB import sqltest
from DateTime import DateTime
from Products.ERP5Type import IS_ZOPE2
list_type_list = list, tuple, set, frozenset, dict
if 1: # For easy diff with original (ZSQLMethods 3.14)
if IS_ZOPE2: # BBB Zope2
def render(self, md):
name=self.__name__
t=self.type
args=self.args
try:
expr=self.expr
if type(expr) is type(''):
v=md[expr]
else:
v=expr(md)
except (KeyError, NameError):
if 'optional' in args and args['optional']:
return ''
raise ValueError('Missing input variable, <em>%s</em>' % name)
# PATCH: use isinstance instead of type comparison, to allow
# subclassing.
if isinstance(v, list_type_list):
if len(v) > 1 and not self.multiple:
raise ValueError(
'multiple values are not allowed for <em>%s</em>'
% name)
else: v=[v]
vs=[]
for v in v:
if not v and type(v) is StringType and t != 'string': continue
if t=='int':
try:
if type(v) is StringType:
if v[-1:]=='L':
v=v[:-1]
atoi(v)
else: v=str(int(v))
except ValueError:
raise ValueError(
'Invalid integer value for <em>%s</em>' % name)
elif t=='float':
if not v and type(v) is StringType: continue
try:
if type(v) is StringType: atof(v)
else: v=str(float(v))
except ValueError:
raise ValueError(
'Invalid floating-point value for <em>%s</em>' % name)
elif t.startswith('datetime'):
# For subsecond precision, use 'datetime(N)' MySQL type,
# where N is the number of digits after the decimal point.
n = 0 if t == 'datetime' else int(t[9])
v = (v if isinstance(v, DateTime) else DateTime(v)).toZone('UTC')
v = "'%s%s'" % (v.ISO(),
('.%06u' % (v.micros() % 1000000))[:1+n] if n else '')
else:
if not isinstance(v, (str, unicode)):
v = str(v)
v=md.getitem('sql_quote__',0)(v)
#if find(v,"\'") >= 0: v=join(split(v,"\'"),"''")
#v="'%s'" % v
vs.append(v)
if not vs and t=='nb':
if 'optional' in args and args['optional']:
return ''
else:
raise ValueError(
'Invalid empty string value for <em>%s</em>' % name)
if not vs:
if self.optional: return ''
raise ValueError(
'No input was provided for <em>%s</em>' % name)
if len(vs) > 1:
vs=join(map(str,vs),', ')
if self.op == '<>':
## Do the equivalent of 'not-equal' for a list,
## "a not in (b,c)"
return "%s not in (%s)" % (self.column, vs)
else:
## "a in (b,c)"
return "%s in (%s)" % (self.column, vs)
return "%s %s %s" % (self.column, self.op, vs[0])
SQLTest.render = SQLTest.__call__ = render
sqltest.valid_type = (('int', 'float', 'string', 'nb', 'datetime') + tuple('datetime(%s)' % x for x in xrange(7))).__contains__
else: # For easy diff with original (ZSQLMethods 3.14)
def render(self, md):
name = self.__name__
......@@ -117,12 +207,12 @@ if 1: # For easy diff with original (ZSQLMethods 3.14)
return '%s %s %s' % (self.column, self.op, vs[0])
SQLTest.render = SQLTest.__call__ = render
from builtins import range
new_valid_types = (('int', 'float', 'string', 'nb', 'datetime') + tuple('datetime(%s)' % x for x in range(7)))
from builtins import range
new_valid_types = (('int', 'float', 'string', 'nb', 'datetime') + tuple('datetime(%s)' % x for x in range(7)))
try:
# BBB
from Shared.DC.ZRDB.sqltest import valid_type
sqltest.valid_type = new_valid_types.__contains__
except ImportError:
sqltest.valid_types = new_valid_types
try:
# BBB
from Shared.DC.ZRDB.sqltest import valid_type
sqltest.valid_type = new_valid_types.__contains__
except ImportError:
sqltest.valid_types = new_valid_types
......@@ -17,8 +17,83 @@
from Shared.DC.ZRDB.sqlvar import *
from Shared.DC.ZRDB import sqlvar
from DateTime import DateTime
from Products.ERP5Type import IS_ZOPE2
if 1: # For easy diff with original (ZSQLMethods 3.14)
if IS_ZOPE2: # BBB Zope2
from string import atoi,atof
def render(self, md):
args=self.args
t=args['type']
try:
expr=self.expr
if type(expr) is str: v=md[expr]
else: v=expr(md)
except Exception:
if args.get('optional'):
return 'null'
if type(expr) is not str:
raise
raise ValueError('Missing input variable, <em>%s</em>' % self.__name__)
if v is None and args.get('optional'):
return 'null'
if t=='int':
try:
if type(v) is str:
if v[-1:]=='L':
v=v[:-1]
atoi(v)
return v
return str(int(v))
except Exception:
t = 'integer'
elif t=='float':
try:
if type(v) is str:
if v[-1:]=='L':
v=v[:-1]
atof(v)
return v
# ERP5 patch, we use repr that have better precision than str for
# floats
return repr(float(v))
except Exception:
t = 'floating-point'
elif t.startswith('datetime'):
# For subsecond precision, use 'datetime(N)' MySQL type,
# where N is the number of digits after the decimal point.
n = 0 if t == 'datetime' else int(t[9])
try:
v = (v if isinstance(v, DateTime) else DateTime(v)).toZone('UTC')
return "'%s%s'" % (v.ISO(),
('.%06u' % (v.micros() % 1000000))[:1+n] if n else '')
except Exception:
t = 'datetime'
elif t=='nb' and not v:
t = 'empty string'
else:
v = md.getitem('sql_quote__',0)(
v if isinstance(v, basestring) else str(v))
#if find(v,"\'") >= 0: v=join(split(v,"\'"),"''")
#v="'%s'" % v
return v
if args.get('optional'):
return 'null'
raise ValueError('Invalid %s value for <em>%s</em>: %r'
% (t, self.__name__, v))
valid_type = 'int', 'float', 'string', 'nb', 'datetime'
valid_type += tuple(map('datetime(%s)'.__mod__, xrange(7)))
valid_type = valid_type.__contains__
SQLVar.render = render
SQLVar.__call__ = render
sqlvar.valid_type = valid_type
else: # For easy diff with original (ZSQLMethods 3.14)
def render(self, md):
name = self.__name__
args = self.args
......@@ -98,15 +173,15 @@ if 1: # For easy diff with original (ZSQLMethods 3.14)
return v
# Patched by yo. datetime is added.
new_valid_types = 'int', 'float', 'string', 'nb', 'datetime'
new_valid_types += tuple(map('datetime(%s)'.__mod__, range(7)))
try:
# BBB
from Shared.DC.ZRDB.sqlvar import valid_type
sqlvar.valid_type = new_valid_types.__contains__
except ImportError:
sqlvar.valid_types = new_valid_types
SQLVar.render = render
SQLVar.__call__ = render
# Patched by yo. datetime is added.
new_valid_types = 'int', 'float', 'string', 'nb', 'datetime'
new_valid_types += tuple(map('datetime(%s)'.__mod__, range(7)))
try:
# BBB
from Shared.DC.ZRDB.sqlvar import valid_type
sqlvar.valid_type = new_valid_types.__contains__
except ImportError:
sqlvar.valid_types = new_valid_types
SQLVar.render = render
SQLVar.__call__ = render
......@@ -32,6 +32,7 @@ from zope.globalrequest import clearRequest, setRequest
from zope.globalrequest import getRequest as get_request
# Flag
from Products.ERP5Type import IS_ZOPE2
patch = False
Z_DEBUG_MODE = os.environ.get('Z_DEBUG_MODE') == '1'
......@@ -69,6 +70,17 @@ def get_new_publish(zope_publish):
if patch is False:
patch = True
if IS_ZOPE2: # BBB Zope2 (ZServer-specific patch)
logger.info('Install "Globals.get_request".')
# Apply the patch
from ZPublisher import Publish
Publish.publish = get_new_publish(Publish.publish)
# Add to Globals for backwards compatibility
import Globals
Globals.get_request = get_request
# PATCH 2: Accept
#
# Adds the variable AcceptLanguage to the REQUEST. It provides a higher
......
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