Commit bab045dc authored by Kazuhiko Shiozaki's avatar Kazuhiko Shiozaki Committed by Aurel

WIP: remove ZServer dependency.

parent 1adfeff6
...@@ -106,14 +106,12 @@ instancehome = getConfiguration().instancehome ...@@ -106,14 +106,12 @@ instancehome = getConfiguration().instancehome
if instancehome is not None: if instancehome is not None:
log_directory = os.path.join(instancehome, 'log') log_directory = os.path.join(instancehome, 'log')
if os.path.isdir(log_directory): if os.path.isdir(log_directory):
from Signals import Signals
from ZConfig.components.logger.loghandler import FileHandler from ZConfig.components.logger.loghandler import FileHandler
log_file_handler = FileHandler(os.path.join(log_directory, 'CMFActivity.log')) log_file_handler = FileHandler(os.path.join(log_directory, 'CMFActivity.log'))
# Default zope log format string borrowed from # Default zope log format string borrowed from
# ZConfig/components/logger/factory.xml, but without the extra "------" # ZConfig/components/logger/factory.xml, but without the extra "------"
# line separating entries. # line separating entries.
log_file_handler.setFormatter(logging.Formatter("%(asctime)s %(levelname)s %(name)s %(message)s", "%Y-%m-%dT%H:%M:%S")) log_file_handler.setFormatter(logging.Formatter("%(asctime)s %(levelname)s %(name)s %(message)s", "%Y-%m-%dT%H:%M:%S"))
Signals.registerZopeSignals([log_file_handler])
activity_logger.addHandler(log_file_handler) activity_logger.addHandler(log_file_handler)
activity_logger.propagate = 0 activity_logger.propagate = 0
......
...@@ -114,7 +114,3 @@ def match(self, request): ...@@ -114,7 +114,3 @@ def match(self, request):
return 1 return 1
else: else:
return 0 return 0
if six.PY2:
from ZServer.HTTPServer import zhttp_handler
zhttp_handler.match = match
...@@ -61,9 +61,6 @@ from Products.ERP5Type.patches import PersistentMapping ...@@ -61,9 +61,6 @@ from Products.ERP5Type.patches import PersistentMapping
from Products.ERP5Type.patches import DateTimePatch from Products.ERP5Type.patches import DateTimePatch
from Products.ERP5Type.patches import PythonScript from Products.ERP5Type.patches import PythonScript
from Products.ERP5Type.patches import MailHost from Products.ERP5Type.patches import MailHost
if six.PY2:
# No more ZServer
from Products.ERP5Type.patches import http_server
from Products.ERP5Type.patches import memcache_client from Products.ERP5Type.patches import memcache_client
from Products.ERP5Type.patches import StateChangeInfoPatch from Products.ERP5Type.patches import StateChangeInfoPatch
from Products.ERP5Type.patches import transforms from Products.ERP5Type.patches import transforms
...@@ -94,9 +91,6 @@ from Products.ERP5Type.patches import OFSFile ...@@ -94,9 +91,6 @@ from Products.ERP5Type.patches import OFSFile
from Products.ERP5Type.patches import ZSQLMethod from Products.ERP5Type.patches import ZSQLMethod
from Products.ERP5Type.patches import MimetypesRegistry from Products.ERP5Type.patches import MimetypesRegistry
from Products.ERP5Type.patches import users from Products.ERP5Type.patches import users
if six.PY2:
# No ZServer
from Products.ERP5Type.patches import Publish
from Products.ERP5Type.patches import WSGITask from Products.ERP5Type.patches import WSGITask
if six.PY2: if six.PY2:
# XXX-zope4py3: urllib2 removed (see future/backports/urllib/request.py) # XXX-zope4py3: urllib2 removed (see future/backports/urllib/request.py)
......
##############################################################################
#
# 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
try:
from ZServer.ZPublisher import Publish
from ZServer.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,
IBrowserPage,
recordMetaData,
pubevents,
Redirect,
Retry,
call_object,
dont_publish_class,
endInteraction,
get_module_info,
mapply,
missing_name,
newInteraction,
notify,
publish,
setDefaultSkin,
sys,
urlparse,
noSecurityManager,
)
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(pubevents.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
noSecurityManager()
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)
if IBrowserPage.providedBy(object):
request.postProcessInputs()
notify(pubevents.PubAfterTraversal(request))
if 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(pubevents.PubBeforeCommit(request))
if transactions_manager:
transactions_manager.commit()
notify(pubevents.PubSuccess(request))
endInteraction()
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(pubevents.PubBeforeAbort(
request, exc_info, retry))
finally:
if transactions_manager:
transactions_manager.abort()
finally:
endInteraction()
notify(pubevents.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(pubevents.PubBeforeAbort(request, exc_info, False))
finally:
if transactions_manager:
transactions_manager.abort()
finally:
endInteraction()
notify(pubevents.PubFailure(request, exc_info, False))
raise
Publish.publish = publish
except ImportError: # BBB Zope2
from ZPublisher import Publish, pubevents
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
# This code is taken from the medusa in zope 2.8.
#
# The license term should be this one:
#
# Medusa is Copyright 1996-2000, Sam Rushing &lt;rushing@nightmare.com&gt;
#
# All Rights Reserved
#
# Permission to use, copy, modify, and distribute this software and
# its documentation for any purpose and without fee is hereby
# granted, provided that the above copyright notice appear in all
# copies and that both that copyright notice and this permission
# notice appear in supporting documentation, and that the name of Sam
# Rushing not be used in advertising or publicity pertaining to
# distribution of the software without specific, written prior
# permission.
# Author: Sam Rushing <rushing@nightmare.com>
# Copyright 1996-2000 by Sam Rushing
# All Rights Reserved.
from ZServer.medusa.http_server import http_request
import ZPublisher.HTTPRequest
import string
import base64
import time
from six.moves.urllib.parse import quote
def log (self, bytes):
addr = self.channel.addr[0]
# Frontend-facing proxy is responsible for sanitising
# HTTP_X_FORWARDED_FOR, and only trusted accesses should bypass
# that proxy. So trust first entry.
#
# <patch>
if ZPublisher.HTTPRequest.trusted_proxies == ('0.0.0.0',): # Magic value to enable this functionality
forwarded_for = (self.get_header('x-forwarded-for') or '').split(',', 1)[0].strip()
if forwarded_for:
addr = forwarded_for
# </patch>
user_agent=self.get_header('user-agent')
if not user_agent: user_agent=''
referer=self.get_header('referer')
if not referer: referer=''
auth=self.get_header('Authorization')
name='Anonymous'
if auth is not None:
if string.lower(auth[:6]) == 'basic ':
try: decoded=base64.decodestring(auth[6:])
except base64.binascii.Error: decoded=''
t = string.split(decoded, ':', 1)
if len(t) < 2:
name = 'Unknown (bad auth string)'
else:
name = t[0]
# Originally, an unquoted request string was logged, but
# it only confuses log analysis programs! Note that Apache
# HTTP Server never unquote URIs in the access log.
t = self.request.split(' ')
quoted_request = '%s %s %s' % (t[0], quote(' '.join(t[1:-1])), t[-1])
self.channel.server.logger.log (
# <patch>
addr,
# </patch>
'- %s [%s] "%s" %d %d "%s" "%s"\n' % (
name,
self.log_date_string (time.time()),
# <patch>
quoted_request,
# </patch>
self.reply_code,
bytes,
referer,
user_agent
)
)
http_request.log = log
...@@ -3,7 +3,6 @@ import errno, logging, mock, os, socket, time ...@@ -3,7 +3,6 @@ import errno, logging, mock, os, socket, time
import itertools import itertools
from threading import Thread from threading import Thread
from UserDict import IterableUserDict from UserDict import IterableUserDict
import Lifetime
import transaction import transaction
from Testing import ZopeTestCase from Testing import ZopeTestCase
from ZODB.POSException import ConflictError from ZODB.POSException import ConflictError
...@@ -142,21 +141,13 @@ class ProcessingNodeTestCase(ZopeTestCase.TestCase): ...@@ -142,21 +141,13 @@ class ProcessingNodeTestCase(ZopeTestCase.TestCase):
""" """
_server_address = None # (host, port) of the http server if it was started, None otherwise _server_address = None # (host, port) of the http server if it was started, None otherwise
@staticmethod
def asyncore_loop():
try:
Lifetime.lifetime_loop()
except KeyboardInterrupt:
pass
Lifetime.graceful_shutdown_loop()
def startZServer(self, verbose=False): def startZServer(self, verbose=False):
"""Start HTTP ZServer in background""" """Start HTTP ZServer in background"""
if self._server_address is None: if self._server_address is None:
from Products.ERP5Type.tests.runUnitTest import log_directory from Products.ERP5Type.tests.runUnitTest import log_directory
log = os.path.join(log_directory, "Z2.log") log = os.path.join(log_directory, "Z2.log")
message = "Running %s server at %s:%s\n" message = "Running %s server at %s:%s\n"
if int(os.environ.get('erp5_wsgi', 0)): if True:
from Products.ERP5.bin.zopewsgi import app_wrapper, createServer from Products.ERP5.bin.zopewsgi import app_wrapper, createServer
sockets = [] sockets = []
server_type = 'HTTP' server_type = 'HTTP'
...@@ -198,23 +189,6 @@ class ProcessingNodeTestCase(ZopeTestCase.TestCase): ...@@ -198,23 +189,6 @@ class ProcessingNodeTestCase(ZopeTestCase.TestCase):
t = Thread(target=hs.run) t = Thread(target=hs.run)
t.setDaemon(1) t.setDaemon(1)
t.start() t.start()
else:
_print = lambda hs: verbose and ZopeTestCase._print(
message % (hs.server_protocol, hs.server_name, hs.server_port))
try:
hs = createZServer(log)
except RuntimeError as e:
ZopeTestCase._print(str(e))
else:
ProcessingNodeTestCase._server_address = hs.server_name, hs.server_port
_print(hs)
try:
_print(createZServer(log, zserver_type='webdav'))
except RuntimeError as e:
ZopeTestCase._print('Could not start webdav zserver: %s\n' % e)
t = Thread(target=Lifetime.loop)
t.setDaemon(1)
t.start()
from Products.CMFActivity import ActivityTool from Products.CMFActivity import ActivityTool
# Reset, in case that getServerAddress was already called, # Reset, in case that getServerAddress was already called,
# in which case, the value was ('', '') # in which case, the value was ('', '')
...@@ -307,9 +281,6 @@ class ProcessingNodeTestCase(ZopeTestCase.TestCase): ...@@ -307,9 +281,6 @@ class ProcessingNodeTestCase(ZopeTestCase.TestCase):
ZopeTestCase._print(' %i' % message_count) ZopeTestCase._print(' %i' % message_count)
old_message_count = message_count old_message_count = message_count
portal_activities.process_timer(None, None) portal_activities.process_timer(None, None)
if Lifetime._shutdown_phase:
# XXX CMFActivity contains bare excepts
raise KeyboardInterrupt
message_list = getMessageList() message_list = getMessageList()
message_count = len(message_list) message_count = len(message_list)
if time.time() >= deadline or message_count and any(x.processing_node == -2 if time.time() >= deadline or message_count and any(x.processing_node == -2
...@@ -377,7 +348,7 @@ class ProcessingNodeTestCase(ZopeTestCase.TestCase): ...@@ -377,7 +348,7 @@ class ProcessingNodeTestCase(ZopeTestCase.TestCase):
def processing_node(self): def processing_node(self):
"""Main loop for nodes that process activities""" """Main loop for nodes that process activities"""
try: try:
while not Lifetime._shutdown_phase: while True:
time.sleep(.3) time.sleep(.3)
transaction.begin() transaction.begin()
try: try:
...@@ -408,7 +379,7 @@ class ProcessingNodeTestCase(ZopeTestCase.TestCase): ...@@ -408,7 +379,7 @@ class ProcessingNodeTestCase(ZopeTestCase.TestCase):
timerserver_thread = None timerserver_thread = None
try: try:
while not Lifetime._shutdown_phase: while True:
time.sleep(.3) time.sleep(.3)
transaction.begin() transaction.begin()
try: try:
......
...@@ -463,9 +463,6 @@ class DebugTestResult: ...@@ -463,9 +463,6 @@ class DebugTestResult:
self.result = result self.result = result
def _start_debugger(self, tb): def _start_debugger(self, tb):
import Lifetime
if Lifetime._shutdown_phase:
return
try: try:
# try ipython if available # try ipython if available
import IPython import IPython
...@@ -624,11 +621,9 @@ def runUnitTestList(test_list, verbosity=1, debug=0, run_only=None): ...@@ -624,11 +621,9 @@ def runUnitTestList(test_list, verbosity=1, debug=0, run_only=None):
TestRunner = unittest.TextTestRunner TestRunner = unittest.TextTestRunner
import Lifetime
from Zope2.custom_zodb import Storage, save_mysql, \ from Zope2.custom_zodb import Storage, save_mysql, \
node_pid_list, neo_cluster, zeo_server_pid, wcfs_server node_pid_list, neo_cluster, zeo_server_pid, wcfs_server
def shutdown(signum, frame, signum_set=set()): def shutdown(signum, frame, signum_set=set()):
Lifetime.shutdown(0)
signum_set.add(signum) signum_set.add(signum)
if node_pid_list is None and len(signum_set) > 1: if node_pid_list is None and len(signum_set) > 1:
# in case of ^C, a child should also receive a SIGHUP from the parent, # in case of ^C, a child should also receive a SIGHUP from the parent,
......
...@@ -69,13 +69,6 @@ def get_new_publish(zope_publish): ...@@ -69,13 +69,6 @@ def get_new_publish(zope_publish):
if patch is False: if patch is False:
patch = True patch = True
if six.PY2: # ZServer-specific patch
# Apply the patch TODO: zope4py2 is this really needed ?
from ZPublisher import Publish
Publish.publish = get_new_publish(Publish.publish)
# PATCH 2: Accept # PATCH 2: Accept
# #
# Adds the variable AcceptLanguage to the REQUEST. It provides a higher # Adds the variable AcceptLanguage to the REQUEST. It provides a higher
......
import six
if six.PY2:
from ZServer.datatypes import ServerFactory
class TimerServerFactory(ServerFactory):
def __init__(self, section):
ServerFactory.__init__(self)
self.interval = section.interval
def create(self):
from .TimerServer import TimerServer
return TimerServer(self.module, self.interval)
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