← Back to team overview

openlp-core team mailing list archive

[Merge] lp:~alisonken1/openlp/pjlink2-d into lp:openlp

 

Ken Roberts has proposed merging lp:~alisonken1/openlp/pjlink2-d into lp:openlp.

Requested reviews:
  OpenLP Core (openlp-core)

For more details, see:
https://code.launchpad.net/~alisonken1/openlp/pjlink2-d/+merge/324718

-- Added openlp.core.lib.projector.upgrade for db version 2
-- Added test class for projector DB upgrade
-- Remove duplicate TEST_DB entry in tests.resources.projector.data
-- Updated TestProjectorDB to use a temporary directory for test db
-- Fix main db update procedure version check (default to version 0 if no version set)
-- Added extra information to projector info popup
-- Restructure valid command dictionary
-- Removed unused _not_implemented method
-- Pep8 in plugins/songusage, plugins/presentations, and core/ui/lib/pathedit.py


--------------------------------
lp:~alisonken1/openlp/pjlink2-d (revision 2743)
[SUCCESS] https://ci.openlp.io/job/Branch-01-Pull/2033/
[SUCCESS] https://ci.openlp.io/job/Branch-02-Functional-Tests/1943/
[SUCCESS] https://ci.openlp.io/job/Branch-03-Interface-Tests/1873/
[SUCCESS] https://ci.openlp.io/job/Branch-04a-Code_Analysis/1253/
[SUCCESS] https://ci.openlp.io/job/Branch-04b-Test_Coverage/1106/
[FAILURE] https://ci.openlp.io/job/Branch-04c-Code_Analysis2/235/

