Skip to content

Commit

Permalink
Merge branch 'master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
bartkl authored Jun 13, 2017
2 parents 762f9ca + f65653a commit 2eb4e3d
Show file tree
Hide file tree
Showing 20 changed files with 402 additions and 57 deletions.
2 changes: 1 addition & 1 deletion beets/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

from beets.util import confit

__version__ = u'1.4.4'
__version__ = u'1.4.5'
__author__ = u'Adrian Sampson <adrian@radbox.org>'


Expand Down
16 changes: 15 additions & 1 deletion beets/autotag/mb.py
Original file line number Diff line number Diff line change
Expand Up @@ -333,12 +333,26 @@ def album_info(release):
disambig.append(release.get('disambiguation'))
info.albumdisambig = u', '.join(disambig)

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

# Log the new-style "primary" and "secondary" release types.
# Eventually, we'd like to actually store this data, but we just log
# it for now to help understand the differences.
if 'primary-type' in release['release-group']:
rel_primarytype = release['release-group']['primary-type']
if rel_primarytype:
log.debug('primary MB release type: ' + rel_primarytype.lower())
if 'secondary-type-list' in release['release-group']:
if release['release-group']['secondary-type-list']:
log.debug('secondary MB release type(s): ' + ', '.join(
[secondarytype.lower() for secondarytype in
release['release-group']['secondary-type-list']]))

# Release events.
info.country, release_date = _preferred_release_event(release)
release_group_date = release['release-group'].get('first-release-date')
Expand Down
41 changes: 30 additions & 11 deletions beets/dbcore/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -533,12 +533,20 @@ class Period(object):
instants of time during January 2014.
"""

precisions = ('year', 'month', 'day')
date_formats = ('%Y', '%Y-%m', '%Y-%m-%d')
precisions = ('year', 'month', 'day', 'hour', 'minute', 'second')
date_formats = (
('%Y',), # year
('%Y-%m',), # month
('%Y-%m-%d',), # day
('%Y-%m-%dT%H', '%Y-%m-%d %H'), # hour
('%Y-%m-%dT%H:%M', '%Y-%m-%d %H:%M'), # minute
('%Y-%m-%dT%H:%M:%S', '%Y-%m-%d %H:%M:%S') # second
)

def __init__(self, date, precision):
"""Create a period with the given date (a `datetime` object) and
precision (a string, one of "year", "month", or "day").
precision (a string, one of "year", "month", "day", "hour", "minute",
or "second").
"""
if precision not in Period.precisions:
raise ValueError(u'Invalid precision {0}'.format(precision))
Expand All @@ -551,16 +559,21 @@ def parse(cls, string):
string is empty, or raise an InvalidQueryArgumentValueError if
the string could not be parsed to a date.
"""

def find_date_and_format(string):
for ord, format in enumerate(cls.date_formats):
for format_option in format:
try:
date = datetime.strptime(string, format_option)
return date, ord
except ValueError:
# Parsing failed.
pass
return (None, None)

if not string:
return None
date = None
for ordinal, date_format in enumerate(cls.date_formats):
try:
date = datetime.strptime(string, date_format)
break
except ValueError:
# Parsing failed.
pass
date, ordinal = find_date_and_format(string)
if date is None:
raise InvalidQueryArgumentValueError(string,
'a valid datetime string')
Expand All @@ -582,6 +595,12 @@ def open_right_endpoint(self):
return date.replace(year=date.year + 1, month=1)
elif 'day' == precision:
return date + timedelta(days=1)
elif 'hour' == precision:
return date + timedelta(hours=1)
elif 'minute' == precision:
return date + timedelta(minutes=1)
elif 'second' == precision:
return date + timedelta(seconds=1)
else:
raise ValueError(u'unhandled precision {0}'.format(precision))

