forked from openlp/openlp
Head
This commit is contained in:
commit
3a0d0ff2ea
@ -115,7 +115,7 @@ def display_thumbnails(request, controller_name, log, dimensions, file_name, sli
|
||||
height = -1
|
||||
image = None
|
||||
if dimensions:
|
||||
match = re.search('(\d+)x(\d+)', dimensions)
|
||||
match = re.search(r'(\d+)x(\d+)', dimensions)
|
||||
if match:
|
||||
# let's make sure that the dimensions are within reason
|
||||
width = sorted([10, int(match.group(1)), 1000])[1]
|
||||
|
@ -39,7 +39,7 @@ log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _route_to_regex(route):
|
||||
"""
|
||||
r"""
|
||||
Convert a route to a regular expression
|
||||
|
||||
For example:
|
||||
|
@ -54,7 +54,7 @@ class ApiTab(SettingsTab):
|
||||
self.address_label.setObjectName('address_label')
|
||||
self.address_edit = QtWidgets.QLineEdit(self.server_settings_group_box)
|
||||
self.address_edit.setSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
|
||||
self.address_edit.setValidator(QtGui.QRegExpValidator(QtCore.QRegExp('\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}'),
|
||||
self.address_edit.setValidator(QtGui.QRegExpValidator(QtCore.QRegExp(r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}'),
|
||||
self))
|
||||
self.address_edit.setObjectName('address_edit')
|
||||
self.server_settings_layout.addRow(self.address_label, self.address_edit)
|
||||
|
@ -64,13 +64,17 @@ def get_local_ip4():
|
||||
log.debug('Getting local IPv4 interface(es) information')
|
||||
my_ip4 = {}
|
||||
for iface in QNetworkInterface.allInterfaces():
|
||||
log.debug('Checking for isValid and flags == IsUP | IsRunning')
|
||||
if not iface.isValid() or not (iface.flags() & (QNetworkInterface.IsUp | QNetworkInterface.IsRunning)):
|
||||
continue
|
||||
log.debug('Checking address(es) protocol')
|
||||
for address in iface.addressEntries():
|
||||
ip = address.ip()
|
||||
# NOTE: Next line will skip if interface is localhost - keep for now until we decide about it later
|
||||
# if (ip.protocol() == QAbstractSocket.IPv4Protocol) and (ip != QHostAddress.LocalHost):
|
||||
log.debug('Checking for protocol == IPv4Protocol')
|
||||
if ip.protocol() == QAbstractSocket.IPv4Protocol:
|
||||
log.debug('Getting interface information')
|
||||
my_ip4[iface.name()] = {'ip': ip.toString(),
|
||||
'broadcast': address.broadcast().toString(),
|
||||
'netmask': address.netmask().toString(),
|
||||
@ -79,12 +83,19 @@ def get_local_ip4():
|
||||
ip.toIPv4Address()).toString()
|
||||
}
|
||||
log.debug('Adding {iface} to active list'.format(iface=iface.name()))
|
||||
if 'localhost' in my_ip4:
|
||||
log.debug('Renaming windows localhost to lo')
|
||||
my_ip4['lo'] = my_ip4['localhost']
|
||||
my_ip4.pop('localhost')
|
||||
if len(my_ip4) == 0:
|
||||
log.warning('No active IPv4 network interfaces detected')
|
||||
if len(my_ip4) == 1:
|
||||
if 'lo' in my_ip4:
|
||||
# No active interfaces - so leave localhost in there
|
||||
log.warning('No active IPv4 interfaces found except localhost')
|
||||
else:
|
||||
# Since we have a valid IP4 interface, remove localhost
|
||||
if 'lo' in my_ip4:
|
||||
log.debug('Found at least one IPv4 interface, removing localhost')
|
||||
my_ip4.pop('lo')
|
||||
|
||||
|
@ -32,6 +32,7 @@ import requests
|
||||
|
||||
from openlp.core.common import trace_error_handler
|
||||
from openlp.core.common.registry import Registry
|
||||
from openlp.core.common.settings import ProxyMode, Settings
|
||||
|
||||
log = logging.getLogger(__name__ + '.__init__')
|
||||
|
||||
@ -64,6 +65,39 @@ CONNECTION_TIMEOUT = 30
|
||||
CONNECTION_RETRIES = 2
|
||||
|
||||
|
||||
def get_proxy_settings(mode=None):
|
||||
"""
|
||||
Create a dictionary containing the proxy settings.
|
||||
|
||||
:param ProxyMode | None mode: Specify the source of the proxy settings
|
||||
:return: A dict using the format expected by the requests library.
|
||||
:rtype: dict | None
|
||||
"""
|
||||
settings = Settings()
|
||||
if mode is None:
|
||||
mode = settings.value('advanced/proxy mode')
|
||||
if mode == ProxyMode.NO_PROXY:
|
||||
return {'http': None, 'https': None}
|
||||
elif mode == ProxyMode.SYSTEM_PROXY:
|
||||
# The requests library defaults to using the proxy settings in the environment variables
|
||||
return
|
||||
elif mode == ProxyMode.MANUAL_PROXY:
|
||||
http_addr = settings.value('advanced/proxy http')
|
||||
https_addr = settings.value('advanced/proxy https')
|
||||
username = settings.value('advanced/proxy username')
|
||||
password = settings.value('advanced/proxy password')
|
||||
basic_auth = ''
|
||||
if username:
|
||||
basic_auth = '{username}:{password}@'.format(username=username, password=password)
|
||||
http_value = None
|
||||
https_value = None
|
||||
if http_addr:
|
||||
http_value = 'http://{basic_auth}{http_addr}'.format(basic_auth=basic_auth, http_addr=http_addr)
|
||||
if https_addr:
|
||||
https_value = 'https://{basic_auth}{https_addr}'.format(basic_auth=basic_auth, https_addr=https_addr)
|
||||
return {'http': http_value, 'https': https_value}
|
||||
|
||||
|
||||
def get_user_agent():
|
||||
"""
|
||||
Return a user agent customised for the platform the user is on.
|
||||
@ -75,14 +109,15 @@ def get_user_agent():
|
||||
return browser_list[random_index]
|
||||
|
||||
|
||||
def get_web_page(url, headers=None, update_openlp=False, proxies=None):
|
||||
def get_web_page(url, headers=None, update_openlp=False, proxy=None):
|
||||
"""
|
||||
Attempts to download the webpage at url and returns that page or None.
|
||||
|
||||
:param url: The URL to be downloaded.
|
||||
:param header: An optional HTTP header to pass in the request to the web server.
|
||||
:param update_openlp: Tells OpenLP to update itself if the page is successfully downloaded.
|
||||
Defaults to False.
|
||||
:param dict | None headers: An optional HTTP header to pass in the request to the web server.
|
||||
:param update_openlp: Tells OpenLP to update itself if the page is successfully downloaded. Defaults to False.
|
||||
:param dict | ProxyMode | None proxy: ProxyMode enum or a dictionary containing the proxy servers, with their types
|
||||
as the key e.g. {'http': 'http://proxyserver:port', 'https': 'https://proxyserver:port'}
|
||||
"""
|
||||
if not url:
|
||||
return None
|
||||
@ -90,11 +125,13 @@ def get_web_page(url, headers=None, update_openlp=False, proxies=None):
|
||||
headers = {}
|
||||
if 'user-agent' not in [key.lower() for key in headers.keys()]:
|
||||
headers['User-Agent'] = get_user_agent()
|
||||
if not isinstance(proxy, dict):
|
||||
proxy = get_proxy_settings(mode=proxy)
|
||||
log.debug('Downloading URL = %s' % url)
|
||||
retries = 0
|
||||
while retries < CONNECTION_RETRIES:
|
||||
try:
|
||||
response = requests.get(url, headers=headers, proxies=proxies, timeout=float(CONNECTION_TIMEOUT))
|
||||
response = requests.get(url, headers=headers, proxies=proxy, timeout=float(CONNECTION_TIMEOUT))
|
||||
log.debug('Downloaded page {url}'.format(url=response.url))
|
||||
break
|
||||
except OSError:
|
||||
|
@ -26,6 +26,7 @@ import datetime
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
from enum import IntEnum
|
||||
from tempfile import gettempdir
|
||||
|
||||
from PyQt5 import QtCore, QtGui
|
||||
@ -38,6 +39,13 @@ log = logging.getLogger(__name__)
|
||||
|
||||
__version__ = 2
|
||||
|
||||
|
||||
class ProxyMode(IntEnum):
|
||||
NO_PROXY = 1
|
||||
SYSTEM_PROXY = 2
|
||||
MANUAL_PROXY = 3
|
||||
|
||||
|
||||
# Fix for bug #1014422.
|
||||
X11_BYPASS_DEFAULT = True
|
||||
if is_linux(): # pragma: no cover
|
||||
@ -116,6 +124,11 @@ class Settings(QtCore.QSettings):
|
||||
'advanced/print file meta data': False,
|
||||
'advanced/print notes': False,
|
||||
'advanced/print slide text': False,
|
||||
'advanced/proxy mode': ProxyMode.SYSTEM_PROXY,
|
||||
'advanced/proxy http': '',
|
||||
'advanced/proxy https': '',
|
||||
'advanced/proxy username': '',
|
||||
'advanced/proxy password': '',
|
||||
'advanced/recent file count': 4,
|
||||
'advanced/save current plugin': False,
|
||||
'advanced/slide limits': SlideLimits.End,
|
||||
|
@ -415,7 +415,7 @@ def expand_chords(text):
|
||||
chords_on_prev_line = True
|
||||
# Matches a chord, a tail, a remainder and a line end. See expand_and_align_chords_in_line() for more info.
|
||||
new_line += re.sub(r'\[(.*?)\]([\u0080-\uFFFF,\w]*)'
|
||||
'([\u0080-\uFFFF,\w,\s,\.,\,,\!,\?,\;,\:,\|,\",\',\-,\_]*)(\Z)?',
|
||||
r'([\u0080-\uFFFF,\w,\s,\.,\,,\!,\?,\;,\:,\|,\",\',\-,\_]*)(\Z)?',
|
||||
expand_and_align_chords_in_line, line)
|
||||
new_line += '</span>'
|
||||
expanded_text_lines.append(new_line)
|
||||
|
@ -19,7 +19,7 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
"""
|
||||
r"""
|
||||
This module is responsible for generating the HTML for :class:`~openlp.core.ui.maindisplay`. The ``build_html`` function
|
||||
is the function which has to be called from outside. The generated and returned HTML will look similar to this::
|
||||
|
||||
@ -416,7 +416,7 @@ from openlp.core.lib.theme import BackgroundType, BackgroundGradientType, Vertic
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
HTML_SRC = Template("""
|
||||
HTML_SRC = Template(r"""
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
|
@ -338,7 +338,7 @@ class PJLinkCommands(object):
|
||||
# Due to stupid projectors not following standards (Optoma, BenQ comes to mind),
|
||||
# AND the different responses that can be received, the semi-permanent way to
|
||||
# fix the class reply is to just remove all non-digit characters.
|
||||
chk = re.findall('\d', data)
|
||||
chk = re.findall(r'\d', data)
|
||||
if len(chk) < 1:
|
||||
log.error('({ip}) No numbers found in class version reply "{data}" - '
|
||||
'defaulting to class "1"'.format(ip=self.entry.name, data=data))
|
||||
|
@ -36,6 +36,7 @@ from openlp.core.ui.style import HAS_DARK_STYLE
|
||||
from openlp.core.ui.icons import UiIcons
|
||||
from openlp.core.widgets.edits import PathEdit
|
||||
from openlp.core.widgets.enums import PathEditType
|
||||
from openlp.core.widgets.widgets import ProxyWidget
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@ -77,6 +78,9 @@ class AdvancedTab(SettingsTab):
|
||||
self.media_plugin_check_box = QtWidgets.QCheckBox(self.ui_group_box)
|
||||
self.media_plugin_check_box.setObjectName('media_plugin_check_box')
|
||||
self.ui_layout.addRow(self.media_plugin_check_box)
|
||||
self.hide_mouse_check_box = QtWidgets.QCheckBox(self.ui_group_box)
|
||||
self.hide_mouse_check_box.setObjectName('hide_mouse_check_box')
|
||||
self.ui_layout.addWidget(self.hide_mouse_check_box)
|
||||
self.double_click_live_check_box = QtWidgets.QCheckBox(self.ui_group_box)
|
||||
self.double_click_live_check_box.setObjectName('double_click_live_check_box')
|
||||
self.ui_layout.addRow(self.double_click_live_check_box)
|
||||
@ -117,6 +121,24 @@ class AdvancedTab(SettingsTab):
|
||||
self.use_dark_style_checkbox = QtWidgets.QCheckBox(self.ui_group_box)
|
||||
self.use_dark_style_checkbox.setObjectName('use_dark_style_checkbox')
|
||||
self.ui_layout.addRow(self.use_dark_style_checkbox)
|
||||
# Service Item Slide Limits
|
||||
self.slide_group_box = QtWidgets.QGroupBox(self.left_column)
|
||||
self.slide_group_box.setObjectName('slide_group_box')
|
||||
self.slide_layout = QtWidgets.QVBoxLayout(self.slide_group_box)
|
||||
self.slide_layout.setObjectName('slide_layout')
|
||||
self.slide_label = QtWidgets.QLabel(self.slide_group_box)
|
||||
self.slide_label.setWordWrap(True)
|
||||
self.slide_layout.addWidget(self.slide_label)
|
||||
self.end_slide_radio_button = QtWidgets.QRadioButton(self.slide_group_box)
|
||||
self.end_slide_radio_button.setObjectName('end_slide_radio_button')
|
||||
self.slide_layout.addWidget(self.end_slide_radio_button)
|
||||
self.wrap_slide_radio_button = QtWidgets.QRadioButton(self.slide_group_box)
|
||||
self.wrap_slide_radio_button.setObjectName('wrap_slide_radio_button')
|
||||
self.slide_layout.addWidget(self.wrap_slide_radio_button)
|
||||
self.next_item_radio_button = QtWidgets.QRadioButton(self.slide_group_box)
|
||||
self.next_item_radio_button.setObjectName('next_item_radio_button')
|
||||
self.slide_layout.addWidget(self.next_item_radio_button)
|
||||
self.left_layout.addWidget(self.slide_group_box)
|
||||
# Data Directory
|
||||
self.data_directory_group_box = QtWidgets.QGroupBox(self.left_column)
|
||||
self.data_directory_group_box.setObjectName('data_directory_group_box')
|
||||
@ -143,33 +165,6 @@ class AdvancedTab(SettingsTab):
|
||||
self.data_directory_layout.addRow(self.data_directory_copy_check_layout)
|
||||
self.data_directory_layout.addRow(self.new_data_directory_has_files_label)
|
||||
self.left_layout.addWidget(self.data_directory_group_box)
|
||||
# Hide mouse
|
||||
self.hide_mouse_group_box = QtWidgets.QGroupBox(self.right_column)
|
||||
self.hide_mouse_group_box.setObjectName('hide_mouse_group_box')
|
||||
self.hide_mouse_layout = QtWidgets.QVBoxLayout(self.hide_mouse_group_box)
|
||||
self.hide_mouse_layout.setObjectName('hide_mouse_layout')
|
||||
self.hide_mouse_check_box = QtWidgets.QCheckBox(self.hide_mouse_group_box)
|
||||
self.hide_mouse_check_box.setObjectName('hide_mouse_check_box')
|
||||
self.hide_mouse_layout.addWidget(self.hide_mouse_check_box)
|
||||
self.right_layout.addWidget(self.hide_mouse_group_box)
|
||||
# Service Item Slide Limits
|
||||
self.slide_group_box = QtWidgets.QGroupBox(self.right_column)
|
||||
self.slide_group_box.setObjectName('slide_group_box')
|
||||
self.slide_layout = QtWidgets.QVBoxLayout(self.slide_group_box)
|
||||
self.slide_layout.setObjectName('slide_layout')
|
||||
self.slide_label = QtWidgets.QLabel(self.slide_group_box)
|
||||
self.slide_label.setWordWrap(True)
|
||||
self.slide_layout.addWidget(self.slide_label)
|
||||
self.end_slide_radio_button = QtWidgets.QRadioButton(self.slide_group_box)
|
||||
self.end_slide_radio_button.setObjectName('end_slide_radio_button')
|
||||
self.slide_layout.addWidget(self.end_slide_radio_button)
|
||||
self.wrap_slide_radio_button = QtWidgets.QRadioButton(self.slide_group_box)
|
||||
self.wrap_slide_radio_button.setObjectName('wrap_slide_radio_button')
|
||||
self.slide_layout.addWidget(self.wrap_slide_radio_button)
|
||||
self.next_item_radio_button = QtWidgets.QRadioButton(self.slide_group_box)
|
||||
self.next_item_radio_button.setObjectName('next_item_radio_button')
|
||||
self.slide_layout.addWidget(self.next_item_radio_button)
|
||||
self.right_layout.addWidget(self.slide_group_box)
|
||||
# Display Workarounds
|
||||
self.display_workaround_group_box = QtWidgets.QGroupBox(self.right_column)
|
||||
self.display_workaround_group_box.setObjectName('display_workaround_group_box')
|
||||
@ -224,6 +219,9 @@ class AdvancedTab(SettingsTab):
|
||||
self.service_name_example.setObjectName('service_name_example')
|
||||
self.service_name_layout.addRow(self.service_name_example_label, self.service_name_example)
|
||||
self.right_layout.addWidget(self.service_name_group_box)
|
||||
# Proxies
|
||||
self.proxy_widget = ProxyWidget(self.right_column)
|
||||
self.right_layout.addWidget(self.proxy_widget)
|
||||
# After the last item on each side, add some spacing
|
||||
self.left_layout.addStretch()
|
||||
self.right_layout.addStretch()
|
||||
@ -312,7 +310,6 @@ class AdvancedTab(SettingsTab):
|
||||
translate('OpenLP.AdvancedTab',
|
||||
'Revert to the default service name "{name}".').format(name=UiStrings().DefaultServiceName))
|
||||
self.service_name_example_label.setText(translate('OpenLP.AdvancedTab', 'Example:'))
|
||||
self.hide_mouse_group_box.setTitle(translate('OpenLP.AdvancedTab', 'Mouse Cursor'))
|
||||
self.hide_mouse_check_box.setText(translate('OpenLP.AdvancedTab', 'Hide mouse cursor when over display window'))
|
||||
self.data_directory_new_label.setText(translate('OpenLP.AdvancedTab', 'Path:'))
|
||||
self.data_directory_cancel_button.setText(translate('OpenLP.AdvancedTab', 'Cancel'))
|
||||
@ -335,6 +332,7 @@ class AdvancedTab(SettingsTab):
|
||||
self.wrap_slide_radio_button.setText(translate('OpenLP.GeneralTab', '&Wrap around'))
|
||||
self.next_item_radio_button.setText(translate('OpenLP.GeneralTab', '&Move to next/previous service item'))
|
||||
self.search_as_type_check_box.setText(translate('SongsPlugin.GeneralTab', 'Enable search as you type'))
|
||||
self.proxy_widget.retranslate_ui()
|
||||
|
||||
def load(self):
|
||||
"""
|
||||
@ -437,6 +435,7 @@ class AdvancedTab(SettingsTab):
|
||||
if HAS_DARK_STYLE:
|
||||
settings.setValue('use_dark_style', self.use_dark_style_checkbox.isChecked())
|
||||
settings.endGroup()
|
||||
self.proxy_widget.save()
|
||||
|
||||
def on_search_as_type_check_box_changed(self, check_state):
|
||||
self.is_search_as_you_type_enabled = (check_state == QtCore.Qt.Checked)
|
||||
|
@ -80,7 +80,7 @@ def get_media_players():
|
||||
"""
|
||||
log.debug('get_media_players')
|
||||
saved_players = Settings().value('media/players')
|
||||
reg_ex = QtCore.QRegExp(".*\[(.*)\].*")
|
||||
reg_ex = QtCore.QRegExp(r'.*\[(.*)\].*')
|
||||
if Settings().value('media/override player') == QtCore.Qt.Checked:
|
||||
if reg_ex.exactMatch(saved_players):
|
||||
overridden_player = '{text}'.format(text=reg_ex.cap(1))
|
||||
|
@ -1127,7 +1127,7 @@ class SlideController(DisplayController, LogMixin, RegistryProperties):
|
||||
# done by the thread holding the lock. If it is a "start" slide, we must wait for the lock, but only for 0.2
|
||||
# seconds, since we don't want to cause a deadlock
|
||||
timeout = 0.2 if start else -1
|
||||
if not self.slide_selected_lock.acquire(start, timeout):
|
||||
if not self.slide_selected_lock.acquire(start, timeout): # pylint: disable=too-many-function-args
|
||||
if start:
|
||||
self.log_debug('Could not get lock in slide_selected after waiting %f, skip to avoid deadlock.'
|
||||
% timeout)
|
||||
|
132
openlp/core/widgets/widgets.py
Normal file
132
openlp/core/widgets/widgets.py
Normal file
@ -0,0 +1,132 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
|
||||
|
||||
###############################################################################
|
||||
# OpenLP - Open Source Lyrics Projection #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Copyright (c) 2008-2018 OpenLP Developers #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# 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; version 2 of the License. #
|
||||
# #
|
||||
# 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, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
"""
|
||||
The :mod:`~openlp.core.widgets.widgets` module contains custom widgets used in OpenLP
|
||||
"""
|
||||
from PyQt5 import QtWidgets
|
||||
|
||||
from openlp.core.common.i18n import translate
|
||||
from openlp.core.common.settings import ProxyMode, Settings
|
||||
|
||||
|
||||
class ProxyWidget(QtWidgets.QGroupBox):
|
||||
"""
|
||||
A proxy settings widget that implements loading and saving its settings.
|
||||
"""
|
||||
def __init__(self, parent=None):
|
||||
"""
|
||||
Initialise the widget.
|
||||
|
||||
:param QtWidgets.QWidget | None parent: The widgets parent
|
||||
"""
|
||||
super().__init__(parent)
|
||||
self._setup()
|
||||
|
||||
def _setup(self):
|
||||
"""
|
||||
A setup method seperate from __init__ to allow easier testing
|
||||
"""
|
||||
self.setup_ui()
|
||||
self.load()
|
||||
|
||||
def setup_ui(self):
|
||||
"""
|
||||
Create the widget layout and sub widgets
|
||||
"""
|
||||
self.layout = QtWidgets.QFormLayout(self)
|
||||
self.radio_group = QtWidgets.QButtonGroup(self)
|
||||
self.no_proxy_radio = QtWidgets.QRadioButton('', self)
|
||||
self.radio_group.addButton(self.no_proxy_radio, ProxyMode.NO_PROXY)
|
||||
self.layout.setWidget(0, QtWidgets.QFormLayout.SpanningRole, self.no_proxy_radio)
|
||||
self.use_sysem_proxy_radio = QtWidgets.QRadioButton('', self)
|
||||
self.radio_group.addButton(self.use_sysem_proxy_radio, ProxyMode.SYSTEM_PROXY)
|
||||
self.layout.setWidget(1, QtWidgets.QFormLayout.SpanningRole, self.use_sysem_proxy_radio)
|
||||
self.manual_proxy_radio = QtWidgets.QRadioButton('', self)
|
||||
self.radio_group.addButton(self.manual_proxy_radio, ProxyMode.MANUAL_PROXY)
|
||||
self.layout.setWidget(2, QtWidgets.QFormLayout.SpanningRole, self.manual_proxy_radio)
|
||||
self.http_edit = QtWidgets.QLineEdit(self)
|
||||
self.layout.addRow('HTTP:', self.http_edit)
|
||||
self.https_edit = QtWidgets.QLineEdit(self)
|
||||
self.layout.addRow('HTTPS:', self.https_edit)
|
||||
self.username_edit = QtWidgets.QLineEdit(self)
|
||||
self.layout.addRow('Username:', self.username_edit)
|
||||
self.password_edit = QtWidgets.QLineEdit(self)
|
||||
self.password_edit.setEchoMode(QtWidgets.QLineEdit.Password)
|
||||
self.layout.addRow('Password:', self.password_edit)
|
||||
# Signal / Slots
|
||||
self.radio_group.buttonToggled.connect(self.on_radio_group_button_toggled)
|
||||
|
||||
def on_radio_group_button_toggled(self, button, checked):
|
||||
"""
|
||||
Handles the toggled signal on the radio buttons. The signal is emitted twice if a radio butting being toggled on
|
||||
causes another radio button in the group to be toggled off.
|
||||
|
||||
En/Disables the `Manual Proxy` line edits depending on the currently selected radio button
|
||||
|
||||
:param QtWidgets.QRadioButton button: The button that has toggled
|
||||
:param bool checked: The buttons new state
|
||||
"""
|
||||
id = self.radio_group.id(button) # The work around (see above comment)
|
||||
enable_manual_edits = id == ProxyMode.MANUAL_PROXY and checked
|
||||
self.http_edit.setEnabled(enable_manual_edits)
|
||||
self.https_edit.setEnabled(enable_manual_edits)
|
||||
self.username_edit.setEnabled(enable_manual_edits)
|
||||
self.password_edit.setEnabled(enable_manual_edits)
|
||||
|
||||
def retranslate_ui(self):
|
||||
"""
|
||||
Translate the Ui
|
||||
"""
|
||||
self.setTitle(translate('OpenLP.ProxyWidget', 'Proxy Server Settings'))
|
||||
self.no_proxy_radio.setText(translate('OpenLP.ProxyWidget', 'No prox&y'))
|
||||
self.use_sysem_proxy_radio.setText(translate('OpenLP.ProxyWidget', '&Use system proxy'))
|
||||
self.manual_proxy_radio.setText(translate('OpenLP.ProxyWidget', '&Manual proxy configuration'))
|
||||
proxy_example = translate('OpenLP.ProxyWidget', 'e.g. proxy_server_address:port_no')
|
||||
self.layout.labelForField(self.http_edit).setText(translate('OpenLP.ProxyWidget', 'HTTP:'))
|
||||
self.http_edit.setPlaceholderText(proxy_example)
|
||||
self.layout.labelForField(self.https_edit).setText(translate('OpenLP.ProxyWidget', 'HTTPS:'))
|
||||
self.https_edit.setPlaceholderText(proxy_example)
|
||||
self.layout.labelForField(self.username_edit).setText(translate('OpenLP.ProxyWidget', 'Username:'))
|
||||
self.layout.labelForField(self.password_edit).setText(translate('OpenLP.ProxyWidget', 'Password:'))
|
||||
|
||||
def load(self):
|
||||
"""
|
||||
Load the data from the settings to the widget.
|
||||
"""
|
||||
settings = Settings()
|
||||
checked_radio = self.radio_group.button(settings.value('advanced/proxy mode'))
|
||||
checked_radio.setChecked(True)
|
||||
self.http_edit.setText(settings.value('advanced/proxy http'))
|
||||
self.https_edit.setText(settings.value('advanced/proxy https'))
|
||||
self.username_edit.setText(settings.value('advanced/proxy username'))
|
||||
self.password_edit.setText(settings.value('advanced/proxy password'))
|
||||
|
||||
def save(self):
|
||||
"""
|
||||
Save the widget data to the settings
|
||||
"""
|
||||
settings = Settings() # TODO: Migrate from old system
|
||||
settings.setValue('advanced/proxy mode', self.radio_group.checkedId())
|
||||
settings.setValue('advanced/proxy http', self.http_edit.text())
|
||||
settings.setValue('advanced/proxy https', self.https_edit.text())
|
||||
settings.setValue('advanced/proxy username', self.username_edit.text())
|
||||
settings.setValue('advanced/proxy password', self.password_edit.text())
|
@ -183,7 +183,7 @@ class EditBibleForm(QtWidgets.QDialog, Ui_EditBibleDialog, RegistryProperties):
|
||||
"""
|
||||
Validate a book.
|
||||
"""
|
||||
book_regex = re.compile('[\d]*[^\d]+$')
|
||||
book_regex = re.compile(r'[\d]*[^\d]+$')
|
||||
if not new_book_name:
|
||||
self.book_name_edit[abbreviation].setFocus()
|
||||
critical_error_message_box(
|
||||
|
@ -217,7 +217,7 @@ def update_reference_separators():
|
||||
# add various Unicode alternatives
|
||||
source_string = source_string.replace('-', '(?:[-\u00AD\u2010\u2011\u2012\u2014\u2014\u2212\uFE63\uFF0D])')
|
||||
source_string = source_string.replace(',', '(?:[,\u201A])')
|
||||
REFERENCE_SEPARATORS['sep_{role}'.format(role=role)] = '\s*(?:{source})\s*'.format(source=source_string)
|
||||
REFERENCE_SEPARATORS['sep_{role}'.format(role=role)] = r'\s*(?:{source})\s*'.format(source=source_string)
|
||||
REFERENCE_SEPARATORS['sep_{role}_default'.format(role=role)] = default_separators[index]
|
||||
# verse range match: (<chapter>:)?<verse>(-((<chapter>:)?<verse>|end)?)?
|
||||
range_regex = '(?:(?P<from_chapter>[0-9]+){sep_v})?' \
|
||||
@ -255,7 +255,7 @@ def get_reference_match(match_type):
|
||||
|
||||
|
||||
def parse_reference(reference, bible, language_selection, book_ref_id=False):
|
||||
"""
|
||||
r"""
|
||||
This is the next generation über-awesome function that takes a person's typed in string and converts it to a list
|
||||
of references to be queried from the Bible database files.
|
||||
|
||||
|
@ -42,7 +42,7 @@ from openlp.plugins.bibles.lib import DisplayStyle, LayoutStyle, VerseReferenceL
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
VALID_TEXT_SEARCH = re.compile('\w\w\w')
|
||||
VALID_TEXT_SEARCH = re.compile(r'\w\w\w')
|
||||
|
||||
|
||||
def get_reference_separators():
|
||||
|
@ -207,7 +207,7 @@ class MediaClipSelectorForm(QtWidgets.QDialog, Ui_MediaClipSelector, RegistryPro
|
||||
# detect if we're dealing with a DVD or CD, so we use different loading approaches depending on the OS.
|
||||
if is_win():
|
||||
# If the given path is in the format "D:\" or "D:", prefix it with "/" to make VLC happy
|
||||
pattern = re.compile('^\w:\\\\*$')
|
||||
pattern = re.compile(r'^\w:\\\\*$')
|
||||
if pattern.match(path):
|
||||
path = '/' + path
|
||||
self.vlc_media = self.vlc_instance.media_new_location('dvd://' + path)
|
||||
|
@ -105,7 +105,7 @@ class EditSongForm(QtWidgets.QDialog, Ui_EditSongDialog, RegistryProperties):
|
||||
self.topics_list_view.setSortingEnabled(False)
|
||||
self.topics_list_view.setAlternatingRowColors(True)
|
||||
self.audio_list_widget.setAlternatingRowColors(True)
|
||||
self.find_verse_split = re.compile('---\[\]---\n')
|
||||
self.find_verse_split = re.compile(r'---\[\]---\n')
|
||||
self.whitespace = re.compile(r'\W+')
|
||||
self.find_tags = re.compile(r'\{/?\w+\}')
|
||||
|
||||
@ -316,7 +316,7 @@ class EditSongForm(QtWidgets.QDialog, Ui_EditSongDialog, RegistryProperties):
|
||||
multiple.append(verse_tag)
|
||||
self.song.lyrics = str(sxml.extract_xml(), 'utf-8')
|
||||
for verse in multiple:
|
||||
self.song.verse_order = re.sub('([' + verse.upper() + verse.lower() + '])(\W|$)',
|
||||
self.song.verse_order = re.sub(r'([' + verse.upper() + verse.lower() + r'])(\W|$)',
|
||||
r'\g<1>1\2', self.song.verse_order)
|
||||
except:
|
||||
log.exception('Problem processing song Lyrics \n{xml}'.format(xml=sxml.dump_xml()))
|
||||
|
@ -557,7 +557,7 @@ def transpose_lyrics(lyrics, transpose_value):
|
||||
:return: The transposed lyrics
|
||||
"""
|
||||
# Split text by verse delimiter - both normal and optional
|
||||
verse_list = re.split('(---\[.+?:.+?\]---|\[---\])', lyrics)
|
||||
verse_list = re.split(r'(---\[.+?:.+?\]---|\[---\])', lyrics)
|
||||
transposed_lyrics = ''
|
||||
notation = Settings().value('songs/chord notation')
|
||||
for verse in verse_list:
|
||||
@ -580,7 +580,7 @@ def transpose_verse(verse_text, transpose_value, notation):
|
||||
if '[' not in verse_text:
|
||||
return verse_text
|
||||
# Split the lyrics based on chord tags
|
||||
lyric_list = re.split('(\[|\]|/)', verse_text)
|
||||
lyric_list = re.split(r'(\[|\]|/)', verse_text)
|
||||
transposed_lyrics = ''
|
||||
in_tag = False
|
||||
for word in lyric_list:
|
||||
|
@ -73,7 +73,7 @@ class DreamBeamImport(SongImport):
|
||||
|
||||
Valid extensions for a DreamBeam song file are:
|
||||
|
||||
* \*.xml
|
||||
* .xml
|
||||
"""
|
||||
|
||||
def do_import(self):
|
||||
|
@ -37,7 +37,7 @@ class EasySlidesImport(SongImport):
|
||||
Import songs exported from EasySlides
|
||||
|
||||
The format example is here:
|
||||
http://wiki.openlp.org/Development:EasySlides\_-_Song_Data_Format
|
||||
http://wiki.openlp.org/Development:EasySlides_-_Song_Data_Format
|
||||
"""
|
||||
def __init__(self, manager, **kwargs):
|
||||
"""
|
||||
@ -210,7 +210,7 @@ class EasySlidesImport(SongImport):
|
||||
vn = '1'
|
||||
# have we got any digits?
|
||||
# If so, versenumber is everything from the digits to the end
|
||||
match = re.match('(.*)(\d+.*)', marker)
|
||||
match = re.match(r'(.*)(\d+.*)', marker)
|
||||
if match:
|
||||
marker = match.group(1).strip()
|
||||
vn = match.group(2)
|
||||
|
@ -273,15 +273,15 @@ class FoilPresenter(object):
|
||||
elif copyright.find('C,)') != -1:
|
||||
temp = copyright.partition('C,)')
|
||||
copyright = temp[0]
|
||||
copyright = re.compile('\\n').sub(' ', copyright)
|
||||
copyright = re.compile('\(.*\)').sub('', copyright)
|
||||
copyright = re.compile(r'\\n').sub(' ', copyright)
|
||||
copyright = re.compile(r'\(.*\)').sub('', copyright)
|
||||
if copyright.find('Rechte') != -1:
|
||||
temp = copyright.partition('Rechte')
|
||||
copyright = temp[0]
|
||||
markers = ['Text +u\.?n?d? +Melodie[\w\,\. ]*:',
|
||||
'Text +u\.?n?d? +Musik', 'T & M', 'Melodie und Satz',
|
||||
'Text[\w\,\. ]*:', 'Melodie', 'Musik', 'Satz',
|
||||
'Weise', '[dD]eutsch', '[dD]t[\.\:]', 'Englisch',
|
||||
markers = [r'Text +u\.?n?d? +Melodie[\w\,\. ]*:',
|
||||
r'Text +u\.?n?d? +Musik', 'T & M', 'Melodie und Satz',
|
||||
r'Text[\w\,\. ]*:', 'Melodie', 'Musik', 'Satz',
|
||||
'Weise', '[dD]eutsch', r'[dD]t[\.\:]', 'Englisch',
|
||||
'[oO]riginal', 'Bearbeitung', '[R|r]efrain']
|
||||
for marker in markers:
|
||||
copyright = re.compile(marker).sub('<marker>', copyright, re.U)
|
||||
@ -301,17 +301,17 @@ class FoilPresenter(object):
|
||||
break
|
||||
author_temp = []
|
||||
for author in strings:
|
||||
temp = re.split(',(?=\D{2})|(?<=\D),|\/(?=\D{3,})|(?<=\D);', author)
|
||||
temp = re.split(r',(?=\D{2})|(?<=\D),|\/(?=\D{3,})|(?<=\D);', author)
|
||||
for tempx in temp:
|
||||
author_temp.append(tempx)
|
||||
for author in author_temp:
|
||||
regex = '^[\/,;\-\s\.]+|[\/,;\-\s\.]+$|\s*[0-9]{4}\s*[\-\/]?\s*([0-9]{4})?[\/,;\-\s\.]*$'
|
||||
regex = r'^[\/,;\-\s\.]+|[\/,;\-\s\.]+$|\s*[0-9]{4}\s*[\-\/]?\s*([0-9]{4})?[\/,;\-\s\.]*$'
|
||||
author = re.compile(regex).sub('', author)
|
||||
author = re.compile('[0-9]{1,2}\.\s?J(ahr)?h\.|um\s*$|vor\s*$').sub('', author)
|
||||
author = re.compile('[N|n]ach.*$').sub('', author)
|
||||
author = re.compile(r'[0-9]{1,2}\.\s?J(ahr)?h\.|um\s*$|vor\s*$').sub('', author)
|
||||
author = re.compile(r'[N|n]ach.*$').sub('', author)
|
||||
author = author.strip()
|
||||
if re.search('\w+\.?\s+\w{3,}\s+[a|u]nd\s|\w+\.?\s+\w{3,}\s+&\s', author, re.U):
|
||||
temp = re.split('\s[a|u]nd\s|\s&\s', author)
|
||||
if re.search(r'\w+\.?\s+\w{3,}\s+[a|u]nd\s|\w+\.?\s+\w{3,}\s+&\s', author, re.U):
|
||||
temp = re.split(r'\s[a|u]nd\s|\s&\s', author)
|
||||
for tempx in temp:
|
||||
tempx = tempx.strip()
|
||||
authors.append(tempx)
|
||||
|
@ -80,7 +80,7 @@ class LyrixImport(SongImport):
|
||||
continue
|
||||
# Detect and get CCLI number
|
||||
if line.lower().startswith('ccli'):
|
||||
ccli = re.findall('\d+', line)[0]
|
||||
ccli = re.findall(r'\d+', line)[0]
|
||||
try:
|
||||
# If the CCLI was found, we are near the end
|
||||
# Find author
|
||||
|
@ -156,7 +156,7 @@ class OpenSongImport(SongImport):
|
||||
ustring = str(root.__getattr__(attr))
|
||||
if isinstance(fn_or_string, str):
|
||||
if attr in ['ccli']:
|
||||
ustring = ''.join(re.findall('\d+', ustring))
|
||||
ustring = ''.join(re.findall(r'\d+', ustring))
|
||||
if ustring:
|
||||
setattr(self, fn_or_string, int(ustring))
|
||||
else:
|
||||
@ -231,7 +231,7 @@ class OpenSongImport(SongImport):
|
||||
content = this_line[1:right_bracket].lower()
|
||||
# have we got any digits? If so, verse number is everything from the digits to the end (openlp does not
|
||||
# have concept of part verses, so just ignore any non integers on the end (including floats))
|
||||
match = re.match('(\D*)(\d+)', content)
|
||||
match = re.match(r'(\D*)(\d+)', content)
|
||||
if match is not None:
|
||||
verse_tag = match.group(1)
|
||||
verse_num = match.group(2)
|
||||
@ -303,7 +303,7 @@ class OpenSongImport(SongImport):
|
||||
# whitespace.
|
||||
order = order.lower().split()
|
||||
for verse_def in order:
|
||||
match = re.match('(\D*)(\d+.*)', verse_def)
|
||||
match = re.match(r'(\D*)(\d+.*)', verse_def)
|
||||
if match is not None:
|
||||
verse_tag = match.group(1)
|
||||
verse_num = match.group(2)
|
||||
|
@ -122,7 +122,7 @@ class OPSProImport(SongImport):
|
||||
# Try to split lyrics based on various rules
|
||||
if lyrics:
|
||||
lyrics_text = lyrics.Lyrics
|
||||
verses = re.split('\r\n\s*?\r\n', lyrics_text)
|
||||
verses = re.split(r'\r\n\s*?\r\n', lyrics_text)
|
||||
verse_tag_defs = {}
|
||||
verse_tag_texts = {}
|
||||
for verse_text in verses:
|
||||
@ -130,13 +130,13 @@ class OPSProImport(SongImport):
|
||||
continue
|
||||
verse_def = 'v'
|
||||
# Detect verse number
|
||||
verse_number = re.match('^(\d+)\r\n', verse_text)
|
||||
verse_number = re.match(r'^(\d+)\r\n', verse_text)
|
||||
if verse_number:
|
||||
verse_text = re.sub('^\d+\r\n', '', verse_text)
|
||||
verse_text = re.sub(r'^\d+\r\n', '', verse_text)
|
||||
verse_def = 'v' + verse_number.group(1)
|
||||
# Detect verse tags
|
||||
elif re.match('^.+?\:\r\n', verse_text):
|
||||
tag_match = re.match('^(.+?)\:\r\n(.*)', verse_text, flags=re.DOTALL)
|
||||
elif re.match(r'^.+?\:\r\n', verse_text):
|
||||
tag_match = re.match(r'^(.+?)\:\r\n(.*)', verse_text, flags=re.DOTALL)
|
||||
tag = tag_match.group(1).lower()
|
||||
tag = tag.split(' ')[0]
|
||||
verse_text = tag_match.group(2)
|
||||
@ -147,25 +147,25 @@ class OPSProImport(SongImport):
|
||||
verse_tag_defs[tag] = verse_def
|
||||
verse_tag_texts[tag] = verse_text
|
||||
# Detect tag reference
|
||||
elif re.match('^\(.*?\)$', verse_text):
|
||||
tag_match = re.match('^\((.*?)\)$', verse_text)
|
||||
elif re.match(r'^\(.*?\)$', verse_text):
|
||||
tag_match = re.match(r'^\((.*?)\)$', verse_text)
|
||||
tag = tag_match.group(1).lower()
|
||||
if tag in verse_tag_defs:
|
||||
verse_text = verse_tag_texts[tag]
|
||||
verse_def = verse_tag_defs[tag]
|
||||
# Detect end tag
|
||||
elif re.match('^\[slot\]\r\n', verse_text, re.IGNORECASE):
|
||||
elif re.match(r'^\[slot\]\r\n', verse_text, re.IGNORECASE):
|
||||
verse_def = 'e'
|
||||
verse_text = re.sub('^\[slot\]\r\n', '', verse_text, flags=re.IGNORECASE)
|
||||
verse_text = re.sub(r'^\[slot\]\r\n', '', verse_text, flags=re.IGNORECASE)
|
||||
# Replace the join tag with line breaks
|
||||
verse_text = verse_text.replace('[join]', '')
|
||||
# Replace the split tag with line breaks and an optional split
|
||||
verse_text = re.sub('\[splits?\]', '\r\n[---]', verse_text)
|
||||
verse_text = re.sub(r'\[splits?\]', '\r\n[---]', verse_text)
|
||||
# Handle translations
|
||||
if lyrics.IsDualLanguage:
|
||||
verse_text = self.handle_translation(verse_text)
|
||||
# Remove comments
|
||||
verse_text = re.sub('\(.*?\)\r\n', '', verse_text, flags=re.IGNORECASE)
|
||||
verse_text = re.sub(r'\(.*?\)\r\n', '', verse_text, flags=re.IGNORECASE)
|
||||
self.add_verse(verse_text, verse_def)
|
||||
self.finish()
|
||||
|
||||
|
@ -70,7 +70,7 @@ class PowerSongImport(SongImport):
|
||||
"""
|
||||
Checks if source is a PowerSong 1.0 folder:
|
||||
* is a directory
|
||||
* contains at least one \*.song file
|
||||
* contains at least one * .song file
|
||||
|
||||
:param openlp.core.common.path.Path import_source: Should be a Path object that fulfills the above criteria
|
||||
:return: If the source is valid
|
||||
|
@ -51,7 +51,7 @@ class PresentationManagerImport(SongImport):
|
||||
encoding = get_file_encoding(file_path)['encoding']
|
||||
# Open file with detected encoding and remove encoding declaration
|
||||
text = file_path.read_text(encoding=encoding)
|
||||
text = re.sub('.+\?>\n', '', text)
|
||||
text = re.sub(r'.+\?>\n', '', text)
|
||||
try:
|
||||
tree = etree.fromstring(text, parser=etree.XMLParser(recover=True))
|
||||
except ValueError:
|
||||
|
@ -333,7 +333,7 @@ class SongsOfFellowshipImport(OpenOfficeImport):
|
||||
There is a complicated word "One", which is sometimes lower and
|
||||
sometimes upper depending on context. Never mind, keep it lower.
|
||||
"""
|
||||
text_arr = re.split('(\W+)', text)
|
||||
text_arr = re.split(r'(\W+)', text)
|
||||
text_arr[0] = text_arr[0].capitalize()
|
||||
for i in range(1, len(text_arr)):
|
||||
# Do not translate these. Fixed strings in SOF song file
|
||||
|
@ -142,7 +142,7 @@ class WorshipAssistantImport(SongImport):
|
||||
# drop the square brackets
|
||||
right_bracket = line.find(']')
|
||||
content = line[1:right_bracket].lower()
|
||||
match = re.match('(\D*)(\d+)', content)
|
||||
match = re.match(r'(\D*)(\d+)', content)
|
||||
if match is not None:
|
||||
verse_tag = match.group(1)
|
||||
verse_num = match.group(2)
|
||||
|
@ -81,7 +81,7 @@ def get_version():
|
||||
latest = output.decode('utf-8').split(':')[0]
|
||||
version_string = latest == revision and tag or 'r%s' % latest
|
||||
# Save decimal version in case we need to do a portable build.
|
||||
version = latest == revision and tag or '%s.%s' % (tag, latest)
|
||||
version = latest == revision and tag or '%s-bzr%s' % (tag, latest)
|
||||
return version_string, version
|
||||
|
||||
|
||||
@ -92,21 +92,24 @@ def get_yml(branch, build_type):
|
||||
f = open('appveyor.yml')
|
||||
yml_text = f.read()
|
||||
f.close()
|
||||
yml_text = yml_text.replace('BRANCHNAME', branch)
|
||||
version_string, version = get_version()
|
||||
yml_text = yml_text.replace('TAG', version)
|
||||
if build_type in ['openlp', 'trunk']:
|
||||
yml_text = yml_text.replace('BRANCHPATH', '~openlp-core/openlp/trunk')
|
||||
yml_text = yml_text.replace('BUILD_DOCS', '$TRUE')
|
||||
else:
|
||||
yml_text = yml_text.replace('BRANCHPATH', branch.split(':')[1])
|
||||
yml_text = yml_text.replace('BUILD_DOCS', '$FALSE')
|
||||
return yml_text
|
||||
return yml_text, version_string
|
||||
|
||||
|
||||
def hook(webhook_url, yml):
|
||||
def hook(webhook_url, branch, build_type):
|
||||
"""
|
||||
Activate the webhook to start the build
|
||||
"""
|
||||
yml, version_string = get_yml(branch, build_type)
|
||||
webhook_element['config'] = yml
|
||||
webhook_element['commit']['message'] = 'Building ' + branch
|
||||
version_string, version = get_version()
|
||||
webhook_element['commit']['id'] = version_string
|
||||
request = urllib.request.Request(webhook_url)
|
||||
request.add_header('Content-Type', 'application/json;charset=utf-8')
|
||||
@ -137,7 +140,7 @@ else:
|
||||
if build_type not in ['dev', 'trunk', 'openlp']:
|
||||
print('Invalid build type\nUsage: %s <webhook-url> <branch> <dev|trunk|openlp>' % sys.argv[0])
|
||||
exit()
|
||||
hook(webhook_url, get_yml(branch, build_type))
|
||||
hook(webhook_url, branch, build_type)
|
||||
# Wait 5 seconds to make sure the hook has been triggered
|
||||
time.sleep(5)
|
||||
get_appveyor_build_url(build_type)
|
||||
|
@ -1,18 +1,17 @@
|
||||
version: OpenLP-win-ci-b{build}
|
||||
|
||||
init:
|
||||
- choco install -y --force bzr
|
||||
- set PATH=C:\Program Files (x86)\Bazaar;%PATH%
|
||||
|
||||
clone_script:
|
||||
- bzr checkout --lightweight BRANCHNAME openlp-branch
|
||||
- curl -L https://bazaar.launchpad.net/BRANCHPATH/tarball -o sourcecode.tar.gz
|
||||
- 7z e sourcecode.tar.gz
|
||||
- 7z x sourcecode.tar
|
||||
- mv BRANCHPATH openlp-branch
|
||||
|
||||
environment:
|
||||
PYTHON: C:\\Python34
|
||||
|
||||
install:
|
||||
# Install dependencies from pypi
|
||||
- "%PYTHON%\\python.exe -m pip install sqlalchemy alembic chardet beautifulsoup4 Mako nose mock pyodbc==4.0.8 psycopg2 pypiwin32 pyenchant websockets asyncio waitress six webob requests"
|
||||
- "%PYTHON%\\python.exe -m pip install sqlalchemy alembic chardet beautifulsoup4 Mako nose mock pyodbc==4.0.8 psycopg2 pypiwin32==219 pyenchant websockets asyncio waitress six webob requests"
|
||||
# Install mysql dependency
|
||||
- "%PYTHON%\\python.exe -m pip install http://cdn.mysql.com/Downloads/Connector-Python/mysql-connector-python-2.0.4.zip#md5=3df394d89300db95163f17c843ef49df"
|
||||
# Download and install lxml and pyicu (originally from http://www.lfd.uci.edu/~gohlke/pythonlibs/)
|
||||
@ -74,10 +73,10 @@ after_test:
|
||||
7z x documentation.tar
|
||||
mv ~openlp-core/openlp/documentation documentation
|
||||
cd packaging
|
||||
&"$env:PYTHON\python.exe" builders/windows-builder.py --skip-update -c windows/config-appveyor.ini -b ../openlp-branch -d ../documentation --portable
|
||||
&"$env:PYTHON\python.exe" builders/windows-builder.py --skip-update -c windows/config-appveyor.ini -b ../openlp-branch -d ../documentation --portable --tag-override TAG
|
||||
} else {
|
||||
cd packaging
|
||||
&"$env:PYTHON\python.exe" builders/windows-builder.py --skip-update --skip-translations -c windows/config-appveyor.ini -b ../openlp-branch --portable
|
||||
&"$env:PYTHON\python.exe" builders/windows-builder.py --skip-update --skip-translations -c windows/config-appveyor.ini -b ../openlp-branch --portable --tag-override TAG
|
||||
}
|
||||
|
||||
artifacts:
|
||||
|
@ -124,7 +124,7 @@ def get_merge_info(url):
|
||||
script_tag = soup.find('script', attrs={"id": "codereview-script"})
|
||||
content = script_tag.contents[0]
|
||||
start_pos = content.find('source_revid') + 16
|
||||
pattern = re.compile('.*\w-\d\d\d\d\d+')
|
||||
pattern = re.compile(r'.*\w-\d\d\d\d\d+')
|
||||
match = pattern.match(content[start_pos:])
|
||||
merge_info['author_email'] = match.group()[:-15]
|
||||
# Launchpad doesn't supply the author's true name, so we'll just grab whatever they use for display on LP
|
||||
|
@ -15,5 +15,10 @@ ignore = E402
|
||||
[pycodestyle]
|
||||
exclude = resources.py,vlc.py
|
||||
max-line-length = 120
|
||||
ignore = E402
|
||||
# Ignoring:
|
||||
# E402...
|
||||
# E722 do not use bare 'except'
|
||||
# W503 line break before binary operator
|
||||
# W504 line break after binary operator
|
||||
ignore = E402,E722,W503,W504
|
||||
|
||||
|
@ -85,7 +85,7 @@ class TestApiTab(TestCase, TestMixin):
|
||||
ip_address = self.form.get_ip_address(ZERO_URL)
|
||||
|
||||
# THEN: the default ip address will be returned
|
||||
assert re.match('\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}', ip_address), \
|
||||
assert re.match(r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}', ip_address), \
|
||||
'The return value should be a valid ip address'
|
||||
assert ip_address in ip4_list, 'The return address should be in the list of local IP addresses'
|
||||
|
||||
|
@ -27,13 +27,14 @@ import tempfile
|
||||
from unittest import TestCase
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from openlp.core.common.httputils import get_user_agent, get_web_page, get_url_file_size, download_file
|
||||
from openlp.core.common.httputils import ProxyMode, download_file, get_proxy_settings, get_url_file_size, \
|
||||
get_user_agent, get_web_page
|
||||
from openlp.core.common.path import Path
|
||||
from openlp.core.common.settings import Settings
|
||||
from tests.helpers.testmixin import TestMixin
|
||||
|
||||
|
||||
class TestHttpUtils(TestCase, TestMixin):
|
||||
|
||||
"""
|
||||
A test suite to test out various http helper functions.
|
||||
"""
|
||||
@ -240,3 +241,119 @@ class TestHttpUtils(TestCase, TestMixin):
|
||||
# THEN: socket.timeout should have been caught
|
||||
# NOTE: Test is if $tmpdir/tempfile is still there, then test fails since ftw deletes bad downloaded files
|
||||
assert os.path.exists(self.tempfile) is False, 'tempfile should have been deleted'
|
||||
|
||||
|
||||
class TestGetProxySettings(TestCase, TestMixin):
|
||||
def setUp(self):
|
||||
self.build_settings()
|
||||
self.addCleanup(self.destroy_settings)
|
||||
|
||||
@patch('openlp.core.common.httputils.Settings')
|
||||
def test_mode_arg_specified(self, MockSettings):
|
||||
"""
|
||||
Test that the argument is used rather than reading the 'advanced/proxy mode' setting
|
||||
"""
|
||||
# GIVEN: Mocked settings
|
||||
mocked_settings = MagicMock()
|
||||
MockSettings.return_value = mocked_settings
|
||||
|
||||
# WHEN: Calling `get_proxy_settings` with the mode arg specified
|
||||
get_proxy_settings(mode=ProxyMode.NO_PROXY)
|
||||
|
||||
# THEN: The mode arg should have been used rather than looking it up in the settings
|
||||
mocked_settings.value.assert_not_called()
|
||||
|
||||
@patch('openlp.core.common.httputils.Settings')
|
||||
def test_mode_incorrect_arg_specified(self, MockSettings):
|
||||
"""
|
||||
Test that the system settings are used when the mode arg specieied is invalid
|
||||
"""
|
||||
# GIVEN: Mocked settings
|
||||
mocked_settings = MagicMock()
|
||||
MockSettings.return_value = mocked_settings
|
||||
|
||||
# WHEN: Calling `get_proxy_settings` with an invalid mode arg specified
|
||||
result = get_proxy_settings(mode='qwerty')
|
||||
|
||||
# THEN: An None should be returned
|
||||
mocked_settings.value.assert_not_called()
|
||||
assert result is None
|
||||
|
||||
def test_no_proxy_mode(self):
|
||||
"""
|
||||
Test that a dictionary with http and https values are set to None is returned, when `NO_PROXY` mode is specified
|
||||
"""
|
||||
# GIVEN: A `proxy mode` setting of NO_PROXY
|
||||
Settings().setValue('advanced/proxy mode', ProxyMode.NO_PROXY)
|
||||
|
||||
# WHEN: Calling `get_proxy_settings`
|
||||
result = get_proxy_settings()
|
||||
|
||||
# THEN: The returned value should be a dictionary with http and https values set to None
|
||||
assert result == {'http': None, 'https': None}
|
||||
|
||||
def test_system_proxy_mode(self):
|
||||
"""
|
||||
Test that None is returned, when `SYSTEM_PROXY` mode is specified
|
||||
"""
|
||||
# GIVEN: A `proxy mode` setting of SYSTEM_PROXY
|
||||
Settings().setValue('advanced/proxy mode', ProxyMode.SYSTEM_PROXY)
|
||||
|
||||
# WHEN: Calling `get_proxy_settings`
|
||||
result = get_proxy_settings()
|
||||
|
||||
# THEN: The returned value should be None
|
||||
assert result is None
|
||||
|
||||
def test_manual_proxy_mode_no_auth(self):
|
||||
"""
|
||||
Test that the correct proxy addresses are returned when basic authentication is not used
|
||||
"""
|
||||
# GIVEN: A `proxy mode` setting of MANUAL_PROXY with proxy servers, but no auth credentials are supplied
|
||||
Settings().setValue('advanced/proxy mode', ProxyMode.MANUAL_PROXY)
|
||||
Settings().setValue('advanced/proxy http', 'testhttp.server:port')
|
||||
Settings().setValue('advanced/proxy https', 'testhttps.server:port')
|
||||
Settings().setValue('advanced/proxy username', '')
|
||||
Settings().setValue('advanced/proxy password', '')
|
||||
|
||||
# WHEN: Calling `get_proxy_settings`
|
||||
result = get_proxy_settings()
|
||||
|
||||
# THEN: The returned value should be the proxy servers without authentication
|
||||
assert result == {'http': 'http://testhttp.server:port', 'https': 'https://testhttps.server:port'}
|
||||
|
||||
def test_manual_proxy_mode_auth(self):
|
||||
"""
|
||||
Test that the correct proxy addresses are returned when basic authentication is used
|
||||
"""
|
||||
# GIVEN: A `proxy mode` setting of MANUAL_PROXY with proxy servers and auth credentials supplied
|
||||
Settings().setValue('advanced/proxy mode', ProxyMode.MANUAL_PROXY)
|
||||
Settings().setValue('advanced/proxy http', 'testhttp.server:port')
|
||||
Settings().setValue('advanced/proxy https', 'testhttps.server:port')
|
||||
Settings().setValue('advanced/proxy username', 'user')
|
||||
Settings().setValue('advanced/proxy password', 'pass')
|
||||
|
||||
# WHEN: Calling `get_proxy_settings`
|
||||
result = get_proxy_settings()
|
||||
|
||||
# THEN: The returned value should be the proxy servers with the authentication credentials
|
||||
assert result == {'http': 'http://user:pass@testhttp.server:port',
|
||||
'https': 'https://user:pass@testhttps.server:port'}
|
||||
|
||||
def test_manual_proxy_mode_no_servers(self):
|
||||
"""
|
||||
Test that the system proxies are overidden when the MANUAL_PROXY mode is specified, but no server addresses are
|
||||
supplied
|
||||
"""
|
||||
# GIVEN: A `proxy mode` setting of MANUAL_PROXY with no servers specified
|
||||
Settings().setValue('advanced/proxy mode', ProxyMode.MANUAL_PROXY)
|
||||
Settings().setValue('advanced/proxy http', '')
|
||||
Settings().setValue('advanced/proxy https', '')
|
||||
Settings().setValue('advanced/proxy username', 'user')
|
||||
Settings().setValue('advanced/proxy password', 'pass')
|
||||
|
||||
# WHEN: Calling `get_proxy_settings`
|
||||
result = get_proxy_settings()
|
||||
|
||||
# THEN: The returned value should be the proxy servers set to None
|
||||
assert result == {'http': None, 'https': None}
|
||||
|
@ -238,8 +238,8 @@ class TestInit(TestCase, TestMixin):
|
||||
Test the clean_filename() function
|
||||
"""
|
||||
# GIVEN: A invalid file name and the valid file name.
|
||||
invalid_name = 'A_file_with_invalid_characters_[\\/:\*\?"<>\|\+\[\]%].py'
|
||||
wanted_name = 'A_file_with_invalid_characters______________________.py'
|
||||
invalid_name = 'A_file_with_invalid_characters_[\\/:*?"<>|+[]%].py'
|
||||
wanted_name = 'A_file_with_invalid_characters________________.py'
|
||||
|
||||
# WHEN: Clean the name.
|
||||
result = clean_filename(invalid_name)
|
||||
|
@ -0,0 +1,78 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
|
||||
|
||||
###############################################################################
|
||||
# OpenLP - Open Source Lyrics Projection #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Copyright (c) 2008-2017 OpenLP Developers #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# 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; version 2 of the License. #
|
||||
# #
|
||||
# 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, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
"""
|
||||
Functional tests to test calls for network interfaces.
|
||||
"""
|
||||
from unittest import TestCase
|
||||
from unittest.mock import MagicMock, call, patch
|
||||
|
||||
import openlp.core.common
|
||||
from openlp.core.common import get_local_ip4
|
||||
|
||||
from tests.helpers.testmixin import TestMixin
|
||||
|
||||
lo_address_attrs = {'isValid.return_value': True,
|
||||
'flags.return_value': True,
|
||||
'InterfaceFlags.return_value': True,
|
||||
'name.return_value': 'lo',
|
||||
'broadcast.toString.return_value': '127.0.0.255',
|
||||
'netmask.toString.return_value': '255.0.0.0',
|
||||
'prefixLength.return_value': 8,
|
||||
'ip.protocol.return_value': True}
|
||||
|
||||
|
||||
class TestInterfaces(TestCase, TestMixin):
|
||||
"""
|
||||
A test suite to test out functions/methods that use network interface(s).
|
||||
"""
|
||||
def setUp(self):
|
||||
"""
|
||||
Create an instance and a few example actions.
|
||||
"""
|
||||
self.build_settings()
|
||||
|
||||
self.ip4_lo_address = MagicMock()
|
||||
self.ip4_lo_address.configure_mock(**lo_address_attrs)
|
||||
|
||||
def tearDown(self):
|
||||
"""
|
||||
Clean up
|
||||
"""
|
||||
self.destroy_settings()
|
||||
|
||||
@patch.object(openlp.core.common, 'log')
|
||||
def test_ip4_no_interfaces(self, mock_log):
|
||||
"""
|
||||
Test no interfaces available
|
||||
"""
|
||||
# GIVEN: Test environment
|
||||
call_warning = [call('No active IPv4 network interfaces detected')]
|
||||
|
||||
with patch('openlp.core.common.QNetworkInterface') as mock_newtork_interface:
|
||||
mock_newtork_interface.allInterfaces.return_value = []
|
||||
|
||||
# WHEN: get_local_ip4 is called
|
||||
ifaces = get_local_ip4()
|
||||
|
||||
# THEN: There should not be any interfaces detected
|
||||
assert not ifaces, 'There should have been no active interfaces'
|
||||
mock_log.warning.assert_has_calls(call_warning)
|
@ -12,7 +12,7 @@ from openlp.core.lib.htmlbuilder import build_html, build_background_css, build_
|
||||
from openlp.core.lib.theme import HorizontalType, VerticalType
|
||||
from tests.helpers.testmixin import TestMixin
|
||||
|
||||
HTML = """
|
||||
HTML = r"""
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
@ -121,7 +121,7 @@ HTML = """
|
||||
}
|
||||
|
||||
function show_text(new_text){
|
||||
var match = /-webkit-text-fill-color:[^;"]+/gi;
|
||||
var match = /-webkit-text-fill-color:[^;\"]+/gi;
|
||||
if(timer != null)
|
||||
clearTimeout(timer);
|
||||
/*
|
||||
|
@ -99,7 +99,7 @@ class TestStartFileRenameForm(TestCase, TestMixin):
|
||||
# GIVEN: QLineEdit with a validator set with illegal file name characters.
|
||||
|
||||
# WHEN: 'Typing' a string containing invalid file characters.
|
||||
QtTest.QTest.keyClicks(self.form.file_name_edit, 'I/n\\v?a*l|i<d> \F[i\l]e" :N+a%me')
|
||||
QtTest.QTest.keyClicks(self.form.file_name_edit, r'I/n\\v?a*l|i<d> \F[i\l]e" :N+a%me')
|
||||
|
||||
# THEN: The text in the QLineEdit should be the same as the input string with the invalid characters filtered
|
||||
# out.
|
||||
|
174
tests/interfaces/openlp_core/widgets/test_widgets.py
Normal file
174
tests/interfaces/openlp_core/widgets/test_widgets.py
Normal file
@ -0,0 +1,174 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
|
||||
|
||||
###############################################################################
|
||||
# OpenLP - Open Source Lyrics Projection #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Copyright (c) 2008-2018 OpenLP Developers #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# 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; version 2 of the License. #
|
||||
# #
|
||||
# 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, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
"""
|
||||
Module to test the custom widgets.
|
||||
"""
|
||||
from unittest import TestCase
|
||||
from unittest.mock import MagicMock, call, patch
|
||||
|
||||
from openlp.core.common.registry import Registry
|
||||
from openlp.core.common.settings import ProxyMode
|
||||
from openlp.core.widgets.widgets import ProxyWidget
|
||||
from tests.helpers.testmixin import TestMixin
|
||||
|
||||
|
||||
class TestProxyWidget(TestCase, TestMixin):
|
||||
"""
|
||||
Test the EditCustomForm.
|
||||
"""
|
||||
def setUp(self):
|
||||
"""
|
||||
Create the UI
|
||||
"""
|
||||
Registry.create()
|
||||
self.setup_application()
|
||||
|
||||
def test_radio_button_exclusivity_no_proxy(self):
|
||||
"""
|
||||
Test that only one radio button can be checked at a time, and that the line edits are only enabled when the
|
||||
`manual_proxy_radio` is checked
|
||||
"""
|
||||
# GIVEN: An instance of the `openlp.core.common.widgets.widgets.ProxyWidget` with a radio already checked
|
||||
proxy_widget = ProxyWidget()
|
||||
proxy_widget.manual_proxy_radio.setChecked(True)
|
||||
|
||||
# WHEN: 'Checking' the `no_proxy_radio` button
|
||||
proxy_widget.no_proxy_radio.setChecked(True)
|
||||
|
||||
# THEN: The other radio buttons should not be checked and the line edits should not be enabled
|
||||
assert proxy_widget.use_sysem_proxy_radio.isChecked() is False
|
||||
assert proxy_widget.manual_proxy_radio.isChecked() is False
|
||||
assert proxy_widget.http_edit.isEnabled() is False
|
||||
assert proxy_widget.https_edit.isEnabled() is False
|
||||
assert proxy_widget.username_edit.isEnabled() is False
|
||||
assert proxy_widget.password_edit.isEnabled() is False
|
||||
|
||||
def test_radio_button_exclusivity_system_proxy(self):
|
||||
"""
|
||||
Test that only one radio button can be checked at a time, and that the line edits are only enabled when the
|
||||
`manual_proxy_radio` is checked
|
||||
"""
|
||||
# GIVEN: An instance of the `openlp.core.common.widgets.widgets.ProxyWidget` with a radio already checked
|
||||
proxy_widget = ProxyWidget()
|
||||
proxy_widget.manual_proxy_radio.setChecked(True)
|
||||
|
||||
# WHEN: 'Checking' the `use_sysem_proxy_radio` button
|
||||
proxy_widget.use_sysem_proxy_radio.setChecked(True)
|
||||
|
||||
# THEN: The other radio buttons should not be checked and the line edits should not be enabled
|
||||
assert proxy_widget.no_proxy_radio.isChecked() is False
|
||||
assert proxy_widget.manual_proxy_radio.isChecked() is False
|
||||
assert proxy_widget.http_edit.isEnabled() is False
|
||||
assert proxy_widget.https_edit.isEnabled() is False
|
||||
assert proxy_widget.username_edit.isEnabled() is False
|
||||
assert proxy_widget.password_edit.isEnabled() is False
|
||||
|
||||
def test_radio_button_exclusivity_manual_proxy(self):
|
||||
"""
|
||||
Test that only one radio button can be checked at a time, and that the line edits are only enabled when the
|
||||
`manual_proxy_radio` is checked
|
||||
"""
|
||||
# GIVEN: An instance of the `openlp.core.common.widgets.widgets.ProxyWidget` with a radio already checked
|
||||
proxy_widget = ProxyWidget()
|
||||
proxy_widget.no_proxy_radio.setChecked(True)
|
||||
|
||||
# WHEN: 'Checking' the `manual_proxy_radio` button
|
||||
proxy_widget.manual_proxy_radio.setChecked(True)
|
||||
|
||||
# THEN: The other radio buttons should not be checked and the line edits should be enabled
|
||||
assert proxy_widget.no_proxy_radio.isChecked() is False
|
||||
assert proxy_widget.use_sysem_proxy_radio.isChecked() is False
|
||||
assert proxy_widget.http_edit.isEnabled() is True
|
||||
assert proxy_widget.https_edit.isEnabled() is True
|
||||
assert proxy_widget.username_edit.isEnabled() is True
|
||||
assert proxy_widget.password_edit.isEnabled() is True
|
||||
|
||||
def test_proxy_widget_load_default_settings(self):
|
||||
"""
|
||||
Test that the default settings are loaded from the config correctly
|
||||
"""
|
||||
# GIVEN: And instance of the widget with default settings
|
||||
proxy_widget = ProxyWidget()
|
||||
|
||||
# WHEN: Calling the `load` method
|
||||
proxy_widget.load()
|
||||
|
||||
# THEN: The widget should be in its default state
|
||||
assert proxy_widget.use_sysem_proxy_radio.isChecked() is True
|
||||
assert proxy_widget.http_edit.text() == ''
|
||||
assert proxy_widget.https_edit.text() == ''
|
||||
assert proxy_widget.username_edit.text() == ''
|
||||
assert proxy_widget.password_edit.text() == ''
|
||||
|
||||
@patch.object(ProxyWidget, 'load')
|
||||
@patch('openlp.core.widgets.widgets.Settings')
|
||||
def test_proxy_widget_save_no_proxy_settings(self, settings_patcher, proxy_widget_load_patcher):
|
||||
"""
|
||||
Test that the settings are saved correctly
|
||||
"""
|
||||
# GIVEN: A Mocked settings instance of the proxy widget with some known values set
|
||||
settings_instance = MagicMock()
|
||||
settings_patcher.return_value = settings_instance
|
||||
proxy_widget = ProxyWidget()
|
||||
proxy_widget.no_proxy_radio.setChecked(True)
|
||||
proxy_widget.http_edit.setText('')
|
||||
proxy_widget.https_edit.setText('')
|
||||
proxy_widget.username_edit.setText('')
|
||||
proxy_widget.password_edit.setText('')
|
||||
|
||||
# WHEN: Calling save
|
||||
proxy_widget.save()
|
||||
|
||||
# THEN: The settings should be set as expected
|
||||
settings_instance.setValue.assert_has_calls(
|
||||
[call('advanced/proxy mode', ProxyMode.NO_PROXY),
|
||||
call('advanced/proxy http', ''),
|
||||
call('advanced/proxy https', ''),
|
||||
call('advanced/proxy username', ''),
|
||||
call('advanced/proxy password', '')])
|
||||
|
||||
@patch.object(ProxyWidget, 'load')
|
||||
@patch('openlp.core.widgets.widgets.Settings')
|
||||
def test_proxy_widget_save_manual_settings(self, settings_patcher, proxy_widget_load_patcher):
|
||||
"""
|
||||
Test that the settings are saved correctly
|
||||
"""
|
||||
# GIVEN: A Mocked and instance of the proxy widget with some known values set
|
||||
settings_instance = MagicMock()
|
||||
settings_patcher.return_value = settings_instance
|
||||
proxy_widget = ProxyWidget()
|
||||
proxy_widget.manual_proxy_radio.setChecked(True)
|
||||
proxy_widget.http_edit.setText('http_proxy_server:port')
|
||||
proxy_widget.https_edit.setText('https_proxy_server:port')
|
||||
proxy_widget.username_edit.setText('username')
|
||||
proxy_widget.password_edit.setText('password')
|
||||
|
||||
# WHEN: Calling save
|
||||
proxy_widget.save()
|
||||
|
||||
# THEN: The settings should be set as expected
|
||||
settings_instance.setValue.assert_has_calls(
|
||||
[call('advanced/proxy mode', ProxyMode.MANUAL_PROXY),
|
||||
call('advanced/proxy http', 'http_proxy_server:port'),
|
||||
call('advanced/proxy https', 'https_proxy_server:port'),
|
||||
call('advanced/proxy username', 'username'),
|
||||
call('advanced/proxy password', 'password')])
|
@ -68,7 +68,7 @@ class TestPylint(TestCase):
|
||||
|
||||
# WHEN: Running pylint
|
||||
(pylint_stdout, pylint_stderr) = \
|
||||
lint.py_run('openlp --errors-only --disable={disabled} --enable={enabled} '
|
||||
lint.py_run('openlp --errors-only -j 4 --disable={disabled} --enable={enabled} '
|
||||
'--reports=no --output-format=parseable'.format(disabled=disabled_checks,
|
||||
enabled=enabled_checks),
|
||||
**pylint_kwargs)
|
||||
@ -88,7 +88,7 @@ class TestPylint(TestCase):
|
||||
filtered_output = ''
|
||||
for line in pylint_output.splitlines():
|
||||
# Filter out module info lines
|
||||
if line.startswith('**'):
|
||||
if '***' in line:
|
||||
continue
|
||||
# Filter out undefined-variable error releated to WindowsError
|
||||
elif 'undefined-variable' in line and 'WindowsError' in line:
|
||||
|
Loading…
Reference in New Issue
Block a user