More flake fixes

This commit is contained in:
Thomas Scholtes 2014-04-09 19:13:59 +02:00
parent 4a2f0d11b8
commit bc55747abc
6 changed files with 142 additions and 108 deletions

3
beet
View file

@ -10,7 +10,7 @@
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
@ -18,4 +18,3 @@ import beets.ui
if __name__ == '__main__':
beets.ui.main()

View file

@ -104,8 +104,11 @@ class StringFieldQuery(FieldQuery):
class SubstringQuery(StringFieldQuery):
"""A query that matches a substring in a specific item field."""
def col_clause(self):
search = '%' + (self.pattern.replace('\\','\\\\').replace('%','\\%')
.replace('_','\\_')) + '%'
pattern = (self.pattern
.replace('\\', '\\\\')
.replace('%', '\\%')
.replace('_', '\\_'))
search = '%' + pattern + '%'
clause = self.field + " like ? escape '\\'"
subvals = [search]
return clause, subvals
@ -236,12 +239,16 @@ class CollectionQuery(Query):
self.subqueries = subqueries
# Act like a sequence.
def __len__(self):
return len(self.subqueries)
def __getitem__(self, key):
return self.subqueries[key]
def __iter__(self):
return iter(self.subqueries)
def __contains__(self, item):
return item in self.subqueries
@ -334,10 +341,8 @@ class FalseQuery(Query):
return False
# Time/date queries.
def _to_epoch_time(date):
"""Convert a `datetime` object to an integer number of seconds since
the (local) Unix epoch.

View file

@ -18,10 +18,8 @@ from . import query
from beets.util import str2bool
# Abstract base.
class Type(object):
"""An object encapsulating the type of a model field. Includes
information about how to store, query, format, and parse a given
@ -63,10 +61,8 @@ class Type(object):
return value
# Reusable types.
class Integer(Type):
"""A basic integer type.
"""

View file

