diff --git a/openlp/core/lib/db.py b/openlp/core/lib/db.py index b49539080..6eb67b5df 100644 --- a/openlp/core/lib/db.py +++ b/openlp/core/lib/db.py @@ -55,7 +55,7 @@ def init_db(url, auto_flush=True, auto_commit=False, base=None): metadata = MetaData(bind=engine) else: base.metadata.bind = engine - metadata = None + metadata = base.metadata session = scoped_session(sessionmaker(autoflush=auto_flush, autocommit=auto_commit, bind=engine)) return session, metadata @@ -227,12 +227,9 @@ class Manager(object): """ self.is_dirty = False self.session = None - # See if we're using declarative_base with a pre-existing session. - log.debug('Manager: Testing for pre-existing session') - if session is not None: - log.debug('Manager: Using existing session') - else: - log.debug('Manager: Creating new session') + self.db_url = None + if db_file_name: + log.debug('Manager: Creating new DB url') self.db_url = init_url(plugin_name, db_file_name) if upgrade_mod: try: @@ -248,10 +245,13 @@ class Manager(object): 'not be loaded.\n\nDatabase: %s') % (db_ver, up_ver, self.db_url) ) return - try: - self.session = init_schema(self.db_url) - except (SQLAlchemyError, DBAPIError): - handle_db_error(plugin_name, db_file_name) + if not session: + try: + self.session = init_schema(self.db_url) + except (SQLAlchemyError, DBAPIError): + handle_db_error(plugin_name, db_file_name) + else: + self.session = session def save_object(self, object_instance, commit=True): """ @@ -344,13 +344,13 @@ class Manager(object): for try_count in range(3): try: return self.session.query(object_class).filter(filter_clause).first() - except OperationalError: + except OperationalError as oe: # This exception clause is for users running MySQL which likes to terminate connections on its own # without telling anyone. See bug #927473. However, other dbms can raise it, usually in a # non-recoverable way. So we only retry 3 times. - log.exception('Probably a MySQL issue, "MySQL has gone away"') - if try_count >= 2: + if try_count >= 2 or 'MySQL has gone away' in str(oe): raise + log.exception('Probably a MySQL issue, "MySQL has gone away"') def get_all_objects(self, object_class, filter_clause=None, order_by_ref=None): """ diff --git a/openlp/core/lib/projector/db.py b/openlp/core/lib/projector/db.py index 670c9e31b..3e050bf22 100644 --- a/openlp/core/lib/projector/db.py +++ b/openlp/core/lib/projector/db.py @@ -20,18 +20,18 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### """ - :mod:`openlp.core.lib.projector.db` module +:mod:`openlp.core.lib.projector.db` module - Provides the database functions for the Projector module. +Provides the database functions for the Projector module. - The Manufacturer, Model, Source tables keep track of the video source - strings used for display of input sources. The Source table maps - manufacturer-defined or user-defined strings from PJLink default strings - to end-user readable strings; ex: PJLink code 11 would map "RGB 1" - default string to "RGB PC (analog)" string. - (Future feature). +The Manufacturer, Model, Source tables keep track of the video source +strings used for display of input sources. The Source table maps +manufacturer-defined or user-defined strings from PJLink default strings +to end-user readable strings; ex: PJLink code 11 would map "RGB 1" +default string to "RGB PC (analog)" string. +(Future feature). - The Projector table keeps track of entries for controlled projectors. +The Projector table keeps track of entries for controlled projectors. """ import logging @@ -218,19 +218,19 @@ class ProjectorDB(Manager): """ def __init__(self, *args, **kwargs): log.debug('ProjectorDB().__init__(args="%s", kwargs="%s")' % (args, kwargs)) - super().__init__(plugin_name='projector', - init_schema=self.init_schema) + super().__init__(plugin_name='projector', init_schema=self.init_schema) log.debug('ProjectorDB() Initialized using db url %s' % self.db_url) + log.debug('Session: %s', self.session) - def init_schema(*args, **kwargs): + def init_schema(self, *args, **kwargs): """ Setup the projector database and initialize the schema. Declarative uses table classes to define schema. """ - url = init_url('projector') - session, metadata = init_db(url, base=Base) - Base.metadata.create_all(checkfirst=True) + self.db_url = init_url('projector') + session, metadata = init_db(self.db_url, base=Base) + metadata.create_all(checkfirst=True) return session def get_projector_by_id(self, dbid): diff --git a/tests/functional/openlp_core_lib/test_projectordb.py b/tests/functional/openlp_core_lib/test_projectordb.py index a6902ad2c..0105caa07 100644 --- a/tests/functional/openlp_core_lib/test_projectordb.py +++ b/tests/functional/openlp_core_lib/test_projectordb.py @@ -25,12 +25,12 @@ record functions. PREREQUISITE: add_record() and get_all() functions validated. """ - +import os from unittest import TestCase -from tests.functional import MagicMock, patch from openlp.core.lib.projector.db import Projector, ProjectorDB, ProjectorSource +from tests.functional import MagicMock, patch from tests.resources.projector.data import TEST1_DATA, TEST2_DATA, TEST3_DATA tmpfile = '/tmp/openlp-test-projectordb.sql' @@ -60,15 +60,15 @@ def compare_source(one, two): one.text == two.text -def add_records(self, test): +def add_records(projector_db, test): """ Add record if not in database """ - record_list = self.projector.get_projector_all() + record_list = projector_db.get_projector_all() if len(record_list) < 1: added = False for record in test: - added = self.projector.add_projector(record) or added + added = projector_db.add_projector(record) or added return added for new_record in test: @@ -76,7 +76,7 @@ def add_records(self, test): for record in record_list: if compare_data(record, new_record): break - added = self.projector.add_projector(new_record) + added = projector_db.add_projector(new_record) return added @@ -88,10 +88,11 @@ class TestProjectorDB(TestCase): """ Set up anything necessary for all tests """ - if not hasattr(self, 'projector'): - with patch('openlp.core.lib.projector.db.init_url') as mocked_init_url: - mocked_init_url.return_value = 'sqlite:///%s' % tmpfile - self.projector = ProjectorDB() + with patch('openlp.core.lib.projector.db.init_url') as mocked_init_url: + if os.path.exists(tmpfile): + os.unlink(tmpfile) + mocked_init_url.return_value = 'sqlite:///%s' % tmpfile + self.projector = ProjectorDB() def tearDown(self): """ @@ -104,7 +105,7 @@ class TestProjectorDB(TestCase): Test find record by IP """ # GIVEN: Record entries in database - add_records(self, [TEST1_DATA, TEST2_DATA]) + add_records(self.projector, [TEST1_DATA, TEST2_DATA]) # WHEN: Search for record using IP record = self.projector.get_projector_by_ip(TEST2_DATA.ip) @@ -118,7 +119,7 @@ class TestProjectorDB(TestCase): Test find record by name """ # GIVEN: Record entries in database - add_records(self, [TEST1_DATA, TEST2_DATA]) + add_records(self.projector, [TEST1_DATA, TEST2_DATA]) # WHEN: Search for record using name record = self.projector.get_projector_by_name(TEST2_DATA.name) @@ -132,7 +133,7 @@ class TestProjectorDB(TestCase): Test record can be deleted """ # GIVEN: Record in database - add_records(self, [TEST3_DATA, ]) + add_records(self.projector, [TEST3_DATA, ]) record = self.projector.get_projector_by_ip(TEST3_DATA.ip) # WHEN: Record deleted @@ -147,7 +148,7 @@ class TestProjectorDB(TestCase): Test edited record returns the same record ID with different data """ # GIVEN: Record entries in database - add_records(self, [TEST1_DATA, TEST2_DATA]) + add_records(self.projector, [TEST1_DATA, TEST2_DATA]) # WHEN: We retrieve a specific record record = self.projector.get_projector_by_ip(TEST1_DATA.ip)