openlp-core team mailing list archive
-
openlp-core team
-
Mailing list archive
-
Message #22146
[Merge] lp:~trb143/openlp/refactor into lp:openlp
Tim Bentley has proposed merging lp:~trb143/openlp/refactor into lp:openlp.
Requested reviews:
Raoul Snyman (raoul-snyman)
For more details, see:
https://code.launchpad.net/~trb143/openlp/refactor/+merge/193146
This is work in progress and not complete.
This is a start to add trace functionality and clean up logging.
Move de_hump as it has more uses than theme!
add register decorator.
--
https://code.launchpad.net/~trb143/openlp/refactor/+merge/193146
Your team OpenLP Core is subscribed to branch lp:openlp.
=== modified file 'openlp/core/common/__init__.py'
--- openlp/core/common/__init__.py 2013-10-13 20:36:42 +0000
+++ openlp/core/common/__init__.py 2013-10-29 21:31:24 +0000
@@ -27,17 +27,20 @@
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
"""
-The :mod:`common` module contains most of the components and libraries that make
-OpenLP work.
+The :mod:`common` module contains most of the components and libraries that make OpenLP work.
"""
import os
import logging
+import re
import sys
from PyQt4 import QtCore
log = logging.getLogger(__name__)
+FIRST_CAMEL_REGEX = re.compile('(.)([A-Z][a-z]+)')
+SECOND_CAMEL_REGEX = re.compile('([a-z0-9])([A-Z])')
+
def check_directory_exists(directory, do_not_log=False):
"""
@@ -94,6 +97,14 @@
return qt_translate(context, text, comment, encoding, n)
+def de_hump(name):
+ """
+ Change any Camel Case string to python string
+ """
+ sub_name = FIRST_CAMEL_REGEX.sub(r"\1_\2", name)
+ return SECOND_CAMEL_REGEX.sub(r"\1_\2", sub_name).lower()
+
+
class SlideLimits(object):
"""
Provides an enumeration for behaviour of OpenLP at the end limits of each service item when pressing the up/down
@@ -103,7 +114,7 @@
Wrap = 2
Next = 3
+from .logger import trace
from .uistrings import UiStrings
from .settings import Settings
from .applocation import AppLocation
-
=== added file 'openlp/core/common/logger.py'
--- openlp/core/common/logger.py 1970-01-01 00:00:00 +0000
+++ openlp/core/common/logger.py 2013-10-29 21:31:24 +0000
@@ -0,0 +1,64 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2013 Raoul Snyman #
+# Portions copyright (c) 2008-2013 Tim Bentley, Gerald Britton, Jonathan #
+# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
+# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. #
+# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, #
+# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
+# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, #
+# Frode Woldsund, Martin Zibricky, Patrick Zimmermann #
+# --------------------------------------------------------------------------- #
+# 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 #
+###############################################################################
+"""
+This class contains the core logger functions.
+"""
+
+import inspect
+import logging
+
+# Events to never be logged. Usually timer events which will flood the log!
+DO_NOT_TRACE_EVENTS = ['timerEvent', 'paintEvent']
+
+
+def log_wrapper(func):
+ """
+ Code to added debug wrapper to work on called functions within a decorated class.
+ """
+ def wrapped(*args, **kwargs):
+ log = logging.getLogger(args[0].__module__)
+ if log.getEffectiveLevel() == logging.DEBUG:
+ log.debug("Entering %s" % func.__name__)
+ try:
+ return func(*args, **kwargs)
+ except Exception as e:
+ if log.getEffectiveLevel() <= logging.ERROR:
+ log.error('Exception in %s : %s' % (func.__name__, e))
+ raise e
+ return wrapped
+
+
+def trace(cls):
+ """
+ Decorator to add log_wrapper to all methods in calls unless they are banned!
+ """
+ for name, m in inspect.getmembers(cls, inspect.isfunction):
+ if name not in DO_NOT_TRACE_EVENTS:
+ setattr(cls, name, log_wrapper(m))
+ return cls
=== modified file 'openlp/core/lib/__init__.py'
--- openlp/core/lib/__init__.py 2013-10-13 20:36:42 +0000
+++ openlp/core/lib/__init__.py 2013-10-29 21:31:24 +0000
@@ -329,7 +329,7 @@
return translate('OpenLP.core.lib', '%s, %s', 'Locale list separator: start') % (string_list[0], merged)
-from .registry import Registry
+from .registry import Registry, register
from .screen import ScreenList
from .listwidgetwithdnd import ListWidgetWithDnD
from .treewidgetwithdnd import TreeWidgetWithDnD
=== modified file 'openlp/core/lib/imagemanager.py'
--- openlp/core/lib/imagemanager.py 2013-08-31 18:17:38 +0000
+++ openlp/core/lib/imagemanager.py 2013-10-29 21:31:24 +0000
@@ -39,7 +39,8 @@
from PyQt4 import QtCore
-from openlp.core.lib import Registry, ScreenList, resize_image, image_to_byte
+from openlp.core.common import trace
+from openlp.core.lib import Registry, ScreenList, resize_image, image_to_byte, register
log = logging.getLogger(__name__)
@@ -172,19 +173,18 @@
if (image.priority, image.secondary_priority, image) in self.queue:
self.queue.remove((image.priority, image.secondary_priority, image))
-
+@trace
class ImageManager(QtCore.QObject):
"""
Image Manager handles the conversion and sizing of images.
"""
log.info('Image Manager loaded')
-
+ @register
def __init__(self):
"""
Constructor for the image manager.
"""
super(ImageManager, self).__init__()
- Registry().register('image_manager', self)
current_screen = ScreenList().current
self.width = current_screen['size'].width()
self.height = current_screen['size'].height()
@@ -198,7 +198,6 @@
"""
Screen has changed size so rebuild the cache to new size.
"""
- log.debug('update_display')
current_screen = ScreenList().current
self.width = current_screen['size'].width()
self.height = current_screen['size'].height()
@@ -210,7 +209,6 @@
"""
Border has changed so update all the images affected.
"""
- log.debug('update_images_border')
# Mark the images as dirty for a rebuild by setting the image and byte stream to None.
for image in list(self._cache.values()):
if image.source == source:
@@ -221,7 +219,6 @@
"""
Border has changed so update the image affected.
"""
- log.debug('update_image_border')
# Mark the image as dirty for a rebuild by setting the image and byte stream to None.
image = self._cache[(path, source)]
if image.source == source:
@@ -302,7 +299,6 @@
"""
Controls the processing called from a ``QtCore.QThread``.
"""
- log.debug('_process - started')
while not self._conversion_queue.empty() and not self.stop_manager:
self._process_cache()
log.debug('_process - ended')
@@ -311,7 +307,6 @@
"""
Actually does the work.
"""
- log.debug('_processCache')
image = self._conversion_queue.get()[2]
# Generate the QImage for the image.
if image.image is None:
=== modified file 'openlp/core/lib/pluginmanager.py'
--- openlp/core/lib/pluginmanager.py 2013-10-13 13:51:13 +0000
+++ openlp/core/lib/pluginmanager.py 2013-10-29 21:31:24 +0000
@@ -34,7 +34,7 @@
import logging
import imp
-from openlp.core.lib import Plugin, PluginStatus, Registry
+from openlp.core.lib import Plugin, PluginStatus, Registry, register
from openlp.core.common import AppLocation
log = logging.getLogger(__name__)
@@ -47,13 +47,13 @@
"""
log.info('Plugin manager loaded')
+ @register
def __init__(self):
"""
The constructor for the plugin manager. Passes the controllers on to
the plugins for them to interact with via their ServiceItems.
"""
log.info('Plugin manager Initialising')
- Registry().register('plugin_manager', self)
Registry().register_function('bootstrap_initialise', self.bootstrap_initialise)
self.base_path = os.path.abspath(AppLocation.get_directory(AppLocation.PluginsDir))
log.debug('Base path %s ', self.base_path)
=== modified file 'openlp/core/lib/registry.py'
--- openlp/core/lib/registry.py 2013-08-31 18:17:38 +0000
+++ openlp/core/lib/registry.py 2013-10-29 21:31:24 +0000
@@ -29,12 +29,26 @@
"""
Provide Registry Services
"""
+import inspect
import logging
import sys
+from openlp.core.common import de_hump
+
log = logging.getLogger(__name__)
+def register(func):
+ """
+ Code to register the class in the registry.
+ """
+ def wrapper(*args, **kwargs):
+ Registry().register(de_hump(args[0].__class__.__name__), args[0])
+ ret = func(*args, **kwargs)
+ return ret
+ return wrapper
+
+
class Registry(object):
"""
This is the Component Registry. It is a singleton object and is used to provide a look up service for common
=== modified file 'openlp/core/lib/renderer.py'
--- openlp/core/lib/renderer.py 2013-10-13 20:36:42 +0000
+++ openlp/core/lib/renderer.py 2013-10-29 21:31:24 +0000
@@ -33,7 +33,7 @@
from openlp.core.common import Settings
from openlp.core.lib import FormattingTags, ImageSource, ItemCapabilities, Registry, ScreenList, \
- ServiceItem, expand_tags, build_lyrics_format_css, build_lyrics_outline_css
+ ServiceItem, expand_tags, build_lyrics_format_css, build_lyrics_outline_css, register
from openlp.core.common import ThemeLevel
from openlp.core.ui import MainDisplay
@@ -57,13 +57,13 @@
"""
log.info('Renderer Loaded')
+ @register
def __init__(self):
"""
Initialise the renderer.
"""
log.debug('Initialisation started')
self.screens = ScreenList()
- Registry().register('renderer', self)
self.theme_level = ThemeLevel.Global
self.global_theme_name = ''
self.service_theme_name = ''
=== modified file 'openlp/core/lib/theme.py'
--- openlp/core/lib/theme.py 2013-10-18 18:10:47 +0000
+++ openlp/core/lib/theme.py 2013-10-29 21:31:24 +0000
@@ -36,7 +36,7 @@
from xml.dom.minidom import Document
from lxml import etree, objectify
-from openlp.core.common import AppLocation
+from openlp.core.common import AppLocation, de_hump
from openlp.core.lib import str_to_bool, ScreenList, get_text_file_string
@@ -157,9 +157,6 @@
"""
A class to encapsulate the Theme XML.
"""
- FIRST_CAMEL_REGEX = re.compile('(.)([A-Z][a-z]+)')
- SECOND_CAMEL_REGEX = re.compile('([a-z0-9])([A-Z])')
-
def __init__(self):
"""
Initialise the theme object.
@@ -532,7 +529,7 @@
reject, master, element, value = self._translate_tags(master, element, value)
if reject:
return
- field = self._de_hump(element)
+ field = de_hump(element)
tag = master + '_' + field
if field in BOOLEAN_LIST:
setattr(self, tag, str_to_bool(value))
@@ -557,13 +554,6 @@
theme_strings.append('%30s: %s' % (key, getattr(self, key)))
return '\n'.join(theme_strings)
- def _de_hump(self, name):
- """
- Change Camel Case string to python string
- """
- sub_name = ThemeXML.FIRST_CAMEL_REGEX.sub(r'\1_\2', name)
- return ThemeXML.SECOND_CAMEL_REGEX.sub(r'\1_\2', sub_name).lower()
-
def _build_xml_from_attrs(self):
"""
Build the XML from the varables in the object
=== modified file 'openlp/core/ui/mainwindow.py'
--- openlp/core/ui/mainwindow.py 2013-10-13 21:07:28 +0000
+++ openlp/core/ui/mainwindow.py 2013-10-29 21:31:24 +0000
@@ -42,12 +42,12 @@
from PyQt4 import QtCore, QtGui
from openlp.core.lib import Renderer, OpenLPDockWidget, PluginManager, ImageManager, PluginStatus, Registry, \
- ScreenList, build_icon
+ ScreenList, build_icon, register
from openlp.core.lib.ui import UiStrings, create_action
from openlp.core.ui import AboutForm, SettingsForm, ServiceManager, ThemeManager, SlideController, PluginForm, \
MediaDockManager, ShortcutListForm, FormattingTagForm
-from openlp.core.common import AppLocation, Settings, check_directory_exists, translate
+from openlp.core.common import AppLocation, Settings, check_directory_exists, translate, trace
from openlp.core.ui.media import MediaController
from openlp.core.utils import LanguageManager, add_actions, get_application_version
from openlp.core.utils.actions import ActionList, CategoryOrder
@@ -467,18 +467,17 @@
self.mode_live_item.setStatusTip(translate('OpenLP.MainWindow', 'Set the view mode to Live.'))
+@trace
class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
"""
The main window.
"""
- log.info('MainWindow loaded')
-
+ @register
def __init__(self):
"""
This constructor sets up the interface, the various managers, and the plugins.
"""
super(MainWindow, self).__init__()
- Registry().register('main_window', self)
self.clipboard = self.application.clipboard()
self.arguments = self.application.args
# Set up settings sections for the main application (not for use by plugins).
@@ -551,7 +550,7 @@
"""
Called on start up to restore the last active media plugin.
"""
- log.info('Load data from Settings')
+ print("bootstrap_post_set_up")
if Settings().value('advanced/save current plugin'):
saved_plugin_id = Settings().value('advanced/current media plugin')
if saved_plugin_id != -1:
@@ -581,9 +580,9 @@
Notifies the user that a newer version of OpenLP is available.
Triggered by delay thread and cannot display popup.
"""
- log.debug('version_notice')
version_text = translate('OpenLP.MainWindow', 'Version %s of OpenLP is now available for download (you are '
- 'currently running version %s). \n\nYou can download the latest version from http://openlp.org/.')
+ 'currently running version %s). \n\nYou can download the latest version from '
+ 'http://openlp.org/.')
self.version_text = version_text % (version, get_application_version()['full'])
def show(self):
@@ -998,7 +997,6 @@
"""
The screen has changed so we have to update components such as the renderer.
"""
- log.debug('screen_changed')
self.application.set_busy_cursor()
self.image_manager.update_display()
self.renderer.update_display()
@@ -1065,7 +1063,7 @@
if Settings().value('advanced/save current plugin'):
Settings().setValue('advanced/current media plugin', self.media_tool_box.currentIndex())
# Call the cleanup method to shutdown plugins.
- log.info('cleanup plugins')
+ log.info('Cleanup plugins')
self.plugin_manager.finalise_plugins()
if save_settings:
# Save settings
@@ -1108,7 +1106,7 @@
Update the default theme indicator in the status bar
"""
self.default_theme_label.setText(translate('OpenLP.MainWindow', 'Default Theme: %s') %
- Settings().value('themes/global theme'))
+ Settings().value('themes/global theme'))
def toggle_media_manager(self):
"""
@@ -1182,7 +1180,6 @@
"""
Load the main window settings.
"""
- log.debug('Loading QSettings')
settings = Settings()
# Remove obsolete entries.
settings.remove('custom slide')
@@ -1209,7 +1206,6 @@
# Exit if we just did a settings import.
if self.settingsImported:
return
- log.debug('Saving QSettings')
settings = Settings()
settings.beginGroup(self.general_settings_section)
settings.setValue('recent files', self.recent_files)
@@ -1349,7 +1345,7 @@
log.info('Copy sucessful')
except (IOError, os.error, DistutilsFileError) as why:
self.application.set_normal_cursor()
- log.exception('Data copy failed %s' % str(why))
+ log.error('Data copy failed %s' % str(why))
QtGui.QMessageBox.critical(self, translate('OpenLP.MainWindow', 'New Data Directory Error'),
translate('OpenLP.MainWindow',
'OpenLP Data directory copy failed\n\n%s').replace('%s', str(why)),
=== modified file 'tests/functional/openlp_core_common/__init__.py'
--- tests/functional/openlp_core_common/__init__.py 2013-10-13 17:02:12 +0000
+++ tests/functional/openlp_core_common/__init__.py 2013-10-29 21:31:24 +0000
@@ -1,1 +0,0 @@
-__author__ = 'tim'
=== modified file 'tests/functional/openlp_core_common/test_applocation.py'
--- tests/functional/openlp_core_common/test_applocation.py 2013-10-14 05:01:01 +0000
+++ tests/functional/openlp_core_common/test_applocation.py 2013-10-29 21:31:24 +0000
@@ -59,7 +59,6 @@
# WHEN: we call AppLocation.get_data_path()
data_path = AppLocation.get_data_path()
- print(data_path)
# THEN: check that all the correct methods were called, and the result is correct
mocked_settings.contains.assert_called_with('advanced/data path')
=== added file 'tests/functional/openlp_core_common/test_init.py'
--- tests/functional/openlp_core_common/test_init.py 1970-01-01 00:00:00 +0000
+++ tests/functional/openlp_core_common/test_init.py 2013-10-29 21:31:24 +0000
@@ -0,0 +1,65 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2013 Raoul Snyman #
+# Portions copyright (c) 2008-2013 Tim Bentley, Gerald Britton, Jonathan #
+# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
+# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. #
+# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, #
+# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
+# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, #
+# Frode Woldsund, Martin Zibricky, Patrick Zimmermann #
+# --------------------------------------------------------------------------- #
+# 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 the AppLocation class and related methods.
+"""
+
+from unittest import TestCase
+
+from openlp.core.common import de_hump
+
+class TestInitFunctions(TestCase):
+ """
+ A test suite to test out various functions in the __init__ class.
+ """
+ def de_hump_conversion_test(self):
+ """
+ Test the de_hump function with a class name
+ """
+ # GIVEN: a Class name in Camel Case
+ string = "MyClass"
+
+ # WHEN: we call de_hump
+ new_string = de_hump(string)
+
+ # THEN: the new string should be converted to python format
+ self.assertTrue(new_string == "my_class", 'The class name should have been converted')
+
+ def de_hump_static_test(self):
+ """
+ Test the de_hump function with a python string
+ """
+ # GIVEN: a Class name in Camel Case
+ string = "my_class"
+
+ # WHEN: we call de_hump
+ new_string = de_hump(string)
+
+ # THEN: the new string should be converted to python format
+ self.assertTrue(new_string == "my_class", 'The class name should have been preserved')