← Back to team overview

openlp-core team mailing list archive

[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/192944

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/192944
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-28 19:54:56 +0000
@@ -32,12 +32,16 @@
 """
 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 +98,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 +115,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-28 19:54:56 +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-28 19:54:56 +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-28 19:54:56 +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-28 19:54:56 +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-28 19:54:56 +0000
@@ -32,9 +32,23 @@
 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-28 19:54:56 +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-28 19:54:56 +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-28 19:54:56 +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,6 @@
         """
         Called on start up to restore the last active media plugin.
         """
-        log.info('Load data from Settings')
         if Settings().value('advanced/save current plugin'):
             saved_plugin_id = Settings().value('advanced/current media plugin')
             if saved_plugin_id != -1:
@@ -581,7 +579,6 @@
         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/.')
         self.version_text = version_text % (version, get_application_version()['full'])
@@ -998,7 +995,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 +1061,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 +1104,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 +1178,6 @@
         """
         Load the main window settings.
         """
-        log.debug('Loading QSettings')
         settings = Settings()
         # Remove obsolete entries.
         settings.remove('custom slide')
@@ -1209,7 +1204,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 +1343,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-28 19:54:56 +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-28 19:54:56 +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-28 19:54:56 +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')