Expand Down
4 changes: 4 additions & 0 deletions beets/library.py
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,8 @@ class Item(LibModel):
'rg_track_peak': types.NULL_FLOAT,
'rg_album_gain': types.NULL_FLOAT,
'rg_album_peak': types.NULL_FLOAT,
'r128_track_gain': types.PaddedInt(6),
'r128_album_gain': types.PaddedInt(6),
'original_year': types.PaddedInt(4),
'original_month': types.PaddedInt(2),
'original_day': types.PaddedInt(2),
Expand Down Expand Up @@ -898,6 +900,7 @@ class Album(LibModel):
'albumdisambig': types.STRING,
'rg_album_gain': types.NULL_FLOAT,
'rg_album_peak': types.NULL_FLOAT,
'r128_album_gain': types.PaddedInt(6),
'original_year': types.PaddedInt(4),
'original_month': types.PaddedInt(2),
'original_day': types.PaddedInt(2),
Expand Down Expand Up @@ -941,6 +944,7 @@ class Album(LibModel):
'albumdisambig',
'rg_album_gain',
'rg_album_peak',
'r128_album_gain',
'original_year',
'original_month',
'original_day',
Expand Down
38 changes: 36 additions & 2 deletions beets/mediafile.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,10 +154,12 @@ def _safe_cast(out_type, val):
return int(val)
else:
# Process any other type as a string.
if not isinstance(val, six.string_types):
if isinstance(val, bytes):
val = val.decode('utf-8', 'ignore')
elif not isinstance(val, six.string_types):
val = six.text_type(val)
# Get a number from the front of the string.
val = re.match(r'[0-9]*', val.strip()).group(0)
val = re.match(r'[\+-]?[0-9]*', val.strip()).group(0)
if not val:
return 0
else:
Expand Down Expand Up @@ -2005,6 +2007,38 @@ def update(self, dict):
out_type=float,
)

# EBU R128 fields.
r128_track_gain = MediaField(
MP3DescStorageStyle(
u'R128_TRACK_GAIN'
),
MP4StorageStyle(
'----:com.apple.iTunes:R128_TRACK_GAIN'
),
StorageStyle(
u'R128_TRACK_GAIN'
),
ASFStorageStyle(
u'R128_TRACK_GAIN'
),
out_type=int,
)
r128_album_gain = MediaField(
MP3DescStorageStyle(
u'R128_ALBUM_GAIN'
),
MP4StorageStyle(
'----:com.apple.iTunes:R128_ALBUM_GAIN'
),
StorageStyle(
u'R128_ALBUM_GAIN'
),
ASFStorageStyle(
u'R128_ALBUM_GAIN'
),
out_type=int,
)

initial_key = MediaField(
MP3StorageStyle('TKEY'),
MP4StorageStyle('----:com.apple.iTunes:initialkey'),
Expand Down
18 changes: 14 additions & 4 deletions beets/ui/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -1457,7 +1457,8 @@ def modify_func(lib, opts, args):

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

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

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

obj.move(copy, basedir=dest)
obj.store()
if export:
# Copy without affecting the database.
obj.move(True, basedir=dest, store=False)
else:
# Ordinary move/copy: store the new path.
obj.move(copy, basedir=dest)


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

move_items(lib, dest, decargs(args), opts.copy, opts.album, opts.pretend,
opts.timid)
opts.timid, opts.export)


move_cmd = ui.Subcommand(
Expand All @@ -1529,6 +1535,10 @@ def move_func(lib, opts, args):
u'-t', u'--timid', dest='timid', action='store_true',
help=u'always confirm all actions'
)
move_cmd.parser.add_option(
u'-e', u'--export', default=False, action='store_true',
help=u'copy without changing the database path'
)
move_cmd.parser.add_album_option()
move_cmd.func = move_func
default_commands.append(move_cmd)
Expand Down
1 change: 1 addition & 0 deletions beetsplug/lastgenre/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ def _sort_by_depth(self, tags):
genre tree.
"""
depth_tag_pairs = [(self._get_depth(t), t) for t in tags]
depth_tag_pairs = [e for e in depth_tag_pairs if e[0] is not None]
depth_tag_pairs.sort(reverse=True)
return [p[1] for p in depth_tag_pairs]

Expand Down
2 changes: 1 addition & 1 deletion beetsplug/mbcollection.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ def imported(self, session, task):
self.update_album_list([task.album])

def update_album_list(self, album_list):
"""Update the MusicBrainz colleciton from a list of Beets albums
"""Update the MusicBrainz collection from a list of Beets albums
"""
# Get the available collections.
collections = mb_call(musicbrainzngs.get_collections)
Expand Down
Loading

0 comments on commit 2eb4e3d

Please sign in to comment.