-- 
Your team OpenLP Core is requested to review the proposed merge of lp:~alisonken1/openlp/pjlink2-d into lp:openlp.
=== modified file 'openlp/core/lib/db.py'
--- openlp/core/lib/db.py	2017-04-25 19:36:37 +0000
+++ openlp/core/lib/db.py	2017-05-27 18:29:46 +0000
@@ -144,6 +144,7 @@
     :param url: The url of the database to upgrade.
     :param upgrade: The python module that contains the upgrade instructions.
     """
+    log.debug('Checking upgrades for DB {db}'.format(db=url))
     session, metadata = init_db(url)
 
     class Metadata(BaseModel):
@@ -160,17 +161,15 @@
     metadata_table.create(checkfirst=True)
     mapper(Metadata, metadata_table)
     version_meta = session.query(Metadata).get('version')
-    if version_meta is None:
-        # Tables have just been created - fill the version field with the most recent version
-        if session.query(Metadata).get('dbversion'):
-            version = 0
-        else:
-            version = upgrade.__version__
+    if version_meta:
+        version = int(version_meta.value)
+    else:
+        # Due to issues with other checks, if the version is not set in the DB then default to 0
+        # and let the upgrade function handle the checks
+        version = 0
         version_meta = Metadata.populate(key='version', value=version)
         session.add(version_meta)
         session.commit()
-    else:
-        version = int(version_meta.value)
     if version > upgrade.__version__:
         session.remove()
         return version, upgrade.__version__

=== modified file 'openlp/core/lib/projector/constants.py'
--- openlp/core/lib/projector/constants.py	2017-05-13 09:00:29 +0000
+++ openlp/core/lib/projector/constants.py	2017-05-27 18:29:46 +0000
@@ -59,33 +59,61 @@
 PJLINK_MAX_PACKET = 136
 # NOTE: Change format to account for some commands are both class 1 and 2
 PJLINK_VALID_CMD = {
-    'ACKN': ['2', ],  # UDP Reply to 'SRCH'
-    'AVMT': ['1', ],  # Shutter option
-    'CLSS': ['1', ],   # PJLink class support query
-    'ERST': ['1', '2'],  # Error status option
-    'FILT': ['2', ],  # Get current filter usage time
-    'FREZ': ['2', ],  # Set freeze/unfreeze picture being projected
-    'INF1': ['1', ],  # Manufacturer name query
-    'INF2': ['1', ],  # Product name query
-    'INFO': ['1', ],  # Other information query
-    'INNM': ['2', ],  # Get Video source input terminal name
-    'INPT': ['1', ],  # Video sources option
-    'INST': ['1', ],  # Input sources available query
-    'IRES': ['2', ],  # Get Video source resolution
-    'LAMP': ['1', ],  # Lamp(s) query (Includes fans)
-    'LKUP': ['2', ],  # UPD Linkup status notification
-    'MVOL': ['2', ],  # Set microphone volume
-    'NAME': ['1', ],  # Projector name query
-    'PJLINK': ['1', ],  # Initial connection
-    'POWR': ['1', ],  # Power option
-    'RFIL': ['2', ],  # Get replacement air filter model number
-    'RLMP': ['2', ],  # Get lamp replacement model number
-    'RRES': ['2', ],  # Get projector recommended video resolution
-    'SNUM': ['2', ],  # Get projector serial number
-    'SRCH': ['2', ],  # UDP broadcast search for available projectors on local network
-    'SVER': ['2', ],  # Get projector software version
-    'SVOL': ['2', ]  # Set speaker volume
+    'ACKN': {'version': ['2', ],  # UDP Reply to 'SRCH'
+             'description': 'Acknowledge a PJLink SRCH command - returns MAC address.'},
+    'AVMT': {'version': ['1', ],
+             'description': 'Blank/unblank video and/or mute audio.'},
+    'CLSS': {'version': ['1', ],
+             'description': 'Query projector PJLink class support.'},
+    'ERST': {'version': ['1', '2'],
+             'description': 'Query error status from projector. '
+                            'Returns fan/lamp/temp/cover/filter/other error status.'},
+    'FILT': {'version': ['2', ],  # Assume (!) time in hours
+             'description': 'Query number of hours on filter.'},
+    'FREZ': {'version': ['2', ],
+             'description': 'Freeze or unfreeze current image being projected.'},
+    'INF1': {'version': ['1', ],
+             'description': 'Query projector manufacturer name.'},
+    'INF2': {'version': ['1', ],
+             'description': 'Query projector product name.'},
+    'INFO': {'version': ['1', ],
+             'description': 'Query projector for other information set by manufacturer.'},
+    'INNM': {'version': ['2', ],
+             'description': 'Query specified input source name'},
+    'INPT': {'version': ['1', ],
+             'description': 'Switch to specified video source.'},
+    'INST': {'version': ['1', ],
+             'description': 'Query available input sources.'},
+    'IRES': {'version:': ['2', ],
+             'description': 'Query current input resolution.'},
+    'LAMP': {'version': ['1', ],
+             'description': 'Query lamp time and on/off status. Multiple lamps supported.'},
+    'LKUP': {'version': ['2', ],
+             'description': 'UDP Status notify. Returns MAC address.'},
+    'MVOL': {'version': ['2', ],
+             'description': 'Adjust microphone volume by 1 step.'},
+    'NAME': {'version': ['1', ],
+             'description': 'Query customer-set projector name.'},
+    'PJLINK': {'version': ['1', ],
+               'description': 'Initial connection with authentication/no authentication request.'},
+    'POWR': {'version': ['1', ],
+             'description': 'Turn lamp on or off/standby.'},
+    'RFIL': {'version': ['2', ],
+             'description': 'Query replacement air filter model number.'},
+    'RLMP': {'version': ['2', ],
+             'description': 'Query replacement lamp model number.'},
+    'RRES': {'version': ['2', ],
+             'description': 'Query recommended resolution.'},
+    'SNUM': {'version': ['2', ],
+             'description': 'Query projector serial number.'},
+    'SRCH': {'version': ['2', ],
+             'description': 'UDP broadcast search request for available projectors.'},
+    'SVER': {'version': ['2', ],
+             'description': 'Query projector software version number.'},
+    'SVOL': {'version': ['2', ],
+             'description': 'Adjust speaker volume by 1 step.'}
 }
+
 # Error and status codes
 S_OK = E_OK = 0  # E_OK included since I sometimes forget
 # Error codes. Start at 200 so we don't duplicate system error codes.

=== modified file 'openlp/core/lib/projector/db.py'
--- openlp/core/lib/projector/db.py	2017-05-20 05:51:58 +0000
+++ openlp/core/lib/projector/db.py	2017-05-27 18:29:46 +0000
@@ -44,6 +44,7 @@
 
 from openlp.core.lib.db import Manager, init_db, init_url
 from openlp.core.lib.projector.constants import PJLINK_DEFAULT_CODES
+from openlp.core.lib.projector import upgrade
 
 Base = declarative_base(MetaData())
 
@@ -243,7 +244,9 @@
     """
     def __init__(self, *args, **kwargs):
         log.debug('ProjectorDB().__init__(args="{arg}", kwargs="{kwarg}")'.format(arg=args, kwarg=kwargs))
