Missing DB in unmounted disk results in Traceback

Bug #1624661 reported by Azaziah
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
OpenLP
Fix Committed
Low
Tomas Groth
2.4
Fix Released
Low
Tomas Groth

Bug Description

When data folder was moved from E: to D:, the following traceback
appears on startup after a few "Missing DB messages.

This is probably happening because the drive E: was dismounted and no longer available. Changing the path in registry fixed this issue.

Trunk 2696 | Win 10

Traceback (most recent call last):
  File "openlp.py", line 44, in <module>
    main()
  File "D:\bzr\openlp\trunk\openlp\core\__init__.py", line 392, in main
    sys.exit(application.run(qt_args))
  File "D:\bzr\openlp\trunk\openlp\core\common\openlpmixin.py", line 59, in wrapped
    raise e
  File "D:\bzr\openlp\trunk\openlp\core\common\openlpmixin.py", line 54, in wrapped
    return func(*args, **kwargs)
  File "D:\bzr\openlp\trunk\openlp\core\__init__.py", line 142, in run
    Registry().execute('bootstrap_initialise')
  File "D:\bzr\openlp\trunk\openlp\core\common\registry.py", line 137, in execute
    result = function(*args, **kwargs)
  File "D:\bzr\openlp\trunk\openlp\core\common\openlpmixin.py", line 59, in wrapped
    raise e
  File "D:\bzr\openlp\trunk\openlp\core\common\openlpmixin.py", line 54, in wrapped
    return func(*args, **kwargs)
  File "D:\bzr\openlp\trunk\openlp\core\lib\pluginmanager.py", line 59, in bootstrap_initialise
    self.hook_media_manager()
  File "D:\bzr\openlp\trunk\openlp\core\common\openlpmixin.py", line 59, in wrapped
    raise e
  File "D:\bzr\openlp\trunk\openlp\core\common\openlpmixin.py", line 54, in wrapped
    return func(*args, **kwargs)
  File "D:\bzr\openlp\trunk\openlp\core\lib\pluginmanager.py", line 123, in hook_media_manager
    plugin.create_media_manager_item()
  File "D:\bzr\openlp\trunk\openlp\core\lib\plugin.py", line 203, in create_media_manager_item
    self.media_item = self.media_item_class(self.main_window.media_dock_manager.media_dock, self)
  File "D:\bzr\openlp\trunk\openlp\plugins\images\lib\mediaitem.py", line 55, in __init__
    super(ImageMediaItem, self).__init__(parent, plugin)
  File "D:\bzr\openlp\trunk\openlp\core\lib\mediamanageritem.py", line 83, in __init__
    self.setup_item()
  File "D:\bzr\openlp\trunk\openlp\plugins\images\lib\mediaitem.py", line 68, in setup_item
    self.fill_groups_combobox(self.choose_group_form.group_combobox)
  File "D:\bzr\openlp\trunk\openlp\plugins\images\lib\mediaitem.py", line 300, in fill_groups_combobox
    image_groups = self.manager.get_all_objects(ImageGroups, ImageGroups.parent_id == parent_group_id)
  File "D:\bzr\openlp\trunk\openlp\core\lib\db.py", line 368, in get_all_objects
    query = self.session.query(object_class)
AttributeError: 'NoneType' object has no attribute 'query'

Related branches

Revision history for this message
Azaziah (suutari-olli) wrote :
Azaziah (suutari-olli)
description: updated
description: updated
summary: - Missing DB results in Traceback
+ Missing DB in unmounted disk results in Traceback
Changed in openlp:
importance: Undecided → Low
Azaziah (suutari-olli)
Changed in openlp:
assignee: nobody → Azaziah (suutari-olli)
status: New → In Progress
Revision history for this message
Phill (phill-ridout) wrote :

This is just a symptom of the actual problem!

Line openlp.core.common.applocation line 84, we assume that a path taken from the settings exists, where as if we are using the default location we actually check that it exists (and create it if we dont)! (openlp.core.common line 65)

openlp.core.common.applocation line 84
    def get_data_path():
        """
        Return the path OpenLP stores all its data under.
        """
        # Check if we have a different data location.
        if Settings().contains('advanced/data path'):
            path = Settings().value('advanced/data path')
        else:
            path = AppLocation.get_directory(AppLocation.DataDir)
            check_directory_exists(path)
        return os.path.normpath(path)

openlp.core.common line 65

    def check_directory_exists(directory, do_not_log=False):
        """
        Check a theme directory exists and if not create it

        :param directory: The directory to make sure exists
        :param do_not_log: To not log anything. This is need for the start up, when the log isn't ready.
        """
        if not do_not_log:
            log.debug('check_directory_exists {text}'.format(text=directory))
        try:
            if not os.path.exists(directory):
                os.makedirs(directory)
        except IOError as e:
            if not do_not_log:
                log.exception('failed to check if directory exists or create directory')

As we assume that the directory exists when openlp.core.lib.db.init_db line 43 is called, it raises an exception openlp/core/lib/db.py:254 and the session isn't created.

First part of my prefered solution would be to modify check_directory_exists (openlp.core.common line 65) to return a boolean value indicating if it exists or not.

Then I would make sure that get_data_path (openlp.core.common.applocation line 84) checks that the custom path exists. If the custom path does not exist, the user would be informed (in case of a removable drive, etc.), with an option of resetting the path back to default. If they chose that option then OpenLP could carry on loading (with out the data), or OpenLP would close to allow the user to make the data available (insert removable drive, mount network share etc)

Revision history for this message
Azaziah (suutari-olli) wrote :

https://gist.github.com/anonymous/10c11792c0b37ec3693bf9494017a3aa

This code fixes the issue, but I can't make it work with:
QtWidgets.QMessageBox.No/Yes.

At this point I'm getting rather frustrated with this issue and would gladly give it up for someone who's a better programmer.

\openlp\core\common\applocation.py

    @staticmethod
    def get_data_path():
        """
        Return the path OpenLP stores all its data under.
        """
        from openlp.core.lib.ui import critical_error_message_box
        from openlp.core.common import AppLocation, Settings, translate
        # Check if we have a different data location.
        if Settings().contains('advanced/data path'):
            path = Settings().value('advanced/data path')
            if not os.path.exists(path):
                critical_error_message_box(translate('OpenLP.Manager', 'Database Error'),
                                           translate('OpenLP.Manager',
                                                     'OpenLP cannot load your database.\n\nDatabase:'))
                Settings().remove('advanced/data path')
                path = AppLocation.get_directory(AppLocation.DataDir)
                check_directory_exists(path)
        else:
            path = AppLocation.get_directory(AppLocation.DataDir)
            check_directory_exists(path)
        return os.path.normpath(path)

Azaziah (suutari-olli)
Changed in openlp:
assignee: Azaziah (suutari-olli) → nobody
assignee: nobody → Tomas Groth (tomasgroth)
status: In Progress → Fix Committed
milestone: none → 2.5.1
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Bug attachments

Remote bug watches

Bug watches keep track of this bug in other bug trackers.