Skip to content

Commit

Permalink
Merge branch 'master' into spectral_music
Browse files Browse the repository at this point in the history
* master: (94 commits)
  Clean up changelog for edit plugin
  scrub: Demote a log message to debug
  scrub: Restore tags & art in auto mode (beetbox#1657)
  scrub: Run on import in auto mode (beetbox#1657)
  Fix beetbox#1673: Escape regex terms in lyrics
  snake_case variable names
  Doc refinements for beetbox#1749
  Remove tests for Google fetchart backend (beetbox#1760)
  fetchart: Remove Google backend (fix beetbox#1760)
  fetchart: Better logging for iTunes (beetbox#1760)
  fetchart: Fix beetbox#1610: itunes install docs
  Fix test that depended on local time, 2
  Fix test that depended on local time
  Fix unused import leftover on test_library
  Add documentation for M:SS length
  Move raw_seconds_short to beets.util
  Add tests for library-specific field types
  Fix test that was expecting raw length format
  Fix pyflakes issues, variable name
  Add config option for human vs raw track duration
  ...
  • Loading branch information
shamangeorge committed Dec 16, 2015
2 parents a60110a + 393d404 commit cb1d817
Show file tree
Hide file tree
Showing 20 changed files with 853 additions and 132 deletions.
1 change: 1 addition & 0 deletions beets/config_default.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ ui:
format_item: $artist - $album - $title
format_album: $albumartist - $album
time_format: '%Y-%m-%d %H:%M:%S'
format_raw_length: no

sort_album: albumartist+ album+
sort_item: artist+ album+ disc+ track+
Expand Down
5 changes: 5 additions & 0 deletions beets/dbcore/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,11 @@ def _parse(cls, key, string):

return cls._type(key).parse(string)

def set_parse(self, key, string):
"""Set the object's key to a value represented by a string.
"""
self[key] = self._parse(key, string)


# Database controller and supporting interfaces.

Expand Down
27 changes: 27 additions & 0 deletions beets/dbcore/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -653,6 +653,33 @@ def col_clause(self):
return clause, subvals


class DurationQuery(NumericQuery):
"""NumericQuery that allow human-friendly (M:SS) time interval formats.
Converts the range(s) to a float value, and delegates on NumericQuery.
Raises InvalidQueryError when the pattern does not represent an int, float
or M:SS time interval.
"""
def _convert(self, s):
"""Convert a M:SS or numeric string to a float.
Return None if `s` is empty.
Raise an InvalidQueryError if the string cannot be converted.
"""
if not s:
return None
try:
return util.raw_seconds_short(s)
except ValueError:
try:
return float(s)
except ValueError:
raise InvalidQueryArgumentTypeError(
s,
"a M:SS string or a float")


# Sorting.

class Sort(object):
Expand Down
24 changes: 23 additions & 1 deletion beets/library.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,28 @@ def normalize(self, key):
return self.parse(key)


class DurationType(types.Float):
"""Human-friendly (M:SS) representation of a time interval."""
query = dbcore.query.DurationQuery

def format(self, value):
if not beets.config['format_raw_length'].get(bool):
return beets.ui.human_seconds_short(value or 0.0)
else:
return value

def parse(self, string):
try:
# Try to format back hh:ss to seconds.
return util.raw_seconds_short(string)
except ValueError:
# Fall back to a plain float.
try:
return float(string)
except ValueError:
return self.null


# Library-specific sort types.

class SmartArtistSort(dbcore.query.Sort):
Expand Down Expand Up @@ -426,7 +448,7 @@ class Item(LibModel):
'original_day': types.PaddedInt(2),
'initial_key': MusicalKey(),

'length': types.FLOAT,
'length': DurationType(),
'bitrate': types.ScaledInt(1000, u'kbps'),
'format': types.STRING,
'samplerate': types.ScaledInt(1000, u'kHz'),
Expand Down
13 changes: 13 additions & 0 deletions beets/util/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -843,3 +843,16 @@ def case_sensitive(path):
lower = _windows_long_path_name(path.lower())
upper = _windows_long_path_name(path.upper())
return lower != upper


def raw_seconds_short(string):
"""Formats a human-readable M:SS string as a float (number of seconds).
Raises ValueError if the conversion cannot take place due to `string` not
being in the right format.
"""
match = re.match('^(\d+):([0-5]\d)$', string)
if not match:
raise ValueError('String not in M:SS format')
minutes, seconds = map(int, match.groups())
return float(minutes * 60 + seconds)
Loading

0 comments on commit cb1d817

Please sign in to comment.