-
Notifications
You must be signed in to change notification settings - Fork 1.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Database parental directories creation if not exist #4327
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi, thanks for getting this started! I've left a few inline comments on how I think the design of this PR might be improved.
beets/dbcore/db.py
Outdated
# Check whether parental directories exist. | ||
def _path_checker(self, path): | ||
if not isinstance(path, bytes) and path == ':memory:': # in memory db | ||
return | ||
newpath = os.path.dirname(path) | ||
if not os.path.isdir(newpath): | ||
from beets.ui.commands import database_dir_creation | ||
if database_dir_creation(newpath): | ||
os.makedirs(newpath) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is somewhat unfortunate that this couples the beets.dbcore
and beets.ui
modules, whereas the former used to be standalone (except for importing beets.util
). Would it be possible instead to catch the exception on missing directory in beets/ui/__init__.py:_open_library()
, ask for creating the directory, and trying to open the database again afterwards?
Apart from that, a more descriptive name instead _path_checker
what be nice, maybe along the lines of check_db_directory_exists
?
beets/ui/commands.py
Outdated
|
||
def database_dir_creation(path): | ||
# Ask the user for a choice. | ||
return ui.input_yn("{} does not exist, create it (Y/n)?" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be helpful to more explicity describe the issue here; the path alone might not be enough to understand the problem: The database directory {} does not exists, ...
?
test/test_dbcore.py
Outdated
try: | ||
dbcore.Database(non_exist_path) | ||
except OSError as e: | ||
raise e |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That would behave identically with the try ... catch
removed, right?
test/test_dbcore.py
Outdated
class ParentalDirCreation(unittest.TestCase): | ||
@mock.patch('builtins.input', side_effect=['y', ]) | ||
def test_create_yes(self, _): | ||
non_exist_path = "ParentalDirCreationTest/nonexist/" + str(random()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should be using a path within a temporary directory, to be certain that we don't pollute the environment where the test is run.
test/test_dbcore.py
Outdated
raise e | ||
shutil.rmtree("ParentalDirCreationTest") | ||
|
||
@mock.patch('builtins.input', side_effect=['n', ]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be easier to use the control_stdin
context manager from test/helper.py
(see its docstring for details).
Hi Benedikt, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking great!! Here are a few granular suggestions.
I actually think it would be fine (and a bit simpler) to keep the prompt code directly in the beets.ui
module (i.e., ui/__init__.py
) rather than having a short function in the beets.ui.commands
module. The latter module is centered around providing implementations for the beet <foo>
subcommands, and this functionality is actually a global thing that is not associated with any particular subcommand—so it would be a bit simpler to just keep everything in the new _check_db_directory_exists
function.
I also just wanted to state for the record that this issue will probably only affect people who have changed the library
configuration option… beets automatically creates ~/.config/beets
by default and puts library.db
in there. But custom database locations would not enjoy this automation (until now).
beets/ui/commands.py
Outdated
def database_dir_creation(path): | ||
# Ask the user for a choice. | ||
return ui.input_yn("The database directory {} does not \ | ||
exists, create it (Y/n)?" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
exists, create it (Y/n)?" | |
exists. Create it (Y/n)?" |
So it's two full sentences.
docs/changelog.rst
Outdated
* Create the parental directories for database if they do not exist. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* Create the parental directories for database if they do not exist. | |
* Create the parental directories for database if they do not exist. | |
:bug:`3808` :bug:`4327` |
Including references to where this was discussed.
docs/guides/main.rst
Outdated
@@ -142,7 +142,8 @@ place to start:: | |||
|
|||
Change that first path to a directory where you'd like to keep your music. Then, | |||
for ``library``, choose a good place to keep a database file that keeps an index | |||
of your music. (The config's format is `YAML`_. You'll want to configure your | |||
of your music. Beets will prompt you if the parental directories for database do | |||
not exist. (The config's format is `YAML`_. You'll want to configure your |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TBH I think it's probably OK to leave this sentence off? This is an edge case, and the prompt clearly explains to users what's going on, so I don't think we need to warn people that this might happen.
Hi Adrian, |
Hi, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good!! I have just a few very small comments, but then I think this should be good to go.
beets/ui/commands.py
Outdated
# database_location: return true if user | ||
# wants to create the parent directories. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment looks like it's out of date (it can just be deleted).
beets/ui/__init__.py
Outdated
def database_dir_creation(path): | ||
# Ask the user for a choice. | ||
return input_yn("The database directory {} does not \ | ||
exists. Create it (Y/n)?" | ||
.format(util.displayable_path(path))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest just "inlining" this code, since it's pretty simple and not called anywhere else. (That is, just do this prompting right inside the function below instead of having a separate function.)
beets/ui/__init__.py
Outdated
.format(util.displayable_path(path))) | ||
|
||
|
||
def _check_db_directory_exists(path): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe should be called _ensure_db_directory_exists
since it does more than just check?
beets/ui/__init__.py
Outdated
def database_dir_creation(path): | ||
# Ask the user for a choice. | ||
return input_yn("The database directory {} does not \ | ||
exists. Create it (Y/n)?" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
exists -> exist
Hi Adrian, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks perfect. Thanks again!!
Description
Add prompt for users to select whether to create parental directories when they do not exist.
To Do
docs/
to describe it.)docs/changelog.rst
near the top of the document.)