-        super().__init__(plugin_name='projector', init_schema=self.init_schema)
+        super(ProjectorDB, self).__init__(plugin_name='projector',
+                                          init_schema=self.init_schema,
+                                          upgrade_mod=upgrade)
         log.debug('ProjectorDB() Initialized using db url {db}'.format(db=self.db_url))
         log.debug('Session: {session}'.format(session=self.session))
 

=== modified file 'openlp/core/lib/projector/pjlink1.py'
--- openlp/core/lib/projector/pjlink1.py	2017-05-20 05:51:58 +0000
+++ openlp/core/lib/projector/pjlink1.py	2017-05-27 18:29:46 +0000
@@ -186,10 +186,15 @@
         self.pjlink_name = None
         self.manufacturer = None
         self.model = None
+        self.serial_no = None
+        self.sw_version = None
         self.shutter = None
         self.mute = None
         self.lamp = None
+        self.model_lamp = None
         self.fan = None
+        self.filter_time = None
+        self.model_filter = None
         self.source_available = None
         self.source = None
         self.other_info = None
@@ -451,14 +456,14 @@
             return
         data_split = data.split('=')
         try:
-            (prefix, class_, cmd, data) = (data_split[0][0], data_split[0][1], data_split[0][2:], data_split[1])
+            (prefix, version, cmd, data) = (data_split[0][0], data_split[0][1], data_split[0][2:], data_split[1])
         except ValueError as e:
             log.warning('({ip}) get_data(): Invalid packet - expected header + command + data'.format(ip=self.ip))
             log.warning('({ip}) get_data(): Received data: "{data}"'.format(ip=self.ip, data=data_in.strip()))
             self.change_status(E_INVALID_DATA)
             self.receive_data_signal()
             return
-        if not (cmd in PJLINK_VALID_CMD and class_ in PJLINK_VALID_CMD[cmd]):
+        if cmd not in PJLINK_VALID_CMD:
             log.warning('({ip}) get_data(): Invalid packet - unknown command "{data}"'.format(ip=self.ip, data=cmd))
             self.receive_data_signal()
             return
@@ -507,14 +512,25 @@
             log.warning('({ip}) send_command(): Not connected - returning'.format(ip=self.ip))
             self.send_queue = []
             return
+        if cmd not in PJLINK_VALID_CMD:
+            log.error('({ip}) send_command(): Invalid command requested - ignoring.'.format(ip=self.ip))
+            return
         self.projectorNetwork.emit(S_NETWORK_SENDING)
         log.debug('({ip}) send_command(): Building cmd="{command}" opts="{data}"{salt}'.format(ip=self.ip,
                                                                                                command=cmd,
                                                                                                data=opts,
                                                                                                salt='' if salt is None
                                                                                                else ' with hash'))
-        # TODO: Check for class of command rather than default to projector PJLink class
-        header = PJLINK_HEADER.format(linkclass=self.pjlink_class)
+        cmd_ver = PJLINK_VALID_CMD[cmd]['version']
+        if self.pjlink_class in cmd_ver:
+            header = PJLINK_HEADER.format(linkclass=self.pjlink_class)
+        elif len(cmd_ver) == 1 and (int(cmd_ver[0]) < int(self.pjlink_class)):
+            # Typically a class 1 only command
+            header = PJLINK_HEADER.format(linkclass=cmd_ver[0])
+        else:
+            # NOTE: Once we get to version 3 then think about looping
+            log.error('({ip}): send_command(): PJLink class check issue? aborting'.format(ip=self.ip))
+            return
         out = '{salt}{header}{command} {options}{suffix}'.format(salt="" if salt is None else salt,
                                                                  header=header,
                                                                  command=cmd,
@@ -589,10 +605,13 @@
                                                                                 cmd=cmd,
                                                                                 data=data))
         # Check if we have a future command not available yet
