diff --git a/openlp/core/common/registry.py b/openlp/core/common/registry.py index 014a534f7..218325823 100644 --- a/openlp/core/common/registry.py +++ b/openlp/core/common/registry.py @@ -62,11 +62,9 @@ class Registry(object): registry = cls() registry.service_list = {} registry.functions_list = {} - registry.running_under_test = False - registry.initialising = True # Allow the tests to remove Registry entries but not the live system - if 'nose' in sys.argv[0]: - registry.running_under_test = True + registry.running_under_test = 'nose' in sys.argv[0] + registry.initialising = True return registry def get(self, key): @@ -128,7 +126,7 @@ class Registry(object): :param event: The function description.. :param function: The function to be called when the event happens. """ - if self.running_under_test is False: + if not self.running_under_test: trace_error_handler(log) log.error('Invalid Method call for key %s' % event) raise KeyError('Invalid Method call for key %s' % event) diff --git a/openlp/plugins/bibles/resources/bibles_resources.sqlite b/openlp/plugins/bibles/resources/bibles_resources.sqlite index c0fa931d1..8f1777124 100644 Binary files a/openlp/plugins/bibles/resources/bibles_resources.sqlite and b/openlp/plugins/bibles/resources/bibles_resources.sqlite differ diff --git a/scripts/check_dependencies.py b/scripts/check_dependencies.py index adb6a47f2..5298139be 100755 --- a/scripts/check_dependencies.py +++ b/scripts/check_dependencies.py @@ -94,6 +94,7 @@ OPTIONAL_MODULES = [ ('psycopg2', '(PostgreSQL support)', True), ('nose', '(testing framework)', True), ('mock', '(testing module)', sys.version_info[1] < 3), + ('jenkins', '(access jenkins api - package name: jenkins-webapi)', True), ] w = sys.stdout.write diff --git a/scripts/jenkins_script.py b/scripts/jenkins_script.py new file mode 100644 index 000000000..386ab69ef --- /dev/null +++ b/scripts/jenkins_script.py @@ -0,0 +1,192 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4 + +############################################################################### +# OpenLP - Open Source Lyrics Projection # +# --------------------------------------------------------------------------- # +# Copyright (c) 2008-2014 Raoul Snyman # +# Portions copyright (c) 2008-2014 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 script helps to trigger builds of branches. To use it you have to install the jenkins-webapi package: + + pip3 install jenkins-webapi + +You probably want to create an alias. Add this to your ~/.bashrc file and then logout and login (to apply the alias): + + alias ci="python3 ./scripts/jenkins_script.py TOKEN" + +You can look up the token in the Branch-01-Pull job configuration or ask in IRC. +""" + +from optparse import OptionParser +from requests.exceptions import HTTPError +from subprocess import Popen, PIPE +import sys +import time + +from jenkins import Jenkins + + +JENKINS_URL = 'http://ci.openlp.org/' + + +class OpenLPJobs(object): + """ + This class holds any jobs we have on jenkins and we actually need in this script. + """ + Branch_Pull = 'Branch-01-Pull' + Branch_Functional = 'Branch-02-Functional-Tests' + Branch_Interface = 'Branch-03-Interface-Tests' + Branch_Windows = 'Branch-04-Windows_Tests' + Branch_PEP = 'Branch-05-Code-Analysis' + + Jobs = [Branch_Pull, Branch_Functional, Branch_Interface, Branch_Windows, Branch_PEP] + + +class JenkinsTrigger(object): + def __init__(self, token): + """ + Create the JenkinsTrigger instance. + + :param token: The token we need to trigger the build. If you do not have this token, ask in IRC. + """ + self.token = token + self.repo_name = get_repo_name() + self.jenkins_instance = Jenkins(JENKINS_URL) + + def trigger_build(self): + """ + Ask our jenkins server to build the "Branch-01-Pull" job. + """ + self.jenkins_instance.job(OpenLPJobs.Branch_Pull).build({'BRANCH_NAME': self.repo_name}, token=self.token) + + def print_output(self): + """ + Print the status information of the build tirggered. + """ + print("Add this to your merge proposal:") + print("--------------------------------") + for job in OpenLPJobs.Jobs: + self.__print_build_info(job) + + def open_browser(self): + """ + Opens the browser. + """ + url = self.jenkins_instance.job(OpenLPJobs.Branch_Pull).info['url'] + # Open the url + Popen(('xdg-open', url), stderr=PIPE) + + def __print_build_info(self, job_name): + """ + This helper method prints the job information of the given ``job_name`` + + :param job_name: The name of the job we want the information from. For example *Branch-01-Pull*. Use the class + variables from the :class:`OpenLPJobs` class. + """ + job = self.jenkins_instance.job(job_name) + while job.info['inQueue']: + # Give other processes the possibility to take over. Like Thread.yield(). + time.sleep(0) + build = job.last_build + build.wait() + result_string = build.info['result'] + url = build.info['url'] + print('[%s] %s' % (result_string, url)) + # On failure open the browser. + #if result_string == "FAILURE": + # url += 'console' + # Popen(('xdg-open', url), stderr=PIPE) + + +def get_repo_name(): + """ + This returns the name of branch of the wokring directory. For example it returns *lp:~googol/openlp/render*. + """ + # Run the bzr command. + bzr = Popen(('bzr', 'info'), stdout=PIPE, stderr=PIPE) + raw_output, error = bzr.communicate() + # Detect any errors + if error: + print('This is not a branch.') + return + # Clean the output. + raw_output = raw_output.decode() + output_list = list(map(str.strip, raw_output.split('\n'))) + # Determine the branch's name + repo_name = '' + for line in output_list: + # Check if it is remote branch. + if 'push branch' in line: + repo_name = line.replace('push branch: bzr+ssh://bazaar.launchpad.net/', 'lp:') + break + elif 'checkout of branch' in line: + repo_name = line.replace('checkout of branch: bzr+ssh://bazaar.launchpad.net/', 'lp:') + break + repo_name = repo_name.strip('/') + + # Did we find the branch name? + if not repo_name: + for line in output_list: + # Check if the branch was pushed. + if 'Shared repository with trees (format: 2a)' in line: + print('Not a branch. cd to a branch.') + return + print('Not a branch. Have you pushed it to launchpad?') + return + return repo_name + + +def main(): + usage = 'Usage: python %prog TOKEN [options]' + + parser = OptionParser(usage=usage) + parser.add_option('-d', '--disable-output', dest='enable_output', action="store_false", default=True, + help='Disable output.') + parser.add_option('-b', '--open-browser', dest='open_browser', action="store_true", default=False, + help='Opens the jenkins page in your browser.') + #parser.add_option('-e', '--open-browser-on-error', dest='open_browser_on_error', action="store_true", + # default=False, help='Opens the jenkins page in your browser in case a test fails.') + options, args = parser.parse_args(sys.argv) + + if len(args) == 2: + if not get_repo_name(): + return + token = args[-1] + jenkins_trigger = JenkinsTrigger(token) + try: + jenkins_trigger.trigger_build() + except HTTPError as e: + print("Wrong token.") + return + # Open the browser before printing the output. + if options.open_browser: + jenkins_trigger.open_browser() + if options.enable_output: + jenkins_trigger.print_output() + else: + parser.print_help() + +if __name__ == '__main__': + main() diff --git a/tests/functional/openlp_core_common/test_registry.py b/tests/functional/openlp_core_common/test_registry.py index a57d7ea85..e27b69d10 100644 --- a/tests/functional/openlp_core_common/test_registry.py +++ b/tests/functional/openlp_core_common/test_registry.py @@ -100,6 +100,20 @@ class TestRegistry(TestCase): # THEN: I expect then function to have been called and a return given self.assertEqual(return_value[0], 'function_2', 'A return value is provided and matches') + def remove_function_test(self): + """ + Test the remove_function() method + """ + # GIVEN: An existing registry register a function + Registry.create() + Registry().register_function('test1', self.dummy_function_1) + + # WHEN: Remove the function. + Registry().remove_function('test1', self.dummy_function_1) + + # THEN: The method should not be available. + assert not Registry().functions_list['test1'], 'The function should not be in the dict anymore.' + def dummy_function_1(self): return "function_1"