← 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/193187

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/193187
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-30 05:51:26 +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-30 05:51:26 +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-30 05:51:26 +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-30 05:51:26 +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-30 05:51:26 +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-30 05:51:26 +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-30 05:51:26 +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-30 05:51:26 +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-30 05:51:26 +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,9 +579,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 +996,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 +1062,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 +1105,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 +1179,6 @@
         """
         Load the main window settings.
         """
-        log.debug('Loading QSettings')
         settings = Settings()
         # Remove obsolete entries.
         settings.remove('custom slide')
@@ -1209,7 +1205,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 +1344,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 'openlp/core/ui/media/mediacontroller.py'
--- openlp/core/ui/media/mediacontroller.py	2013-10-13 20:36:42 +0000
+++ openlp/core/ui/media/mediacontroller.py	2013-10-30 05:51:26 +0000
@@ -36,7 +36,7 @@
 from PyQt4 import QtCore, QtGui
 
 from openlp.core.common import Settings, UiStrings, translate
-from openlp.core.lib import OpenLPToolbar, Registry
+from openlp.core.lib import OpenLPToolbar, Registry, register
 from openlp.core.lib.ui import critical_error_message_box
 from openlp.core.ui.media import MediaState, MediaInfo, MediaType, get_media_players, set_media_players
 from openlp.core.ui.media.mediaplayer import MediaPlayer
@@ -94,11 +94,11 @@
     current_media_players is an array of player instances keyed on ControllerType.
 
     """
+    @register
     def __init__(self):
         """
         Constructor
         """
-        Registry().register('media_controller', self)
         Registry().register_function('bootstrap_initialise', self.check_available_media_players)
         self.media_players = {}
         self.display_controllers = {}

=== modified file 'openlp/core/ui/servicemanager.py'
--- openlp/core/ui/servicemanager.py	2013-10-13 21:07:28 +0000
+++ openlp/core/ui/servicemanager.py	2013-10-30 05:51:26 +0000
@@ -43,7 +43,7 @@
 from PyQt4 import QtCore, QtGui
 
 from openlp.core.common import AppLocation, Settings, ThemeLevel, check_directory_exists, UiStrings, translate
-from openlp.core.lib import OpenLPToolbar, ServiceItem, ItemCapabilities, PluginStatus, Registry, build_icon
+from openlp.core.lib import OpenLPToolbar, ServiceItem, ItemCapabilities, PluginStatus, Registry, build_icon, register
 from openlp.core.lib.ui import critical_error_message_box, create_widget_action, find_and_set_in_combo_box
 from openlp.core.ui import ServiceNoteForm, ServiceItemEditForm, StartTimeForm
 from openlp.core.ui.printserviceform import PrintServiceForm
@@ -289,6 +289,7 @@
     can then be zipped up with all the resources used into one OSZ or oszl file for use on any OpenLP v2 installation.
     Also handles the UI tasks of moving things up and down etc.
     """
+    @register
     def __init__(self, parent=None):
         """
         Sets up the service manager, toolbars, list view, et al.
@@ -296,7 +297,6 @@
         super(ServiceManager, self).__init__(parent)
         self.active = build_icon(':/media/auto-start_active.png')
         self.inactive = build_icon(':/media/auto-start_inactive.png')
-        Registry().register('service_manager', self)
         self.service_items = []
         self.suffixes = []
         self.drop_position = 0

=== modified file 'openlp/core/ui/settingsform.py'
--- openlp/core/ui/settingsform.py	2013-08-31 18:17:38 +0000
+++ openlp/core/ui/settingsform.py	2013-10-30 05:51:26 +0000
@@ -33,7 +33,7 @@
 
 from PyQt4 import QtGui
 
-from openlp.core.lib import PluginStatus, Registry, build_icon
+from openlp.core.lib import PluginStatus, Registry, build_icon, register
 from openlp.core.ui import AdvancedTab, GeneralTab, ThemesTab
 from openlp.core.ui.media import PlayerTab
 from .settingsdialog import Ui_SettingsDialog
@@ -45,11 +45,11 @@
     """
     Provide the form to manipulate the settings for OpenLP
     """
+    @register
     def __init__(self, parent=None):
         """
         Initialise the settings form
         """
-        Registry().register('settings_form', self)
         Registry().register_function('bootstrap_post_set_up', self.post_set_up)
         super(SettingsForm, self).__init__(parent)
         self.processes = []

=== modified file 'openlp/core/ui/thememanager.py'
--- openlp/core/ui/thememanager.py	2013-10-13 21:07:28 +0000
+++ openlp/core/ui/thememanager.py	2013-10-30 05:51:26 +0000
@@ -40,7 +40,7 @@
 
 from openlp.core.common import AppLocation, Settings, check_directory_exists, UiStrings, translate
 from openlp.core.lib import ImageSource, OpenLPToolbar, Registry, get_text_file_string, build_icon, \
-    check_item_selected, create_thumb, validate_thumb
+    check_item_selected, create_thumb, validate_thumb, register
 from openlp.core.lib.theme import ThemeXML, BackgroundType
 from openlp.core.lib.ui import critical_error_message_box, create_widget_action
 from openlp.core.ui import FileRenameForm, ThemeForm, ThemeManagerHelper
@@ -53,12 +53,12 @@
     """
     Manages the orders of Theme.
     """
+    @register
     def __init__(self, parent=None):
         """
         Constructor
         """
         super(ThemeManager, self).__init__(parent)
-        Registry().register('theme_manager', self)
         Registry().register_function('bootstrap_initialise', self.load_first_time_themes)
         Registry().register_function('bootstrap_post_set_up', self._push_themes)
         self.settings_section = 'themes'

=== modified file 'openlp/plugins/alerts/lib/alertsmanager.py'
--- openlp/plugins/alerts/lib/alertsmanager.py	2013-10-13 21:07:28 +0000
+++ openlp/plugins/alerts/lib/alertsmanager.py	2013-10-30 05:51:26 +0000
@@ -36,7 +36,7 @@
 from PyQt4 import QtCore
 
 from openlp.core.common import translate
-from openlp.core.lib import Registry
+from openlp.core.lib import Registry, register
 
 
 log = logging.getLogger(__name__)
@@ -48,9 +48,9 @@
     """
     log.info('Alert Manager loaded')
 
+    @register
     def __init__(self, parent):
         super(AlertsManager, self).__init__(parent)
-        Registry().register('alerts_manager', self)
         self.timer_id = 0
         self.alert_list = []
         Registry().register_function('live_display_active', self.generate_alert)

=== 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-30 05:51:26 +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-30 05:51:26 +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-30 05:51:26 +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')