Skip to content

Database parental directories creation if not exist - #4327

Merged
sampsyo merged 12 commits into
beetbox:masterfrom
alicezou:databaseCreate
Apr 7, 2022
Merged

Database parental directories creation if not exist#4327
sampsyo merged 12 commits into
beetbox:masterfrom
alicezou:databaseCreate

Conversation

@alicezou

@alicezou alicezou commented Mar 27, 2022

Copy link
Copy Markdown
Contributor

Description

Add prompt for users to select whether to create parental directories when they do not exist.

To Do

  • Documentation. (If you've add a new command-line flag, for example, find the appropriate page under docs/ to describe it.)
  • Changelog. (Add an entry to docs/changelog.rst near the top of the document.)
  • Tests. (Encouraged but not strictly required.) [still working on it]

@alicezou
alicezou marked this pull request as ready for review March 27, 2022 21:11

@wisp3rwind wisp3rwind left a comment

Copy link
Copy Markdown
Member

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.

Comment thread beets/dbcore/db.py Outdated
Comment on lines +904 to +913
# 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)

@wisp3rwind wisp3rwind Mar 29, 2022

Copy link
Copy Markdown
Member

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?

Comment thread 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)?"

Copy link
Copy Markdown
Member

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, ...?

Comment thread test/test_dbcore.py Outdated
Comment on lines +769 to +772
try:
dbcore.Database(non_exist_path)
except OSError as e:
raise e

Copy link
Copy Markdown
Member

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?

Comment thread 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())

Copy link
Copy Markdown
Member

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.

Comment thread test/test_dbcore.py Outdated
raise e
shutil.rmtree("ParentalDirCreationTest")

@mock.patch('builtins.input', side_effect=['n', ])

Copy link
Copy Markdown
Member

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).

@alicezou

Copy link
Copy Markdown
Contributor Author

Hi Benedikt,
Thank you for your review! I have updated my commits.

@sampsyo sampsyo left a comment

Copy link
Copy Markdown
Member

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).

Comment thread 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)?"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
exists, create it (Y/n)?"
exists. Create it (Y/n)?"

So it's two full sentences.

Comment thread docs/changelog.rst Outdated
Comment on lines 10 to 11
* Create the parental directories for database if they do not exist.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* 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.

Comment thread docs/guides/main.rst Outdated
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

Copy link
Copy Markdown
Member

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.

@alicezou

Copy link
Copy Markdown
Contributor Author

Hi Adrian,
Thank you for the feedback! I have updated the related files.

@alicezou

alicezou commented Apr 6, 2022

Copy link
Copy Markdown
Contributor Author

Hi,
It's been a week since my last update. Are there any changes that I can make to improve this pull request? I am looking forward to hearing from you. :)
@wisp3rwind @sampsyo

@sampsyo sampsyo left a comment

Copy link
Copy Markdown
Member

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.

Comment thread beets/ui/commands.py Outdated
Comment on lines +1401 to +1403
# database_location: return true if user
# wants to create the parent directories.

Copy link
Copy Markdown
Member

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).

Comment thread beets/ui/__init__.py Outdated
Comment on lines +1212 to +1216
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)))

Copy link
Copy Markdown
Member

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.)

Comment thread beets/ui/__init__.py Outdated
.format(util.displayable_path(path)))


def _check_db_directory_exists(path):

Copy link
Copy Markdown
Member

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?

Comment thread 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)?"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

exists -> exist

@alicezou

alicezou commented Apr 7, 2022

Copy link
Copy Markdown
Contributor Author

Hi Adrian,
Thank you for your comments! I have updated the relevant parts.

@sampsyo sampsyo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks perfect. Thanks again!!

@sampsyo
sampsyo merged commit e977a6f into beetbox:master Apr 7, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants