mirror of
https://github.com/beetbox/beets.git
synced 2026-02-19 05:45:33 +01:00
Merge branch 'master' into extractart-for-albums
This commit is contained in:
commit
e2a7f7c153
7 changed files with 66 additions and 22 deletions
|
|
@ -402,6 +402,14 @@ class Item(LibModel):
|
|||
`write`.
|
||||
"""
|
||||
|
||||
_media_tag_fields = set(MediaFile.fields()).intersection(_fields.keys())
|
||||
"""Set of item fields that are backed by *writable* `MediaFile` tag
|
||||
fields.
|
||||
|
||||
This excludes fields that represent audio data, such as `bitrate` or
|
||||
`length`.
|
||||
"""
|
||||
|
||||
_formatter = FormattedItemMapping
|
||||
|
||||
_sorts = {'artist': SmartArtistSort}
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ def print_(*strings):
|
|||
if isinstance(strings[0], unicode):
|
||||
txt = u' '.join(strings)
|
||||
else:
|
||||
txt = ' '.join(strings)
|
||||
txt = b' '.join(strings)
|
||||
else:
|
||||
txt = u''
|
||||
if isinstance(txt, unicode):
|
||||
|
|
|
|||
|
|
@ -1428,7 +1428,7 @@ def write_items(lib, query, pretend, force):
|
|||
|
||||
# Check for and display changes.
|
||||
changed = ui.show_model_changes(item, clean_item,
|
||||
library.Item._media_fields, force)
|
||||
library.Item._media_tag_fields, force)
|
||||
if (changed or force) and not pretend:
|
||||
item.try_sync()
|
||||
|
||||
|
|
|
|||
|
|
@ -26,21 +26,21 @@ from beets import config
|
|||
from beets import mediafile
|
||||
|
||||
_MUTAGEN_FORMATS = {
|
||||
'asf': 'ASF',
|
||||
'apev2': 'APEv2File',
|
||||
'flac': 'FLAC',
|
||||
'id3': 'ID3FileType',
|
||||
'mp3': 'MP3',
|
||||
'mp4': 'MP4',
|
||||
'oggflac': 'OggFLAC',
|
||||
'oggspeex': 'OggSpeex',
|
||||
'oggtheora': 'OggTheora',
|
||||
'oggvorbis': 'OggVorbis',
|
||||
'oggopus': 'OggOpus',
|
||||
'trueaudio': 'TrueAudio',
|
||||
'wavpack': 'WavPack',
|
||||
'monkeysaudio': 'MonkeysAudio',
|
||||
'optimfrog': 'OptimFROG',
|
||||
b'asf': b'ASF',
|
||||
b'apev2': b'APEv2File',
|
||||
b'flac': b'FLAC',
|
||||
b'id3': b'ID3FileType',
|
||||
b'mp3': b'MP3',
|
||||
b'mp4': b'MP4',
|
||||
b'oggflac': b'OggFLAC',
|
||||
b'oggspeex': b'OggSpeex',
|
||||
b'oggtheora': b'OggTheora',
|
||||
b'oggvorbis': b'OggVorbis',
|
||||
b'oggopus': b'OggOpus',
|
||||
b'trueaudio': b'TrueAudio',
|
||||
b'wavpack': b'WavPack',
|
||||
b'monkeysaudio': b'MonkeysAudio',
|
||||
b'optimfrog': b'OptimFROG',
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -103,7 +103,7 @@ class ScrubPlugin(BeetsPlugin):
|
|||
"""
|
||||
classes = []
|
||||
for modname, clsname in _MUTAGEN_FORMATS.items():
|
||||
mod = __import__('mutagen.{0}'.format(modname),
|
||||
mod = __import__(b'mutagen.{0}'.format(modname),
|
||||
fromlist=[clsname])
|
||||
classes.append(getattr(mod, clsname))
|
||||
return classes
|
||||
|
|
|
|||
|
|
@ -78,6 +78,8 @@ Fixes:
|
|||
* :doc:`/plugins/importfeeds` and :doc:`/plugins/smartplaylist`: Automatically
|
||||
create parent directories for playlist files (instead of crashing when the
|
||||
parent directory does not exist). :bug:`1266`
|
||||
* The :ref:`write-cmd` command no longer tries to "write" non-writable fields
|
||||
like the bitrate. :bug:`1268`
|
||||
|
||||
For developers:
|
||||
|
||||
|
|
|
|||
|
|
@ -318,6 +318,37 @@ class WriteTest(unittest.TestCase, TestHelper):
|
|||
item = self.lib.items().get()
|
||||
self.assertEqual(item.mtime, item.current_mtime())
|
||||
|
||||
def test_non_metadata_field_unchanged(self):
|
||||
"""Changing a non-"tag" field like `bitrate` and writing should
|
||||
have no effect.
|
||||
"""
|
||||
# An item that starts out "clean".
|
||||
item = self.add_item_fixture()
|
||||
item.read()
|
||||
|
||||
# ... but with a mismatched bitrate.
|
||||
item.bitrate = 123
|
||||
item.store()
|
||||
|
||||
with capture_stdout() as stdout:
|
||||
self.write_cmd()
|
||||
|
||||
self.assertEqual(stdout.getvalue(), '')
|
||||
|
||||
def test_write_metadata_field(self):
|
||||
item = self.add_item_fixture()
|
||||
item.read()
|
||||
old_title = item.title
|
||||
|
||||
item.title = 'new title'
|
||||
item.store()
|
||||
|
||||
with capture_stdout() as stdout:
|
||||
self.write_cmd()
|
||||
|
||||
self.assertTrue('{0} -> new title'.format(old_title)
|
||||
in stdout.getvalue())
|
||||
|
||||
|
||||
class MoveTest(_common.TestCase):
|
||||
def setUp(self):
|
||||
|
|
|
|||
11
tox.ini
11
tox.ini
|
|
@ -17,14 +17,12 @@ deps =
|
|||
rarfile
|
||||
responses
|
||||
commands =
|
||||
nosetests -v {posargs}
|
||||
nosetests {posargs}
|
||||
|
||||
[testenv:py26]
|
||||
deps =
|
||||
{[testenv]deps}
|
||||
unittest2
|
||||
commands =
|
||||
python ./setup.py test {posargs}
|
||||
|
||||
[testenv:py27cov]
|
||||
basepython = python2.7
|
||||
|
|
@ -32,7 +30,12 @@ deps =
|
|||
{[testenv]deps}
|
||||
coverage
|
||||
commands =
|
||||
nosetests -v --with-coverage {posargs}
|
||||
nosetests --with-coverage {posargs}
|
||||
|
||||
[testenv:py27setup]
|
||||
basepython = python2.7
|
||||
commands =
|
||||
python ./setup.py test {posargs}
|
||||
|
||||
[testenv:docs]
|
||||
changedir = docs
|
||||
|
|
|
|||
Loading…
Reference in a new issue