-        if cmd in self.pjlink_future:
-            self._not_implemented(cmd)
-            return
-        if data in PJLINK_ERRORS:
+        if cmd not in PJLINK_VALID_CMD:
+            log.error('({ip}) Unknown command received - ignoring'.format(ip=self.ip))
+            return
+        elif cmd not in self.pjlink_functions:
+            log.warn('({ip}) Future command received - unable to process yet'.format(ip=self.ip))
+            return
+        elif data in PJLINK_ERRORS:
             # Oops - projector error
             log.error('({ip}) Projector returned error "{data}"'.format(ip=self.ip, data=data))
             if data.upper() == 'ERRA':
@@ -624,14 +643,11 @@
             self.send_busy = False
             self.projectorReceivedData.emit()
             return
-
-        if cmd in self.pjlink_functions:
-            log.debug('({ip}) Calling function for {cmd}'.format(ip=self.ip, cmd=cmd))
-            self.pjlink_functions[cmd](data)
-        else:
-            log.warning('({ip}) Invalid command {data}'.format(ip=self.ip, data=cmd))
+        # Command checks already passed
+        log.debug('({ip}) Calling function for {cmd}'.format(ip=self.ip, cmd=cmd))
         self.send_busy = False
         self.projectorReceivedData.emit()
+        self.pjlink_functions[cmd](data)
 
     def process_lamp(self, data):
         """

=== added file 'openlp/core/lib/projector/upgrade.py'
--- openlp/core/lib/projector/upgrade.py	1970-01-01 00:00:00 +0000
+++ openlp/core/lib/projector/upgrade.py	2017-05-27 18:29:46 +0000
@@ -0,0 +1,73 @@
+# -*- 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                          #
+###############################################################################
+"""
+The :mod:`upgrade` module provides a way for the database and schema that is the
+backend for the Songs plugin
+"""
+import logging
+
+# Not all imports used at this time, but keep for future upgrades
+from sqlalchemy import Column, types
+from sqlalchemy.sql.expression import null
+
+from openlp.core.common.db import drop_columns
+from openlp.core.lib.db import get_upgrade_op
+
+log = logging.getLogger(__name__)
+
+# Initial projector DB was unversioned
+__version__ = 2
+
+log.debug('Projector DB upgrade module loading')
+
+
+def upgrade_1(session, metadata):
+    """
+    Version 1 upgrade - old db might/might not be versioned.
+    """
+    pass
+
+
+def upgrade_2(session, metadata):
+    """
+    Version 2 upgrade.
+
+    Update Projector() table to include new data defined in PJLink version 2 changes
+
+    serial_no:      Column(String(30))
+    sw_version:     Column(String(30))
+    model_filter:   Column(String(30))
+    model_lamp:     Column(String(30))
+
+    :param session: DB session instance
+    :param metadata: Metadata of current DB
+    """
+
+    new_op = get_upgrade_op(session)
+    if 'serial_no' not in [t.name for t in metadata.tables.values()]:
+        log.debug("Upgrading projector DB to version '2'")
+        new_op.add_column('projector', Column('serial_no', types.String(30), server_default=null()))
+        new_op.add_column('projector', Column('sw_version', types.String(30), server_default=null()))
+        new_op.add_column('projector', Column('model_filter', types.String(30), server_default=null()))
+        new_op.add_column('projector', Column('model_lamp', types.String(30), server_default=null()))
+    else:
+        log_warn("Skipping upgrade_2 of projector DB")

=== modified file 'openlp/core/ui/lib/pathedit.py'
--- openlp/core/ui/lib/pathedit.py	2017-05-22 18:22:43 +0000
+++ openlp/core/ui/lib/pathedit.py	2017-05-27 18:29:46 +0000
@@ -46,16 +46,16 @@
 
         :param parent: The parent of the widget. This is just passed to the super method.
         :type parent: QWidget or None
-        
+
         :param dialog_caption: Used to customise the caption in the QFileDialog.
         :param dialog_caption: str
-        
+
         :param default_path: The default path. This is set as the path when the revert button is clicked
         :type default_path: str
 
         :param show_revert: Used to determin if the 'revert button' should be visible.
         :type show_revert: bool
-        
+
         :return: None
         :rtype: None
         """
@@ -72,7 +72,7 @@
         Set up the widget
         :param show_revert: Show or hide the revert button
         :type show_revert: bool
