Skip to content

Commit 2eb4e3d

Browse files
authored
Merge branch 'master' into master
2 parents 762f9ca + f65653a commit 2eb4e3d

File tree

20 files changed

+402
-57
lines changed

20 files changed

+402
-57
lines changed

beets/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
from beets.util import confit
2121

22-
__version__ = u'1.4.4'
22+
__version__ = u'1.4.5'
2323
__author__ = u'Adrian Sampson <[email protected]>'
2424

2525

beets/autotag/mb.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,12 +333,26 @@ def album_info(release):
333333
disambig.append(release.get('disambiguation'))
334334
info.albumdisambig = u', '.join(disambig)
335335

336-
# Release type not always populated.
336+
# Get the "classic" Release type. This data comes from a legacy API
337+
# feature before MusicBrainz supported multiple release types.
337338
if 'type' in release['release-group']:
338339
reltype = release['release-group']['type']
339340
if reltype:
340341
info.albumtype = reltype.lower()
341342

343+
# Log the new-style "primary" and "secondary" release types.
344+
# Eventually, we'd like to actually store this data, but we just log
345+
# it for now to help understand the differences.
346+
if 'primary-type' in release['release-group']:
347+
rel_primarytype = release['release-group']['primary-type']
348+
if rel_primarytype:
349+
log.debug('primary MB release type: ' + rel_primarytype.lower())
350+
if 'secondary-type-list' in release['release-group']:
351+
if release['release-group']['secondary-type-list']:
352+
log.debug('secondary MB release type(s): ' + ', '.join(
353+
[secondarytype.lower() for secondarytype in
354+
release['release-group']['secondary-type-list']]))
355+
342356
# Release events.
343357
info.country, release_date = _preferred_release_event(release)
344358
release_group_date = release['release-group'].get('first-release-date')

beets/dbcore/query.py

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -533,12 +533,20 @@ class Period(object):
533533
instants of time during January 2014.
534534
"""
535535

536-
precisions = ('year', 'month', 'day')
537-
date_formats = ('%Y', '%Y-%m', '%Y-%m-%d')
536+
precisions = ('year', 'month', 'day', 'hour', 'minute', 'second')
537+
date_formats = (
538+
('%Y',), # year
539+
('%Y-%m',), # month
540+
('%Y-%m-%d',), # day
541+
('%Y-%m-%dT%H', '%Y-%m-%d %H'), # hour
542+
('%Y-%m-%dT%H:%M', '%Y-%m-%d %H:%M'), # minute
543+
('%Y-%m-%dT%H:%M:%S', '%Y-%m-%d %H:%M:%S') # second
544+
)
538545

539546
def __init__(self, date, precision):
540547
"""Create a period with the given date (a `datetime` object) and
541-
precision (a string, one of "year", "month", or "day").
548+
precision (a string, one of "year", "month", "day", "hour", "minute",
549+
or "second").
542550
"""
543551
if precision not in Period.precisions:
544552
raise ValueError(u'Invalid precision {0}'.format(precision))
@@ -551,16 +559,21 @@ def parse(cls, string):
551559
string is empty, or raise an InvalidQueryArgumentValueError if
552560
the string could not be parsed to a date.
553561
"""
562+
563+
def find_date_and_format(string):
564+
for ord, format in enumerate(cls.date_formats):
565+
for format_option in format:
566+
try:
567+
date = datetime.strptime(string, format_option)
568+
return date, ord
569+
except ValueError:
570+
# Parsing failed.
571+
pass
572+
return (None, None)
573+
554574
if not string:
555575
return None
556-
date = None
557-
for ordinal, date_format in enumerate(cls.date_formats):
558-
try:
559-
date = datetime.strptime(string, date_format)
560-
break
561-
except ValueError:
562-
# Parsing failed.
563-
pass
576+
date, ordinal = find_date_and_format(string)
564577
if date is None:
565578
raise InvalidQueryArgumentValueError(string,
566579
'a valid datetime string')
@@ -582,6 +595,12 @@ def open_right_endpoint(self):
582595
return date.replace(year=date.year + 1, month=1)
583596
elif 'day' == precision:
584597
return date + timedelta(days=1)
598+
elif 'hour' == precision:
599+
return date + timedelta(hours=1)
600+
elif 'minute' == precision:
601+
return date + timedelta(minutes=1)
602+
elif 'second' == precision:
603+
return date + timedelta(seconds=1)
585604
else:
586605
raise ValueError(u'unhandled precision {0}'.format(precision))
587606

beets/library.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,8 @@ class Item(LibModel):
454454
'rg_track_peak': types.NULL_FLOAT,
455455
'rg_album_gain': types.NULL_FLOAT,
456456
'rg_album_peak': types.NULL_FLOAT,
457+
'r128_track_gain': types.PaddedInt(6),
458+
'r128_album_gain': types.PaddedInt(6),
457459
'original_year': types.PaddedInt(4),
458460
'original_month': types.PaddedInt(2),
459461
'original_day': types.PaddedInt(2),
@@ -898,6 +900,7 @@ class Album(LibModel):
898900
'albumdisambig': types.STRING,
899901
'rg_album_gain': types.NULL_FLOAT,
900902
'rg_album_peak': types.NULL_FLOAT,
903+
'r128_album_gain': types.PaddedInt(6),
901904
'original_year': types.PaddedInt(4),
902905
'original_month': types.PaddedInt(2),
903906
'original_day': types.PaddedInt(2),
@@ -941,6 +944,7 @@ class Album(LibModel):
941944
'albumdisambig',
942945
'rg_album_gain',
943946
'rg_album_peak',
947+
'r128_album_gain',
944948
'original_year',
945949
'original_month',
946950
'original_day',

