mirror of
https://github.com/beetbox/beets.git
synced 2026-01-09 09:22:55 +01:00
Merge pull request #4899 from fracai/update-field-exclusions
Support excluding fields with update command
This commit is contained in:
commit
cd0f2b1aa3
4 changed files with 47 additions and 14 deletions
|
|
@ -1196,19 +1196,37 @@ default_commands.append(list_cmd)
|
|||
|
||||
# update: Update library contents according to on-disk tags.
|
||||
|
||||
def update_items(lib, query, album, move, pretend, fields):
|
||||
def update_items(lib, query, album, move, pretend, fields,
|
||||
exclude_fields=None):
|
||||
"""For all the items matched by the query, update the library to
|
||||
reflect the item's embedded tags.
|
||||
:param fields: The fields to be stored. If not specified, all fields will
|
||||
be.
|
||||
:param exclude_fields: The fields to not be stored. If not specified, all
|
||||
fields will be.
|
||||
"""
|
||||
with lib.transaction():
|
||||
items, _ = _do_query(lib, query, album)
|
||||
if move and fields is not None and 'path' not in fields:
|
||||
# Special case: if an item needs to be moved, the path field has to
|
||||
# updated; otherwise the new path will not be reflected in the
|
||||
# database.
|
||||
fields.append('path')
|
||||
items, _ = _do_query(lib, query, album)
|
||||
if fields is None:
|
||||
# no fields were provided, update all media fields
|
||||
item_fields = fields or library.Item._media_fields
|
||||
if move and 'path' not in item_fields:
|
||||
# move is enabled, add 'path' to the list of fields to update
|
||||
item_fields.add('path')
|
||||
else:
|
||||
# fields was provided, just update those
|
||||
item_fields = fields
|
||||
# get all the album fields to update
|
||||
album_fields = fields or library.Album._fields.keys()
|
||||
if exclude_fields:
|
||||
# remove any excluded fields from the item and album sets
|
||||
item_fields = [f for f in item_fields if f not in exclude_fields]
|
||||
album_fields = [f for f in album_fields if f not in exclude_fields]
|
||||
|
||||
# Walk through the items and pick up their changes.
|
||||
affected_albums = set()
|
||||
|
|
@ -1248,7 +1266,7 @@ def update_items(lib, query, album, move, pretend, fields):
|
|||
# Check for and display changes.
|
||||
changed = ui.show_model_changes(
|
||||
item,
|
||||
fields=fields or library.Item._media_fields)
|
||||
fields=item_fields)
|
||||
|
||||
# Save changes.
|
||||
if not pretend:
|
||||
|
|
@ -1257,14 +1275,14 @@ def update_items(lib, query, album, move, pretend, fields):
|
|||
if move and lib.directory in ancestry(item.path):
|
||||
item.move(store=False)
|
||||
|
||||
item.store(fields=fields)
|
||||
item.store(fields=item_fields)
|
||||
affected_albums.add(item.album_id)
|
||||
else:
|
||||
# The file's mtime was different, but there were no
|
||||
# changes to the metadata. Store the new mtime,
|
||||
# which is set in the call to read(), so we don't
|
||||
# check this again in the future.
|
||||
item.store(fields=fields)
|
||||
item.store(fields=item_fields)
|
||||
|
||||
# Skip album changes while pretending.
|
||||
if pretend:
|
||||
|
|
@ -1283,7 +1301,7 @@ def update_items(lib, query, album, move, pretend, fields):
|
|||
# Update album structure to reflect an item in it.
|
||||
for key in library.Album.item_keys:
|
||||
album[key] = first_item[key]
|
||||
album.store(fields=fields)
|
||||
album.store(fields=album_fields)
|
||||
|
||||
# Move album art (and any inconsistent items).
|
||||
if move and lib.directory in ancestry(first_item.path):
|
||||
|
|
@ -1293,9 +1311,9 @@ def update_items(lib, query, album, move, pretend, fields):
|
|||
items = list(album.items())
|
||||
for item in items:
|
||||
item.move(store=False, with_album=False)
|
||||
item.store(fields=fields)
|
||||
item.store(fields=item_fields)
|
||||
album.move(store=False)
|
||||
album.store(fields=fields)
|
||||
album.store(fields=album_fields)
|
||||
|
||||
|
||||
def update_func(lib, opts, args):
|
||||
|
|
@ -1306,7 +1324,7 @@ def update_func(lib, opts, args):
|
|||
if not ui.input_yn("Are you sure you want to continue (y/n)?", True):
|
||||
return
|
||||
update_items(lib, decargs(args), opts.album, ui.should_move(opts.move),
|
||||
opts.pretend, opts.fields)
|
||||
opts.pretend, opts.fields, opts.exclude_fields)
|
||||
|
||||
|
||||
update_cmd = ui.Subcommand(
|
||||
|
|
@ -1330,6 +1348,11 @@ update_cmd.parser.add_option(
|
|||
'-F', '--field', default=None, action='append', dest='fields',
|
||||
help='list of fields to update'
|
||||
)
|
||||
update_cmd.parser.add_option(
|
||||
'-e', '--exclude-field', default=None, action='append',
|
||||
dest='exclude_fields',
|
||||
help='list of fields to exclude from updates'
|
||||
)
|
||||
update_cmd.func = update_func
|
||||
default_commands.append(update_cmd)
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ for Python 3.6).
|
|||
|
||||
New features:
|
||||
|
||||
* :ref:`update-cmd`: added ```-e``` flag for excluding fields from being updated.
|
||||
* :doc:`/plugins/deezer`: Import rank and other attributes from Deezer during import and add a function to update the rank of existing items.
|
||||
:bug:`4841`
|
||||
* resolve transl-tracklisting relations for pseudo releases and merge data with the actual release
|
||||
|
|
|
|||
|
|
@ -329,7 +329,7 @@ update
|
|||
``````
|
||||
::
|
||||
|
||||
beet update [-F] FIELD [-aM] QUERY
|
||||
beet update [-F] FIELD [-e] EXCLUDE_FIELD [-aM] QUERY
|
||||
|
||||
Update the library (and, by default, move files) to reflect out-of-band metadata
|
||||
changes and file deletions.
|
||||
|
|
@ -347,8 +347,9 @@ on disk.
|
|||
|
||||
By default, all the changed metadata will be populated back to the database.
|
||||
If you only want certain fields to be written, specify them with the ```-F```
|
||||
flags (which can be used multiple times). For the list of supported fields,
|
||||
please see ```beet fields```.
|
||||
flags (which can be used multiple times). Alternatively, specify fields to *not*
|
||||
write with ```-e``` flags (which can be used multiple times). For the list of
|
||||
supported fields, please see ```beet fields```.
|
||||
|
||||
When an updated track is part of an album, the album-level fields of *all*
|
||||
tracks from the album are also updated. (Specifically, the command copies
|
||||
|
|
|
|||
|
|
@ -579,13 +579,13 @@ class UpdateTest(_common.TestCase):
|
|||
util.remove(artfile)
|
||||
|
||||
def _update(self, query=(), album=False, move=False, reset_mtime=True,
|
||||
fields=None):
|
||||
fields=None, exclude_fields=None):
|
||||
self.io.addinput('y')
|
||||
if reset_mtime:
|
||||
self.i.mtime = 0
|
||||
self.i.store()
|
||||
commands.update_items(self.lib, query, album, move, False,
|
||||
fields=fields)
|
||||
fields=fields, exclude_fields=exclude_fields)
|
||||
|
||||
def test_delete_removes_item(self):
|
||||
self.assertTrue(list(self.lib.items()))
|
||||
|
|
@ -729,6 +729,14 @@ class UpdateTest(_common.TestCase):
|
|||
self.assertEqual(album.albumtype, correct_albumtype)
|
||||
self.assertEqual(album.albumtypes, correct_albumtypes)
|
||||
|
||||
def test_modified_metadata_excluded(self):
|
||||
mf = MediaFile(syspath(self.i.path))
|
||||
mf.lyrics = 'new lyrics'
|
||||
mf.save()
|
||||
self._update(exclude_fields=['lyrics'])
|
||||
item = self.lib.items().get()
|
||||
self.assertNotEqual(item.lyrics, 'new lyrics')
|
||||
|
||||
|
||||
class PrintTest(_common.TestCase):
|
||||
def setUp(self):
|
||||
|
|
|
|||
Loading…
Reference in a new issue