monkeypatch quixote with thread-aware functions (#6735)
This commit is contained in:
parent
01b280aa2c
commit
079ccafc75
|
@ -1361,7 +1361,7 @@ def test_sms_with_passerelle(pub):
|
|||
item.body = 'my message'
|
||||
with mock.patch('wcs.wscalls.get_secret_and_orig') as mocked_secret_and_orig:
|
||||
mocked_secret_and_orig.return_value = ('secret', 'localhost')
|
||||
with mock.patch('wcs.wscalls.http_post_request') as mocked_http_post:
|
||||
with mock.patch('qommon.misc.http_post_request') as mocked_http_post:
|
||||
mocked_http_post.return_value = ('response', '200', 'data', 'headers')
|
||||
item.perform(formdata)
|
||||
url, payload = mocked_http_post.call_args[0]
|
||||
|
|
|
@ -7,6 +7,7 @@ import random
|
|||
import psycopg2
|
||||
import pytest
|
||||
import shutil
|
||||
import sys
|
||||
import threading
|
||||
import urlparse
|
||||
|
||||
|
@ -22,6 +23,7 @@ from wcs import publisher, compat
|
|||
from wcs.qommon.http_request import HTTPRequest
|
||||
from wcs.users import User
|
||||
from wcs.tracking_code import TrackingCode
|
||||
import wcs.qommon.emails
|
||||
import wcs.qommon.sms
|
||||
import qommon.sms
|
||||
from qommon.errors import ConnectionError
|
||||
|
@ -195,21 +197,19 @@ class EmailsMocking(object):
|
|||
return len(self.emails)
|
||||
|
||||
def __enter__(self):
|
||||
import wcs.qommon.emails
|
||||
import qommon.emails
|
||||
self.wcs_create_smtp_server = wcs.qommon.emails.create_smtp_server
|
||||
self.qommon_create_smtp_server = qommon.emails.create_smtp_server
|
||||
self.wcs_create_smtp_server = sys.modules['wcs.qommon.emails'].create_smtp_server
|
||||
self.qommon_create_smtp_server = sys.modules['qommon.emails'].create_smtp_server
|
||||
|
||||
wcs.qommon.emails.create_smtp_server = self.create_smtp_server
|
||||
qommon.emails.create_smtp_server = self.create_smtp_server
|
||||
sys.modules['wcs.qommon.emails'].create_smtp_server = self.create_smtp_server
|
||||
sys.modules['qommon.emails'].create_smtp_server = self.create_smtp_server
|
||||
|
||||
self.emails = {}
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_value, tb):
|
||||
del self.emails
|
||||
wcs.qommon.emails.create_smtp_server = self.wcs_create_smtp_server
|
||||
qommon.emails.create_smtp_server = self.qommon_create_smtp_server
|
||||
sys.modules['wcs.qommon.emails'].create_smtp_server = self.wcs_create_smtp_server
|
||||
sys.modules['qommon.emails'].create_smtp_server = self.qommon_create_smtp_server
|
||||
|
||||
|
||||
class MockSubstitutionVariables(object):
|
||||
|
|
|
@ -18,7 +18,10 @@ import sys
|
|||
import os
|
||||
sys.path.insert(0, os.path.dirname(__file__))
|
||||
|
||||
import monkeypatch
|
||||
|
||||
import qommon
|
||||
sys.modules['qommon'] = sys.modules['wcs.qommon']
|
||||
|
||||
import qommon.form
|
||||
sys.modules['form'] = qommon.form
|
||||
|
|
|
@ -41,11 +41,11 @@ from qommon.evalutils import make_datetime
|
|||
from qommon.misc import C_, ellipsize
|
||||
from qommon.afterjobs import AfterJob
|
||||
from qommon import emails
|
||||
import qommon.sms
|
||||
from qommon import errors
|
||||
from qommon import ezt
|
||||
from qommon import ods
|
||||
from qommon.form import *
|
||||
from qommon.sms import SMS
|
||||
from qommon.storage import (Equal, NotEqual, LessOrEqual, GreaterOrEqual, Or,
|
||||
Intersects, ILike, FtsMatch, Contains, Null)
|
||||
|
||||
|
@ -131,7 +131,7 @@ class SendCodeFormdefDirectory(Directory):
|
|||
if get_publisher().use_sms_feature:
|
||||
sms_cfg = get_cfg('sms', {})
|
||||
mode = sms_cfg.get('mode', 'none')
|
||||
sms_class = SMS.get_sms_class(mode)
|
||||
sms_class = qommon.sms.SMS.get_sms_class(mode)
|
||||
if sms_class:
|
||||
form.add(StringWidget, 'sms', title=_('SMS Number'), required=False)
|
||||
form.add(RadiobuttonsWidget, 'method',
|
||||
|
|
|
@ -36,21 +36,6 @@ from .publisher import WcsPublisher
|
|||
from .qommon.http_request import HTTPRequest
|
||||
from .qommon.http_response import HTTPResponse
|
||||
|
||||
def init_publisher_if_needed():
|
||||
if get_publisher() is not None:
|
||||
return get_publisher()
|
||||
# initialize publisher in first request
|
||||
config = ConfigParser.ConfigParser()
|
||||
if settings.WCS_LEGACY_CONFIG_FILE:
|
||||
config.read(settings.WCS_LEGACY_CONFIG_FILE)
|
||||
if hasattr(settings, 'WCS_EXTRA_MODULES') and settings.WCS_EXTRA_MODULES:
|
||||
if not config.has_section('extra'):
|
||||
config.add_section('extra')
|
||||
for i, extra in enumerate(settings.WCS_EXTRA_MODULES):
|
||||
config.set('extra', 'cmd_line_extra_%d' % i, extra)
|
||||
CompatWcsPublisher.configure(config)
|
||||
return CompatWcsPublisher.create_publisher()
|
||||
|
||||
|
||||
class TemplateWithFallbackView(TemplateView):
|
||||
quixote_response = None
|
||||
|
@ -192,7 +177,8 @@ class CompatWcsPublisher(WcsPublisher):
|
|||
quixote_lock = Lock()
|
||||
|
||||
def quixote(request):
|
||||
with quixote_lock:
|
||||
#with quixote_lock:
|
||||
if True:
|
||||
pub = get_publisher()
|
||||
compat_request = CompatHTTPRequest(request)
|
||||
return pub.process_request(compat_request)
|
||||
|
|
|
@ -14,12 +14,19 @@
|
|||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from .compat import init_publisher_if_needed, CompatHTTPRequest
|
||||
import thread
|
||||
import threading
|
||||
|
||||
from quixote import get_publisher
|
||||
from .compat import CompatHTTPRequest, CompatWcsPublisher
|
||||
|
||||
|
||||
class PublisherInitialisationMiddleware(object):
|
||||
'''Initializes the publisher according to the request server name.'''
|
||||
def process_request(self, request):
|
||||
pub = init_publisher_if_needed()
|
||||
pub = get_publisher()
|
||||
if not pub:
|
||||
pub = CompatWcsPublisher.create_publisher()
|
||||
compat_request = CompatHTTPRequest(request)
|
||||
pub.init_publish(compat_request)
|
||||
pub._set_request(compat_request)
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
# w.c.s. - web application for online forms
|
||||
# Copyright (C) 2005-2017 Entr'ouvert
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import threading
|
||||
import types
|
||||
import urlparse
|
||||
|
||||
import quixote
|
||||
import quixote.publish
|
||||
|
||||
_thread_local = threading.local()
|
||||
|
||||
cleanup_orig = quixote.publish.cleanup
|
||||
PublisherOrig = quixote.publish.Publisher
|
||||
|
||||
class Publisher(quixote.publish.Publisher):
|
||||
def __init__(self, root_directory, *args, **kwargs):
|
||||
try:
|
||||
PublisherOrig.__init__(self, root_directory, *args, **kwargs)
|
||||
except RuntimeError:
|
||||
pass
|
||||
_thread_local.publisher = self
|
||||
self.root_directory = root_directory
|
||||
self._request = None
|
||||
|
||||
def get_publisher():
|
||||
return getattr(_thread_local, 'publisher', None)
|
||||
|
||||
def get_request():
|
||||
return _thread_local.publisher.get_request()
|
||||
|
||||
def get_response():
|
||||
return _thread_local.publisher.get_request().response
|
||||
|
||||
def get_field(name, default=None):
|
||||
return _thread_local.publisher.get_request().get_field(name, default)
|
||||
|
||||
def get_cookie(name, default=None):
|
||||
return _thread_local.publisher.get_request().get_cookie(name, default)
|
||||
|
||||
def get_path(n=0):
|
||||
return _thread_local.publisher.get_request().get_path(n)
|
||||
|
||||
def redirect(location, permanent=False):
|
||||
"""(location : string, permanent : boolean = false) -> string
|
||||
|
||||
Create a redirection response. If the location is relative, then it
|
||||
will automatically be made absolute. The return value is an HTML
|
||||
document indicating the new URL (useful if the client browser does
|
||||
not honor the redirect).
|
||||
"""
|
||||
request = _thread_local.publisher.get_request()
|
||||
location = urlparse.urljoin(request.get_url(), str(location))
|
||||
return request.response.redirect(location, permanent)
|
||||
|
||||
def get_session():
|
||||
return _thread_local.publisher.get_request().session
|
||||
|
||||
def get_session_manager():
|
||||
return _thread_local.publisher.session_manager
|
||||
|
||||
def get_user():
|
||||
session = _thread_local.publisher.get_request().session
|
||||
if session is None:
|
||||
return None
|
||||
else:
|
||||
return session.user
|
||||
|
||||
def cleanup():
|
||||
cleanup_orig()
|
||||
_thread_local.publisher = None
|
||||
|
||||
|
||||
for key, value in locals().items():
|
||||
if type(value) in (types.FunctionType, types.TypeType, types.ClassType):
|
||||
setattr(quixote, key, value)
|
||||
setattr(quixote.publish, key, value)
|
|
@ -14,6 +14,9 @@
|
|||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import ConfigParser
|
||||
import django.apps
|
||||
from django.conf import settings
|
||||
from quixote import get_publisher
|
||||
|
||||
try:
|
||||
|
@ -33,7 +36,30 @@ def ngettext(*args):
|
|||
return message
|
||||
return unicode(pub.ngettext(*args), 'utf-8').encode(pub.site_charset)
|
||||
|
||||
from publisher import get_cfg, get_logger
|
||||
from publisher import get_cfg, get_logger, get_publisher_class
|
||||
import publisher
|
||||
publisher._ = _
|
||||
|
||||
|
||||
class AppConfig(django.apps.AppConfig):
|
||||
name = 'wcs.qommon'
|
||||
|
||||
def ready(self):
|
||||
config = ConfigParser.ConfigParser()
|
||||
if settings.WCS_LEGACY_CONFIG_FILE:
|
||||
config.read(settings.WCS_LEGACY_CONFIG_FILE)
|
||||
if hasattr(settings, 'WCS_EXTRA_MODULES') and settings.WCS_EXTRA_MODULES:
|
||||
if not config.has_section('extra'):
|
||||
config.add_section('extra')
|
||||
for i, extra in enumerate(settings.WCS_EXTRA_MODULES):
|
||||
config.set('extra', 'cmd_line_extra_%d' % i, extra)
|
||||
|
||||
get_publisher_class().configure(config)
|
||||
get_publisher_class().register_tld_names = True
|
||||
get_publisher_class().init_publisher_class()
|
||||
|
||||
default_app_config = 'wcs.qommon.AppConfig'
|
||||
|
||||
|
||||
if lasso:
|
||||
if not hasattr(lasso, 'SAML2_SUPPORT'):
|
||||
|
|
|
@ -21,7 +21,6 @@ import quixote
|
|||
from quixote.errors import *
|
||||
from quixote.html import TemplateIO, htmltext
|
||||
|
||||
from qommon import _
|
||||
import template
|
||||
|
||||
|
||||
|
@ -31,6 +30,7 @@ class AccessForbiddenError(AccessError):
|
|||
self.location_hint = location_hint
|
||||
|
||||
def render(self):
|
||||
from qommon import _
|
||||
if self.public_msg:
|
||||
return template.error_page(self.public_msg, _('Access Forbidden'),
|
||||
continue_to = (get_publisher().get_root_url(), _('the homepage')),
|
||||
|
@ -63,6 +63,7 @@ class EmailError(Exception):
|
|||
|
||||
class InternalServerError(object):
|
||||
def render(self):
|
||||
from qommon import _
|
||||
template.html_top(_('Oops, the server borked severely'))
|
||||
r = TemplateIO(html=True)
|
||||
|
||||
|
@ -115,6 +116,7 @@ TraversalError.description = N_(
|
|||
|
||||
|
||||
def format_publish_error(exc):
|
||||
from qommon import _
|
||||
if getattr(exc, 'public_msg', None):
|
||||
return template.error_page(exc.format(), _(exc.title))
|
||||
else:
|
||||
|
|
|
@ -1187,7 +1187,7 @@ class PasswordAuthMethod(AuthMethod):
|
|||
|
||||
@classmethod
|
||||
def register(cls):
|
||||
rdb = get_publisher().backoffice_directory_class
|
||||
rdb = get_publisher_class().backoffice_directory_class
|
||||
if rdb:
|
||||
rdb.register_directory('accounts', AccountsDirectory())
|
||||
|
||||
|
|
|
@ -57,8 +57,6 @@ import storage
|
|||
import strftime
|
||||
import urllib
|
||||
|
||||
from qommon import _
|
||||
|
||||
class ImmediateRedirectException(Exception):
|
||||
def __init__(self, location):
|
||||
self.location = location
|
||||
|
@ -802,16 +800,25 @@ class QommonPublisher(Publisher, object):
|
|||
cls.register_cronjob(CronJob(cls.clean_afterjobs, minutes=[random.randint(0, 59)]))
|
||||
cls.register_cronjob(CronJob(cls.clean_tempfiles, minutes=[random.randint(0, 59)]))
|
||||
|
||||
register_cron = False
|
||||
register_tld_names = False
|
||||
|
||||
_initialized = False
|
||||
@classmethod
|
||||
def create_publisher(cls, register_cron=True, register_tld_names=True):
|
||||
def init_publisher_class(cls):
|
||||
if cls._initialized:
|
||||
return
|
||||
cls._initialized = True
|
||||
cls.load_extra_dirs()
|
||||
cls.load_translations()
|
||||
if register_cron:
|
||||
if cls.register_cron:
|
||||
cls.register_cronjobs()
|
||||
|
||||
if register_tld_names:
|
||||
if cls.register_tld_names:
|
||||
cls.load_effective_tld_names()
|
||||
|
||||
@classmethod
|
||||
def create_publisher(cls, **kwargs):
|
||||
publisher = cls(cls.root_directory_class(),
|
||||
session_cookie_name = cls.APP_NAME,
|
||||
session_cookie_path = '/',
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from quixote.html import htmltext, TemplateIO
|
||||
from qommon import _
|
||||
|
||||
class Substitutions(object):
|
||||
substitutions_dict = {}
|
||||
|
@ -61,6 +60,7 @@ class Substitutions(object):
|
|||
|
||||
@classmethod
|
||||
def get_substitution_html_table(cls):
|
||||
from qommon import _
|
||||
r = TemplateIO(html=True)
|
||||
r += htmltext('<table id="substvars">')
|
||||
r += htmltext('<thead><tr><th>%s</th><th>%s</th><th>%s</th></tr></thead>' % (
|
||||
|
|
|
@ -24,7 +24,6 @@ from quixote.directory import Directory
|
|||
from quixote.util import StaticDirectory, StaticFile
|
||||
from quixote.html import htmltext, htmlescape, TemplateIO
|
||||
|
||||
from qommon import _
|
||||
import errors
|
||||
import ezt
|
||||
|
||||
|
@ -227,6 +226,7 @@ def html_top(title=None, default_org=None):
|
|||
|
||||
def error_page(error_message, error_title = None, exception = None, continue_to = None,
|
||||
location_hint = None):
|
||||
from qommon import _
|
||||
if not error_title:
|
||||
error_title = _('Error')
|
||||
if exception:
|
||||
|
|
|
@ -24,11 +24,11 @@ import xml.etree.ElementTree as ET
|
|||
from quixote import get_publisher
|
||||
|
||||
from qommon import _
|
||||
from qommon.misc import (simplify, http_get_page, http_post_request,
|
||||
get_variadic_url, JSONEncoder, json_loads)
|
||||
from qommon.misc import simplify, get_variadic_url, JSONEncoder, json_loads
|
||||
from qommon.xml_storage import XmlStorableObject
|
||||
from qommon.form import (CompositeWidget, StringWidget, WidgetDict,
|
||||
ComputedExpressionWidget, RadiobuttonsWidget, CheckboxWidget)
|
||||
import qommon.misc
|
||||
|
||||
from wcs.api_utils import sign_url, get_secret_and_orig, MissingSecret
|
||||
from wcs.workflows import WorkflowStatusItem
|
||||
|
@ -106,10 +106,10 @@ def call_webservice(url, qs_data=None, request_signature_key=None,
|
|||
# increase timeout for huge loads, one second every 65536
|
||||
# bytes, to match a country 512kbps DSL line.
|
||||
timeout += len(payload) / 65536
|
||||
response, status, data, auth_header = http_post_request(
|
||||
response, status, data, auth_header = qommon.misc.http_post_request(
|
||||
url, payload, headers=headers, timeout=timeout)
|
||||
else:
|
||||
response, status, data, auth_header = http_get_page(
|
||||
response, status, data, auth_header = qommon.misc.http_get_page(
|
||||
url, headers=headers, timeout=TIMEOUT)
|
||||
return (response, status, data)
|
||||
|
||||
|
|
Loading…
Reference in New Issue