Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions beets/ui/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1207,10 +1207,22 @@ def _configure(options):
return config


def _ensure_db_directory_exists(path):
if path == b':memory:': # in memory db
return
newpath = os.path.dirname(path)
if not os.path.isdir(newpath):
if input_yn("The database directory {} does not \
exist. Create it (Y/n)?"
.format(util.displayable_path(newpath))):
os.makedirs(newpath)


def _open_library(config):
"""Create a new library instance from the configuration.
"""
dbpath = util.bytestring_path(config['library'].as_filename())
_ensure_db_directory_exists(dbpath)
try:
lib = library.Library(
dbpath,
Expand Down
2 changes: 2 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ Changelog goes here!

New features:

* Create the parental directories for database if they do not exist.
:bug:`3808` :bug:`4327`
* :ref:`musicbrainz-config`: a new :ref:`musicbrainz.enabled` option allows disabling
the MusicBrainz metadata source during the autotagging process
* :doc:`/plugins/kodiupdate`: Now supports multiple kodi instances
Expand Down
1 change: 1 addition & 0 deletions test/test_dbcore.py
Original file line number Diff line number Diff line change
Expand Up @@ -763,5 +763,6 @@ def test_no_results(self):
def suite():
return unittest.TestLoader().loadTestsFromName(__name__)


if __name__ == '__main__':
unittest.main(defaultTest='suite')
40 changes: 38 additions & 2 deletions test/test_ui_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,16 @@
"""Test module for file ui/__init__.py
"""


import os
import shutil
import unittest
from test import _common
from random import random
from copy import deepcopy

from beets import ui
from test import _common
from test.helper import control_stdin
from beets import config


class InputMethodsTest(_common.TestCase):
Expand Down Expand Up @@ -121,8 +126,39 @@ def test_human_seconds(self):
self.assertEqual(h, ui.human_seconds(i))


class ParentalDirCreation(_common.TestCase):
def test_create_yes(self):
non_exist_path = _common.util.py3_path(os.path.join(
self.temp_dir, b'nonexist', str(random()).encode()))
# Deepcopy instead of recovering because exceptions might
# occcur; wish I can use a golang defer here.
test_config = deepcopy(config)
test_config['library'] = non_exist_path
with control_stdin('y'):
ui._open_library(test_config)

def test_create_no(self):
non_exist_path_parent = _common.util.py3_path(
os.path.join(self.temp_dir, b'nonexist'))
non_exist_path = _common.util.py3_path(os.path.join(
non_exist_path_parent.encode(), str(random()).encode()))
test_config = deepcopy(config)
test_config['library'] = non_exist_path

with control_stdin('n'):
try:
ui._open_library(test_config)
except ui.UserError:
if os.path.exists(non_exist_path_parent):
shutil.rmtree(non_exist_path_parent)
raise OSError("Parent directories should not be created.")
else:
raise OSError("Parent directories should not be created.")


def suite():
return unittest.TestLoader().loadTestsFromName(__name__)


if __name__ == '__main__':
unittest.main(defaultTest='suite')