beets/mediafile.py

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,10 +154,12 @@ def _safe_cast(out_type, val):
154154
return int(val)
155155
else:
156156
# Process any other type as a string.
157-
if not isinstance(val, six.string_types):
157+
if isinstance(val, bytes):
158+
val = val.decode('utf-8', 'ignore')
159+
elif not isinstance(val, six.string_types):
158160
val = six.text_type(val)
159161
# Get a number from the front of the string.
160-
val = re.match(r'[0-9]*', val.strip()).group(0)
162+
val = re.match(r'[\+-]?[0-9]*', val.strip()).group(0)
161163
if not val:
162164
return 0
163165
else:
@@ -2005,6 +2007,38 @@ def update(self, dict):
20052007
out_type=float,
20062008
)
20072009

2010+
# EBU R128 fields.
2011+
r128_track_gain = MediaField(
2012+
MP3DescStorageStyle(
2013+
u'R128_TRACK_GAIN'
2014+
),
2015+
MP4StorageStyle(
2016+
'----:com.apple.iTunes:R128_TRACK_GAIN'
2017+
),
2018+
StorageStyle(
2019+
u'R128_TRACK_GAIN'
2020+
),
2021+
ASFStorageStyle(
2022+
u'R128_TRACK_GAIN'
2023+
),
2024+
out_type=int,
2025+
)
2026+
r128_album_gain = MediaField(
2027+
MP3DescStorageStyle(
2028+
u'R128_ALBUM_GAIN'
2029+
),
2030+
MP4StorageStyle(
2031+
'----:com.apple.iTunes:R128_ALBUM_GAIN'
2032+
),
2033+
StorageStyle(
2034+
u'R128_ALBUM_GAIN'
2035+
),
2036+
ASFStorageStyle(
2037+
u'R128_ALBUM_GAIN'
2038+
),
2039+
out_type=int,
2040+
)
2041+
20082042
initial_key = MediaField(
20092043
MP3StorageStyle('TKEY'),
20102044
MP4StorageStyle('----:com.apple.iTunes:initialkey'),

beets/ui/commands.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1457,7 +1457,8 @@ def modify_func(lib, opts, args):
14571457

14581458
# move: Move/copy files to the library or a new base directory.
14591459

1460-
def move_items(lib, dest, query, copy, album, pretend, confirm=False):
1460+
def move_items(lib, dest, query, copy, album, pretend, confirm=False,
1461+
export=False):
14611462
"""Moves or copies items to a new base directory, given by dest. If
14621463
dest is None, then the library's base directory is used, making the
14631464
command "consolidate" files.
@@ -1470,6 +1471,7 @@ def move_items(lib, dest, query, copy, album, pretend, confirm=False):
14701471
isalbummoved = lambda album: any(isitemmoved(i) for i in album.items())
14711472
objs = [o for o in objs if (isalbummoved if album else isitemmoved)(o)]
14721473

1474+
copy = copy or export # Exporting always copies.
14731475
action = u'Copying' if copy else u'Moving'
14741476
act = u'copy' if copy else u'move'
14751477
entity = u'album' if album else u'item'
@@ -1495,8 +1497,12 @@ def move_items(lib, dest, query, copy, album, pretend, confirm=False):
14951497
for obj in objs:
14961498
log.debug(u'moving: {0}', util.displayable_path(obj.path))
14971499

1498-
obj.move(copy, basedir=dest)
1499-
obj.store()
1500+
if export:
1501+
# Copy without affecting the database.
1502+
obj.move(True, basedir=dest, store=False)
1503+
else:
1504+
# Ordinary move/copy: store the new path.
1505+
obj.move(copy, basedir=dest)
15001506

15011507

15021508
def move_func(lib, opts, args):
@@ -1507,7 +1513,7 @@ def move_func(lib, opts, args):
15071513
raise ui.UserError(u'no such directory: %s' % dest)
15081514

15091515
move_items(lib, dest, decargs(args), opts.copy, opts.album, opts.pretend,
1510-
opts.timid)
1516+
opts.timid, opts.export)
15111517

15121518

15131519
move_cmd = ui.Subcommand(
@@ -1529,6 +1535,10 @@ def move_func(lib, opts, args):
15291535
u'-t', u'--timid', dest='timid', action='store_true',
15301536
help=u'always confirm all actions'
15311537
)
1538+
move_cmd.parser.add_option(
1539+
u'-e', u'--export', default=False, action='store_true',
1540+
help=u'copy without changing the database path'
1541+
)
15321542
move_cmd.parser.add_album_option()
15331543
move_cmd.func = move_func
15341544
default_commands.append(move_cmd)

beetsplug/lastgenre/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ def _sort_by_depth(self, tags):
174174
genre tree.
175175
"""
176176
depth_tag_pairs = [(self._get_depth(t), t) for t in tags]
177+
depth_tag_pairs = [e for e in depth_tag_pairs if e[0] is not None]
177178
depth_tag_pairs.sort(reverse=True)
178179
return [p[1] for p in depth_tag_pairs]
179180

beetsplug/mbcollection.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ def imported(self, session, task):
8080
self.update_album_list([task.album])
8181

8282
def update_album_list(self, album_list):
83-
"""Update the MusicBrainz colleciton from a list of Beets albums
83+
"""Update the MusicBrainz collection from a list of Beets albums
8484
"""
8585
# Get the available collections.
8686
collections = mb_call(musicbrainzngs.get_collections)

0 commit comments

Comments
 (0)