forked from openlp/openlp
Fix db.Manager upgrade/PJlink2 update D
This commit is contained in:
parent
533bef159a
commit
3ea37800b7
@ -144,6 +144,7 @@ def upgrade_db(url, upgrade):
|
|||||||
:param url: The url of the database to upgrade.
|
:param url: The url of the database to upgrade.
|
||||||
:param upgrade: The python module that contains the upgrade instructions.
|
: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)
|
session, metadata = init_db(url)
|
||||||
|
|
||||||
class Metadata(BaseModel):
|
class Metadata(BaseModel):
|
||||||
@ -160,17 +161,15 @@ def upgrade_db(url, upgrade):
|
|||||||
metadata_table.create(checkfirst=True)
|
metadata_table.create(checkfirst=True)
|
||||||
mapper(Metadata, metadata_table)
|
mapper(Metadata, metadata_table)
|
||||||
version_meta = session.query(Metadata).get('version')
|
version_meta = session.query(Metadata).get('version')
|
||||||
if version_meta is None:
|
if version_meta:
|
||||||
# Tables have just been created - fill the version field with the most recent version
|
version = int(version_meta.value)
|
||||||
if session.query(Metadata).get('dbversion'):
|
else:
|
||||||
version = 0
|
# Due to issues with other checks, if the version is not set in the DB then default to 0
|
||||||
else:
|
# and let the upgrade function handle the checks
|
||||||
version = upgrade.__version__
|
version = 0
|
||||||
version_meta = Metadata.populate(key='version', value=version)
|
version_meta = Metadata.populate(key='version', value=version)
|
||||||
session.add(version_meta)
|
session.add(version_meta)
|
||||||
session.commit()
|
session.commit()
|
||||||
else:
|
|
||||||
version = int(version_meta.value)
|
|
||||||
if version > upgrade.__version__:
|
if version > upgrade.__version__:
|
||||||
session.remove()
|
session.remove()
|
||||||
return version, upgrade.__version__
|
return version, upgrade.__version__
|
||||||
|
@ -59,33 +59,61 @@ TIMEOUT = 30.0
|
|||||||
PJLINK_MAX_PACKET = 136
|
PJLINK_MAX_PACKET = 136
|
||||||
# NOTE: Change format to account for some commands are both class 1 and 2
|
# NOTE: Change format to account for some commands are both class 1 and 2
|
||||||
PJLINK_VALID_CMD = {
|
PJLINK_VALID_CMD = {
|
||||||
'ACKN': ['2', ], # UDP Reply to 'SRCH'
|
'ACKN': {'version': ['2', ], # UDP Reply to 'SRCH'
|
||||||
'AVMT': ['1', ], # Shutter option
|
'description': 'Acknowledge a PJLink SRCH command - returns MAC address.'},
|
||||||
'CLSS': ['1', ], # PJLink class support query
|
'AVMT': {'version': ['1', ],
|
||||||
'ERST': ['1', '2'], # Error status option
|
'description': 'Blank/unblank video and/or mute audio.'},
|
||||||
'FILT': ['2', ], # Get current filter usage time
|
'CLSS': {'version': ['1', ],
|
||||||
'FREZ': ['2', ], # Set freeze/unfreeze picture being projected
|
'description': 'Query projector PJLink class support.'},
|
||||||
'INF1': ['1', ], # Manufacturer name query
|
'ERST': {'version': ['1', '2'],
|
||||||
'INF2': ['1', ], # Product name query
|
'description': 'Query error status from projector. '
|
||||||
'INFO': ['1', ], # Other information query
|
'Returns fan/lamp/temp/cover/filter/other error status.'},
|
||||||
'INNM': ['2', ], # Get Video source input terminal name
|
'FILT': {'version': ['2', ], # Assume (!) time in hours
|
||||||
'INPT': ['1', ], # Video sources option
|
'description': 'Query number of hours on filter.'},
|
||||||
'INST': ['1', ], # Input sources available query
|
'FREZ': {'version': ['2', ],
|
||||||
'IRES': ['2', ], # Get Video source resolution
|
'description': 'Freeze or unfreeze current image being projected.'},
|
||||||
'LAMP': ['1', ], # Lamp(s) query (Includes fans)
|
'INF1': {'version': ['1', ],
|
||||||
'LKUP': ['2', ], # UPD Linkup status notification
|
'description': 'Query projector manufacturer name.'},
|
||||||
'MVOL': ['2', ], # Set microphone volume
|
'INF2': {'version': ['1', ],
|
||||||
'NAME': ['1', ], # Projector name query
|
'description': 'Query projector product name.'},
|
||||||
'PJLINK': ['1', ], # Initial connection
|
'INFO': {'version': ['1', ],
|
||||||
'POWR': ['1', ], # Power option
|
'description': 'Query projector for other information set by manufacturer.'},
|
||||||
'RFIL': ['2', ], # Get replacement air filter model number
|
'INNM': {'version': ['2', ],
|
||||||
'RLMP': ['2', ], # Get lamp replacement model number
|
'description': 'Query specified input source name'},
|
||||||
'RRES': ['2', ], # Get projector recommended video resolution
|
'INPT': {'version': ['1', ],
|
||||||
'SNUM': ['2', ], # Get projector serial number
|
'description': 'Switch to specified video source.'},
|
||||||
'SRCH': ['2', ], # UDP broadcast search for available projectors on local network
|
'INST': {'version': ['1', ],
|
||||||
'SVER': ['2', ], # Get projector software version
|
'description': 'Query available input sources.'},
|
||||||
'SVOL': ['2', ] # Set speaker volume
|
'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
|
# Error and status codes
|
||||||
S_OK = E_OK = 0 # E_OK included since I sometimes forget
|
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.
|
# Error codes. Start at 200 so we don't duplicate system error codes.
|
||||||
|
@ -44,6 +44,7 @@ from sqlalchemy.orm import relationship
|
|||||||
|
|
||||||
from openlp.core.lib.db import Manager, init_db, init_url
|
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.constants import PJLINK_DEFAULT_CODES
|
||||||
|
from openlp.core.lib.projector import upgrade
|
||||||
|
|
||||||
Base = declarative_base(MetaData())
|
Base = declarative_base(MetaData())
|
||||||
|
|
||||||
@ -243,7 +244,9 @@ class ProjectorDB(Manager):
|
|||||||
"""
|
"""
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
log.debug('ProjectorDB().__init__(args="{arg}", kwargs="{kwarg}")'.format(arg=args, kwarg=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('ProjectorDB() Initialized using db url {db}'.format(db=self.db_url))
|
||||||
log.debug('Session: {session}'.format(session=self.session))
|
log.debug('Session: {session}'.format(session=self.session))
|
||||||
|
|
||||||
|
@ -186,10 +186,15 @@ class PJLink(QtNetwork.QTcpSocket):
|
|||||||
self.pjlink_name = None
|
self.pjlink_name = None
|
||||||
self.manufacturer = None
|
self.manufacturer = None
|
||||||
self.model = None
|
self.model = None
|
||||||
|
self.serial_no = None
|
||||||
|
self.sw_version = None
|
||||||
self.shutter = None
|
self.shutter = None
|
||||||
self.mute = None
|
self.mute = None
|
||||||
self.lamp = None
|
self.lamp = None
|
||||||
|
self.model_lamp = None
|
||||||
self.fan = None
|
self.fan = None
|
||||||
|
self.filter_time = None
|
||||||
|
self.model_filter = None
|
||||||
self.source_available = None
|
self.source_available = None
|
||||||
self.source = None
|
self.source = None
|
||||||
self.other_info = None
|
self.other_info = None
|
||||||
@ -451,14 +456,14 @@ class PJLink(QtNetwork.QTcpSocket):
|
|||||||
return
|
return
|
||||||
data_split = data.split('=')
|
data_split = data.split('=')
|
||||||
try:
|
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:
|
except ValueError as e:
|
||||||
log.warning('({ip}) get_data(): Invalid packet - expected header + command + data'.format(ip=self.ip))
|
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()))
|
log.warning('({ip}) get_data(): Received data: "{data}"'.format(ip=self.ip, data=data_in.strip()))
|
||||||
self.change_status(E_INVALID_DATA)
|
self.change_status(E_INVALID_DATA)
|
||||||
self.receive_data_signal()
|
self.receive_data_signal()
|
||||||
return
|
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))
|
log.warning('({ip}) get_data(): Invalid packet - unknown command "{data}"'.format(ip=self.ip, data=cmd))
|
||||||
self.receive_data_signal()
|
self.receive_data_signal()
|
||||||
return
|
return
|
||||||
@ -507,14 +512,25 @@ class PJLink(QtNetwork.QTcpSocket):
|
|||||||
log.warning('({ip}) send_command(): Not connected - returning'.format(ip=self.ip))
|
log.warning('({ip}) send_command(): Not connected - returning'.format(ip=self.ip))
|
||||||
self.send_queue = []
|
self.send_queue = []
|
||||||
return
|
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)
|
self.projectorNetwork.emit(S_NETWORK_SENDING)
|
||||||
log.debug('({ip}) send_command(): Building cmd="{command}" opts="{data}"{salt}'.format(ip=self.ip,
|
log.debug('({ip}) send_command(): Building cmd="{command}" opts="{data}"{salt}'.format(ip=self.ip,
|
||||||
command=cmd,
|
command=cmd,
|
||||||
data=opts,
|
data=opts,
|
||||||
salt='' if salt is None
|
salt='' if salt is None
|
||||||
else ' with hash'))
|
else ' with hash'))
|
||||||
# TODO: Check for class of command rather than default to projector PJLink class
|
cmd_ver = PJLINK_VALID_CMD[cmd]['version']
|
||||||
header = PJLINK_HEADER.format(linkclass=self.pjlink_class)
|
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,
|
out = '{salt}{header}{command} {options}{suffix}'.format(salt="" if salt is None else salt,
|
||||||
header=header,
|
header=header,
|
||||||
command=cmd,
|
command=cmd,
|
||||||
@ -589,10 +605,13 @@ class PJLink(QtNetwork.QTcpSocket):
|
|||||||
cmd=cmd,
|
cmd=cmd,
|
||||||
data=data))
|
data=data))
|
||||||
# Check if we have a future command not available yet
|
# Check if we have a future command not available yet
|
||||||
if cmd in self.pjlink_future:
|
if cmd not in PJLINK_VALID_CMD:
|
||||||
self._not_implemented(cmd)
|
log.error('({ip}) Unknown command received - ignoring'.format(ip=self.ip))
|
||||||
return
|
return
|
||||||
if data in PJLINK_ERRORS:
|
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
|
# Oops - projector error
|
||||||
log.error('({ip}) Projector returned error "{data}"'.format(ip=self.ip, data=data))
|
log.error('({ip}) Projector returned error "{data}"'.format(ip=self.ip, data=data))
|
||||||
if data.upper() == 'ERRA':
|
if data.upper() == 'ERRA':
|
||||||
@ -624,14 +643,11 @@ class PJLink(QtNetwork.QTcpSocket):
|
|||||||
self.send_busy = False
|
self.send_busy = False
|
||||||
self.projectorReceivedData.emit()
|
self.projectorReceivedData.emit()
|
||||||
return
|
return
|
||||||
|
# Command checks already passed
|
||||||
if cmd in self.pjlink_functions:
|
log.debug('({ip}) Calling function for {cmd}'.format(ip=self.ip, cmd=cmd))
|
||||||
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))
|
|
||||||
self.send_busy = False
|
self.send_busy = False
|
||||||
self.projectorReceivedData.emit()
|
self.projectorReceivedData.emit()
|
||||||
|
self.pjlink_functions[cmd](data)
|
||||||
|
|
||||||
def process_lamp(self, data):
|
def process_lamp(self, data):
|
||||||
"""
|
"""
|
||||||
|
73
openlp/core/lib/projector/upgrade.py
Normal file
73
openlp/core/lib/projector/upgrade.py
Normal file
@ -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")
|
@ -662,6 +662,20 @@ class ProjectorManager(OpenLPMixin, RegistryMixin, QtWidgets.QWidget, UiProjecto
|
|||||||
message = '%s<b>%s</b>: %s<br />' % (message,
|
message = '%s<b>%s</b>: %s<br />' % (message,
|
||||||
translate('OpenLP.ProjectorManager', 'Current source input is'),
|
translate('OpenLP.ProjectorManager', 'Current source input is'),
|
||||||
projector.link.source)
|
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
|
count = 1
|
||||||
for item in projector.link.lamp:
|
for item in projector.link.lamp:
|
||||||
message += '<b>{title} {count}</b> {status} '.format(title=translate('OpenLP.ProjectorManager',
|
message += '<b>{title} {count}</b> {status} '.format(title=translate('OpenLP.ProjectorManager',
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
|
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
@ -69,7 +69,7 @@ class Ui_SongUsageDetailDialog(object):
|
|||||||
self.file_horizontal_layout.setSpacing(8)
|
self.file_horizontal_layout.setSpacing(8)
|
||||||
self.file_horizontal_layout.setContentsMargins(8, 8, 8, 8)
|
self.file_horizontal_layout.setContentsMargins(8, 8, 8, 8)
|
||||||
self.file_horizontal_layout.setObjectName('file_horizontal_layout')
|
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.file_horizontal_layout.addWidget(self.report_path_edit)
|
||||||
self.vertical_layout.addWidget(self.file_group_box)
|
self.vertical_layout.addWidget(self.file_group_box)
|
||||||
self.button_box = create_button_box(song_usage_detail_dialog, 'button_box', ['cancel', 'ok'])
|
self.button_box = create_button_box(song_usage_detail_dialog, 'button_box', ['cancel', 'ok'])
|
||||||
|
@ -384,21 +384,6 @@ class TestPJLink(TestCase):
|
|||||||
self.assertEquals("{test}".format(test=mock_send_command.call_args),
|
self.assertEquals("{test}".format(test=mock_send_command.call_args),
|
||||||
"call(data='{hash}%1CLSS ?\\r')".format(hash=TEST_HASH))
|
"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')
|
@patch.object(pjlink_test, 'disconnect_from_host')
|
||||||
def socket_abort_test(self, mock_disconnect):
|
def socket_abort_test(self, mock_disconnect):
|
||||||
"""
|
"""
|
||||||
|
@ -27,11 +27,15 @@ PREREQUISITE: add_record() and get_all() functions validated.
|
|||||||
"""
|
"""
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
from unittest import TestCase
|
from tempfile import mkdtemp
|
||||||
|
|
||||||
|
from unittest import TestCase, skip
|
||||||
from unittest.mock import MagicMock, patch
|
from unittest.mock import MagicMock, patch
|
||||||
|
|
||||||
from openlp.core.lib.projector.db import Manufacturer, Model, Projector, ProjectorDB, ProjectorSource, Source
|
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.constants import PJLINK_PORT
|
||||||
|
from openlp.core.lib.projector.db import Manufacturer, Model, Projector, ProjectorDB, ProjectorSource, Source
|
||||||
|
|
||||||
from tests.resources.projector.data import TEST_DB_PJLINK1, TEST_DB, TEST1_DATA, TEST2_DATA, TEST3_DATA
|
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
|
from tests.utils.constants import TEST_RESOURCES_PATH
|
||||||
@ -85,6 +89,42 @@ def add_records(projector_db, test):
|
|||||||
return added
|
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):
|
class TestProjectorDB(TestCase):
|
||||||
"""
|
"""
|
||||||
Test case for ProjectorDB
|
Test case for ProjectorDB
|
||||||
@ -94,7 +134,9 @@ class TestProjectorDB(TestCase):
|
|||||||
"""
|
"""
|
||||||
Set up anything necessary for all tests
|
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()
|
self.projector = ProjectorDB()
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
@ -103,15 +145,8 @@ class TestProjectorDB(TestCase):
|
|||||||
"""
|
"""
|
||||||
self.projector.session.close()
|
self.projector.session.close()
|
||||||
self.projector = None
|
self.projector = None
|
||||||
retries = 0
|
# Ignore errors since windows can have problems with locked files
|
||||||
while retries < 5:
|
shutil.rmtree(self.tmp_folder, ignore_errors=True)
|
||||||
try:
|
|
||||||
if os.path.exists(TEST_DB):
|
|
||||||
os.unlink(TEST_DB)
|
|
||||||
break
|
|
||||||
except:
|
|
||||||
time.sleep(1)
|
|
||||||
retries += 1
|
|
||||||
|
|
||||||
def test_find_record_by_ip(self):
|
def test_find_record_by_ip(self):
|
||||||
"""
|
"""
|
||||||
|
@ -29,7 +29,7 @@ from tempfile import gettempdir
|
|||||||
# Test data
|
# Test data
|
||||||
TEST_DB_PJLINK1 = 'projector_pjlink1.sqlite'
|
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'
|
TEST_SALT = '498e4a67'
|
||||||
|
|
||||||
@ -39,8 +39,6 @@ TEST_HASH = '5d8409bc1c3fa39749434aa3a5c38682'
|
|||||||
|
|
||||||
TEST_CONNECT_AUTHENTICATE = 'PJLink 1 {salt}'.format(salt=TEST_SALT)
|
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',
|
TEST1_DATA = dict(ip='111.111.111.111',
|
||||||
port='1111',
|
port='1111',
|
||||||
pin='1111',
|
pin='1111',
|
||||||
|
Loading…
Reference in New Issue
Block a user