@ -53,34 +53,8 @@ import enum
__all__ = ['UnreadableFileError', 'FileTypeError', 'MediaFile']
# Logger.
log = logging.getLogger('beets')
# Exceptions.
class UnreadableFileError(Exception):
"""Indicates a file that MediaFile can't read.
"""
pass
class FileTypeError(UnreadableFileError):
"""Raised for files that don't seem to have a type MediaFile
supports.
"""
pass
class MutagenError(UnreadableFileError):
"""Raised when Mutagen fails unexpectedly---probably due to a bug.
"""
# Constants.
# Human-readable type names.
TYPES = {
'mp3': 'MP3',
@ -96,6 +70,25 @@ TYPES = {
}
# Exceptions.
class UnreadableFileError(Exception):
"""Indicates a file that MediaFile can't read.
"""
pass
class FileTypeError(UnreadableFileError):
"""Raised for files that don't seem to have a type MediaFile
supports.
"""
pass
class MutagenError(UnreadableFileError):
"""Raised when Mutagen fails unexpectedly---probably due to a bug.
"""
# Utility.
@ -161,7 +154,6 @@ def _safe_cast(out_type, val):
return val
# Image coding for ASF/WMA.
def _unpack_asf_image(data):
@ -189,6 +181,7 @@ def _unpack_asf_image(data):
return (mime.decode("utf-16-le"), image_data, type,
description.decode("utf-16-le"))
def _pack_asf_image(mime, data, type=3, description=""):
"""Pack image data for a WM/Picture tag.
"""
@ -199,7 +192,6 @@ def _pack_asf_image(mime, data, type=3, description=""):
return tag_data
# iTunes Sound Check encoding.
def _sc_decode(soundcheck):
@ -237,6 +229,7 @@ def _sc_decode(soundcheck):
return round(gain, 2), round(peak, 6)
def _sc_encode(gain, peak):
"""Encode ReplayGain gain/peak values as a Sound Check string.
"""
@ -261,10 +254,8 @@ def _sc_encode(gain, peak):
return (u' %08X' * 10) % values
# Cover art and other images.
def _image_mime_type(data):
"""Return the MIME type of the image data (a bytestring).
"""
@ -341,7 +332,6 @@ class Image(object):
return self.type.value
# StorageStyle classes describe strategies for accessing values in
# Mutagen file objects.
@ -417,7 +407,7 @@ class StorageStyle(object):
return the represented value.
"""
if self.suffix and isinstance(mutagen_value, unicode) \
and mutagen_value.endswith(self.suffix):
and mutagen_value.endswith(self.suffix):
return mutagen_value[:-len(self.suffix)]
else:
return mutagen_value
@ -588,10 +578,11 @@ class MP4ListStorageStyle(ListStorageStyle, MP4StorageStyle):
class MP4SoundCheckStorageStyle(SoundCheckStorageStyleMixin, MP4StorageStyle):
def __init__(self, index=0, **kwargs):
super(MP4SoundCheckStorageStyle, self).__init__(**kwargs)
def __init__(self, key, index=0, **kwargs):
super(MP4SoundCheckStorageStyle, self).__init__(key, **kwargs)
self.index = index
class MP4BoolStorageStyle(MP4StorageStyle):
"""A style for booleans in MPEG-4 files. (MPEG-4 has an atom type
specifically for representing booleans.)
@ -716,7 +707,10 @@ class MP3DescStorageStyle(MP3StorageStyle):
# need to make a new frame?
if not found:
frame = mutagen.id3.Frames[self.key](
desc=str(self.description), text=value, encoding=3)
desc=str(self.description),
text=value,
encoding=3
)
if self.id3_lang:
frame.lang = self.id3_lang
mutagen_file.tags.add(frame)
@ -832,7 +826,8 @@ class VorbisImageStorageStyle(ListStorageStyle):
def __init__(self):
super(VorbisImageStorageStyle, self).__init__(
key='metadata_block_picture')
key='metadata_block_picture'
)
self.as_type = str
def fetch(self, mutagen_file):
@ -849,7 +844,7 @@ class VorbisImageStorageStyle(ListStorageStyle):
except (TypeError, AttributeError):
continue
images.append(Image(data=pic.data, desc=pic.desc,
type=pic.type))
type=pic.type))
return images
def store(self, mutagen_file, image_data):
@ -904,7 +899,6 @@ class FlacImageStorageStyle(ListStorageStyle):
return pic
# MediaField is a descriptor that represents a single logical field. It
# aggregates several StorageStyles describing how to access the data for
# each file type.
@ -1141,10 +1135,8 @@ class ImageListField(MediaField):
style.set_list(mediafile.mgfile, images)
# MediaFile is a collection of fields.
class MediaFile(object):
"""Represents a multimedia file on disk and provides access to its
metadata.
@ -1186,10 +1178,11 @@ class MediaFile(object):
log.error('uncaught Mutagen exception in open: {0}'.format(exc))
raise MutagenError('Mutagen raised an exception')
if self.mgfile is None: # Mutagen couldn't guess the type
if self.mgfile is None:
# Mutagen couldn't guess the type
raise FileTypeError('file type unsupported by Mutagen')
elif type(self.mgfile).__name__ == 'M4A' or \
type(self.mgfile).__name__ == 'MP4':
elif (type(self.mgfile).__name__ == 'M4A' or
type(self.mgfile).__name__ == 'MP4'):
# This hack differentiates AAC and ALAC until we find a more
# deterministic approach. Mutagen only sets the sample rate
# for AAC files. See:
@ -1199,8 +1192,8 @@ class MediaFile(object):
self.type = 'aac'
else:
self.type = 'alac'
elif type(self.mgfile).__name__ == 'ID3' or \
type(self.mgfile).__name__ == 'MP3':
elif (type(self.mgfile).__name__ == 'ID3' or
type(self.mgfile).__name__ == 'MP3'):
self.type = 'mp3'
elif type(self.mgfile).__name__ == 'FLAC':
self.type = 'flac'
@ -1261,7 +1254,6 @@ class MediaFile(object):
for tag in self.mgfile.keys():
del self.mgfile[tag]
# Convenient access to the set of available fields.
@classmethod
@ -1313,7 +1305,6 @@ class MediaFile(object):
if field in dict:
setattr(self, field, dict[field])
# Field definitions.
title = MediaField(
@ -1487,8 +1478,8 @@ class MediaFile(object):
)
country = MediaField(
MP3DescStorageStyle('MusicBrainz Album Release Country'),
MP4StorageStyle("----:com.apple.iTunes:MusicBrainz Album "
"Release Country"),
MP4StorageStyle("----:com.apple.iTunes:MusicBrainz "
"Album Release Country"),
StorageStyle('RELEASECOUNTRY'),
ASFStorageStyle('MusicBrainz/Album Release Country'),
)
@ -1603,63 +1594,101 @@ class MediaFile(object):
# ReplayGain fields.
rg_track_gain = MediaField(
MP3DescStorageStyle(u'REPLAYGAIN_TRACK_GAIN',
float_places=2, suffix=u' dB'),
MP3DescStorageStyle(u'replaygain_track_gain',
float_places=2, suffix=u' dB'),
MP3SoundCheckStorageStyle(key='COMM', index=0, desc=u'iTunNORM',
id3_lang='eng'),
MP4StorageStyle(key='----:com.apple.iTunes:replaygain_track_gain',
float_places=2, suffix=b' dB'),
MP4SoundCheckStorageStyle(key='----:com.apple.iTunes:iTunNORM',
index=0),
StorageStyle(u'REPLAYGAIN_TRACK_GAIN',
float_places=2, suffix=u' dB'),
ASFStorageStyle(u'replaygain_track_gain',
float_places=2, suffix=u' dB'),
MP3DescStorageStyle(
u'REPLAYGAIN_TRACK_GAIN',
float_places=2, suffix=u' dB'
),
MP3DescStorageStyle(
u'replaygain_track_gain',
float_places=2, suffix=u' dB'
),
MP3SoundCheckStorageStyle(
key='COMM',
index=0, desc=u'iTunNORM',
id3_lang='eng'
),
MP4StorageStyle(
'----:com.apple.iTunes:replaygain_track_gain',
float_places=2, suffix=b' dB'
),
MP4SoundCheckStorageStyle(
'----:com.apple.iTunes:iTunNORM',
index=0
),
StorageStyle(
u'REPLAYGAIN_TRACK_GAIN',
float_places=2, suffix=u' dB'
),
ASFStorageStyle(
u'replaygain_track_gain',
float_places=2, suffix=u' dB'
),
out_type=float
)
rg_album_gain = MediaField(
MP3DescStorageStyle(u'REPLAYGAIN_ALBUM_GAIN',
float_places=2, suffix=u' dB'),
MP3DescStorageStyle(u'replaygain_album_gain',
float_places=2, suffix=u' dB'),
MP4SoundCheckStorageStyle(key='----:com.apple.iTunes:iTunNORM',
index=1),
StorageStyle(u'REPLAYGAIN_ALBUM_GAIN',
float_places=2, suffix=u' dB'),
ASFStorageStyle(u'replaygain_album_gain',
float_places=2, suffix=u' dB'),
MP3DescStorageStyle(
u'REPLAYGAIN_ALBUM_GAIN',
float_places=2, suffix=u' dB'
),
MP3DescStorageStyle(
u'replaygain_album_gain',
float_places=2, suffix=u' dB'
),
MP4SoundCheckStorageStyle(
'----:com.apple.iTunes:iTunNORM',
index=1
),
StorageStyle(
u'REPLAYGAIN_ALBUM_GAIN',
float_places=2, suffix=u' dB'
),
ASFStorageStyle(
u'replaygain_album_gain',
float_places=2, suffix=u' dB'
),
out_type=float
)
rg_track_peak = MediaField(
MP3DescStorageStyle(u'REPLAYGAIN_TRACK_PEAK',
float_places=6),
MP3DescStorageStyle(u'replaygain_track_peak',
float_places=6),
MP3SoundCheckStorageStyle(key='COMM', index=1, desc=u'iTunNORM',
id3_lang='eng'),
MP4StorageStyle('----:com.apple.iTunes:replaygain_track_peak',
float_places=6),
MP4SoundCheckStorageStyle(key='----:com.apple.iTunes:iTunNORM',
index=1),
StorageStyle(u'REPLAYGAIN_TRACK_PEAK',
float_places=6),
ASFStorageStyle(u'replaygain_track_peak',
float_places=6),
MP3DescStorageStyle(
u'REPLAYGAIN_TRACK_PEAK',
float_places=6
),
MP3DescStorageStyle(
u'replaygain_track_peak',
float_places=6
),
MP3SoundCheckStorageStyle(
key=u'COMM',
index=1, desc=u'iTunNORM',
id3_lang='eng'
),
MP4StorageStyle(
'----:com.apple.iTunes:replaygain_track_peak',
float_places=6
),
MP4SoundCheckStorageStyle(
'----:com.apple.iTunes:iTunNORM',
index=1
),
StorageStyle(u'REPLAYGAIN_TRACK_PEAK', float_places=6),
ASFStorageStyle(u'replaygain_track_peak', float_places=6),
out_type=float,
)
rg_album_peak = MediaField(
MP3DescStorageStyle(u'REPLAYGAIN_ALBUM_PEAK',
float_places=6),
MP3DescStorageStyle(u'replaygain_album_peak',
float_places=6),
MP4StorageStyle('----:com.apple.iTunes:replaygain_album_peak',
float_places=6),
StorageStyle(u'REPLAYGAIN_ALBUM_PEAK',
float_places=6),
ASFStorageStyle(u'replaygain_album_peak',
float_places=6),
MP3DescStorageStyle(
u'REPLAYGAIN_ALBUM_PEAK',
float_places=6
),
MP3DescStorageStyle(
u'replaygain_album_peak',
float_places=6
),
MP4StorageStyle(
'----:com.apple.iTunes:replaygain_album_peak',
float_places=6
),
StorageStyle(u'REPLAYGAIN_ALBUM_PEAK', float_places=6),
ASFStorageStyle(u'replaygain_album_peak', float_places=6),
out_type=float,
)

View file

@ -143,7 +143,8 @@ def ancestry(path):
break
last_path = path
if path: # don't yield ''
if path:
# don't yield ''
out.insert(0, path)
return out
@ -477,6 +478,8 @@ CHAR_REPLACE = [
(re.compile(ur'\.$'), u'_'), # Trailing dots.
(re.compile(ur'\s+$'), u''), # Trailing whitespace.
]
def sanitize_path(path, replacements=None):
"""Takes a path (as a Unicode string) and makes sure that it is
legal. Returns a new path. Only works with fragments; won't work

View file

@ -20,6 +20,7 @@ from beets import util
Node = namedtuple('Node', ['files', 'dirs'])
def _insert(node, path, itemid):
"""Insert an item into a virtual filesystem node."""
if len(path) == 1:
@ -33,6 +34,7 @@ def _insert(node, path, itemid):
node.dirs[dirname] = Node({}, {})
_insert(node.dirs[dirname], rest, itemid)
def libtree(lib):
"""Generates a filesystem-like directory tree for the files
contained in `lib`. Filesystem nodes are (files, dirs) named