-        
+
         :return: None
         :rtype: None
         """

=== modified file 'openlp/core/ui/projector/manager.py'
--- openlp/core/ui/projector/manager.py	2017-05-20 05:51:58 +0000
+++ openlp/core/ui/projector/manager.py	2017-05-27 18:29:46 +0000
@@ -662,6 +662,20 @@
             message = '%s<b>%s</b>: %s<br />' % (message,
                                                  translate('OpenLP.ProjectorManager', 'Current source input is'),
                                                  projector.link.source)
+            if projector.link.pjlink_class == '2':
+                # Information only available for PJLink Class 2 projectors
+                message += '<b>{title}</b>: {data}<br /><br />'.format(title=translate('OpenLP.ProjectorManager',
+                                                                                       'Serial Number'),
+                                                                       data=projector.serial_no)
+                message += '<b>{title}</b>: {data}<br /><br />'.format(title=translate('OpenLP.ProjectorManager',
+                                                                                       'Software Version'),
+                                                                       data=projector.sw_version)
+                message += '<b>{title}</b>: {data}<br /><br />'.format(title=translate('OpenLP.ProjectorManager',
+                                                                                       'Lamp type'),
+                                                                       data=projector.model_lamp)
+                message += '<b>{title}</b>: {data}<br /><br />'.format(title=translate('OpenLP.ProjectorManager',
+                                                                                       'Filter type'),
+                                                                       data=projector.model_filter)
             count = 1
             for item in projector.link.lamp:
                 message += '<b>{title} {count}</b> {status} '.format(title=translate('OpenLP.ProjectorManager',

=== modified file 'openlp/plugins/presentations/presentationplugin.py'
--- openlp/plugins/presentations/presentationplugin.py	2017-05-22 18:27:40 +0000
+++ openlp/plugins/presentations/presentationplugin.py	2017-05-27 18:29:46 +0000
@@ -1,4 +1,4 @@
-    # -*- coding: utf-8 -*-
+# -*- coding: utf-8 -*-
 # vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
 
 ###############################################################################

=== modified file 'openlp/plugins/songusage/forms/songusagedetaildialog.py'
--- openlp/plugins/songusage/forms/songusagedetaildialog.py	2017-05-22 18:22:43 +0000
+++ openlp/plugins/songusage/forms/songusagedetaildialog.py	2017-05-27 18:29:46 +0000
@@ -69,7 +69,7 @@
         self.file_horizontal_layout.setSpacing(8)
         self.file_horizontal_layout.setContentsMargins(8, 8, 8, 8)
         self.file_horizontal_layout.setObjectName('file_horizontal_layout')
-        self.report_path_edit = PathEdit(self.file_group_box, path_type = PathType.Directories, show_revert=False)
+        self.report_path_edit = PathEdit(self.file_group_box, path_type=PathType.Directories, show_revert=False)
         self.file_horizontal_layout.addWidget(self.report_path_edit)
         self.vertical_layout.addWidget(self.file_group_box)
         self.button_box = create_button_box(song_usage_detail_dialog, 'button_box', ['cancel', 'ok'])

=== modified file 'tests/functional/openlp_core_lib/test_projector_pjlink1.py'
--- tests/functional/openlp_core_lib/test_projector_pjlink1.py	2017-05-20 05:51:58 +0000
+++ tests/functional/openlp_core_lib/test_projector_pjlink1.py	2017-05-27 18:29:46 +0000
@@ -384,21 +384,6 @@
         self.assertEquals("{test}".format(test=mock_send_command.call_args),
                           "call(data='{hash}%1CLSS ?\\r')".format(hash=TEST_HASH))
 
-    @patch.object(pjlink_test, '_not_implemented')
-    def not_implemented_test(self, mock_not_implemented):
-        """
-        Test PJLink._not_implemented method being called
-        """
-        # GIVEN: test object
-        pjlink = pjlink_test
-        test_cmd = 'TESTMEONLY'
-
-        # WHEN: A future command is called that is not implemented yet
-        pjlink.process_command(test_cmd, "Garbage data for test only")
-
-        # THEN: PJLink.__not_implemented should have been called with test_cmd
-        mock_not_implemented.assert_called_with(test_cmd)
-
     @patch.object(pjlink_test, 'disconnect_from_host')
     def socket_abort_test(self, mock_disconnect):
         """

=== modified file 'tests/functional/openlp_core_lib/test_projectordb.py'
--- tests/functional/openlp_core_lib/test_projectordb.py	2017-05-20 05:51:58 +0000
+++ tests/functional/openlp_core_lib/test_projectordb.py	2017-05-27 18:29:46 +0000
@@ -27,11 +27,15 @@
 """
 import os
 import shutil
-from unittest import TestCase
+from tempfile import mkdtemp
+
+from unittest import TestCase, skip
 from unittest.mock import MagicMock, patch
 
+from openlp.core.lib.projector import upgrade
+from openlp.core.lib.db import upgrade_db
+from openlp.core.lib.projector.constants import PJLINK_PORT
 from openlp.core.lib.projector.db import Manufacturer, Model, Projector, ProjectorDB, ProjectorSource, Source
-from openlp.core.lib.projector.constants import PJLINK_PORT
 
 from tests.resources.projector.data import TEST_DB_PJLINK1, TEST_DB, TEST1_DATA, TEST2_DATA, TEST3_DATA
 from tests.utils.constants import TEST_RESOURCES_PATH
@@ -85,6 +89,42 @@
     return added
 
 
+class TestProjectorDBUpdate(TestCase):
+    """
+    Test case for upgrading Projector DB.
+    NOTE: Separate class so I don't have to look for upgrade tests.
+    """
+    def setUp(self):
+        """
+        Setup for tests
+        """
+        self.tmp_folder = mkdtemp(prefix='openlp_')
+
+    def tearDown(self):
+        """
+        Clean up after tests
+        """
+        # Ignore errors since windows can have problems with locked files
+        shutil.rmtree(self.tmp_folder, ignore_errors=True)
+
+    def test_upgrade_old_projector_db(self):
+        """
+        Test that we can upgrade an old song db to the current schema
+        """
+        # GIVEN: An old song db
+        old_db = os.path.join(TEST_RESOURCES_PATH, "projector", TEST_DB_PJLINK1)
+        tmp_db = os.path.join(self.tmp_folder, TEST_DB)
+        shutil.copyfile(old_db, tmp_db)
+        db_url = 'sqlite:///{db}'.format(db=tmp_db)
+
+        # WHEN: upgrading the db
+        updated_to_version, latest_version = upgrade_db(db_url, upgrade)
+
+        # THEN: the song db should have been upgraded to the latest version
+        self.assertEqual(updated_to_version, latest_version,
+                         'The projector DB should have been upgrade to the latest version')
+
+
 class TestProjectorDB(TestCase):
     """
     Test case for ProjectorDB
@@ -94,7 +134,9 @@
         """
         Set up anything necessary for all tests
         """
-        mocked_init_url.return_value = 'sqlite:///{db}'.format(db=TEST_DB)
+        self.tmp_folder = mkdtemp(prefix='openlp_')
+        tmpdb_url = 'sqlite:///{db}'.format(db=os.path.join(self.tmp_folder, TEST_DB))
+        mocked_init_url.return_value = tmpdb_url
         self.projector = ProjectorDB()
 
     def tearDown(self):
@@ -103,15 +145,8 @@
         """
         self.projector.session.close()
         self.projector = None
-        retries = 0
-        while retries < 5:
-            try:
-                if os.path.exists(TEST_DB):
-                    os.unlink(TEST_DB)
-                break
-            except:
-                time.sleep(1)
-                retries += 1
+        # Ignore errors since windows can have problems with locked files
+        shutil.rmtree(self.tmp_folder, ignore_errors=True)
 
     def test_find_record_by_ip(self):
         """

=== modified file 'tests/resources/projector/data.py'
--- tests/resources/projector/data.py	2017-05-20 05:51:58 +0000
+++ tests/resources/projector/data.py	2017-05-27 18:29:46 +0000
@@ -29,7 +29,7 @@
 # Test data
 TEST_DB_PJLINK1 = 'projector_pjlink1.sqlite'
 
-TEST_DB = os.path.join(gettempdir(), 'openlp-test-projectordb.sql')
+TEST_DB = 'openlp-test-projectordb.sqlite'
 
 TEST_SALT = '498e4a67'
 
@@ -39,8 +39,6 @@
 
 TEST_CONNECT_AUTHENTICATE = 'PJLink 1 {salt}'.format(salt=TEST_SALT)
 
-TEST_DB = os.path.join(gettempdir(), 'openlp-test-projectordb.sql')
-
 TEST1_DATA = dict(ip='111.111.111.111',
                   port='1111',
                   pin='1111',


Follow ups