Merge branch 'invalidqueryerror'

This commit is contained in:
Bruno Cauet 2015-02-09 21:29:01 +01:00
commit 54abd1a510
5 changed files with 53 additions and 14 deletions

View file

@ -23,5 +23,6 @@ from .types import Type
from .queryparse import query_from_strings
from .queryparse import sort_from_strings
from .queryparse import parse_sorted_query
from .query import InvalidQueryError
# flake8: noqa

View file

@ -23,12 +23,35 @@ from beets import util
from datetime import datetime, timedelta
class InvalidQueryError(ValueError):
class ParsingError(ValueError):
"""Abstract class for any unparseable user-requested album/query
specification.
"""
class InvalidQueryError(ParsingError):
"""Represent any kind of invalid query.
The query should be a unicode string or a list, which will be space-joined.
"""
def __init__(self, query, explanation):
if isinstance(query, list):
query = " ".join(query)
message = "'{0}': {1}".format(query, explanation)
super(InvalidQueryError, self).__init__(message)
class InvalidQueryArgumentTypeError(ParsingError):
"""Represent a query argument that could not be converted as expected.
It exists to be caught in upper stack levels so a meaningful (i.e. with the
query) InvalidQueryError can be raised.
"""
def __init__(self, what, expected, detail=None):
message = "'{0}' is not {1}".format(what, expected)
if detail:
message = "{0}: {1}".format(message, detail)
super(InvalidQueryError, self).__init__(message)
super(InvalidQueryArgumentTypeError, self).__init__(message)
class Query(object):
@ -160,8 +183,9 @@ class RegexpQuery(StringFieldQuery):
self.pattern = re.compile(self.pattern)
except re.error as exc:
# Invalid regular expression.
raise InvalidQueryError(pattern, "a regular expression",
format(exc))
raise InvalidQueryArgumentTypeError(pattern,
"a regular expression",
format(exc))
@classmethod
def string_match(cls, pattern, value):
@ -228,7 +252,7 @@ class NumericQuery(FieldQuery):
try:
return float(s)
except ValueError:
raise InvalidQueryError(s, "an int or a float")
raise InvalidQueryArgumentTypeError(s, "an int or a float")
def __init__(self, field, pattern, fast=True):
super(NumericQuery, self).__init__(field, pattern, fast)

View file

@ -1085,7 +1085,7 @@ def parse_query_string(s, model_cls):
try:
parts = [p.decode('utf8') for p in shlex.split(s)]
except ValueError as exc:
raise ValueError("Cannot parse {0!r} (error was: {1})".format(s, exc))
raise dbcore.InvalidQueryError(s, exc)
return parse_query_parts(parts, model_cls)
@ -1155,11 +1155,14 @@ class Library(dbcore.Database):
in the query string the `sort` argument is ignored.
"""
# Parse the query, if necessary.
parsed_sort = None
if isinstance(query, basestring):
query, parsed_sort = parse_query_string(query, model_cls)
elif isinstance(query, (list, tuple)):
query, parsed_sort = parse_query_parts(query, model_cls)
try:
parsed_sort = None
if isinstance(query, basestring):
query, parsed_sort = parse_query_string(query, model_cls)
elif isinstance(query, (list, tuple)):
query, parsed_sort = parse_query_parts(query, model_cls)
except dbcore.query.InvalidQueryArgumentTypeError as exc:
raise dbcore.InvalidQueryError(query, exc)
# Any non-null sort specified by the parsed query overrides the
# provided sort.

View file

@ -31,6 +31,7 @@ from test._common import unittest
from test._common import item
import beets.library
import beets.mediafile
import beets.dbcore.query
from beets import util
from beets import plugins
from beets import config
@ -1171,6 +1172,14 @@ class ItemReadTest(unittest.TestCase):
item.read('/thisfiledoesnotexist')
class ParseQueryTest(unittest.TestCase):
def test_parse_invalid_query_string(self):
with self.assertRaises(beets.dbcore.InvalidQueryError) as raised:
beets.library.parse_query_string('foo"', None)
self.assertIsInstance(raised.exception,
beets.dbcore.query.ParsingError)
def suite():
return unittest.TestLoader().loadTestsFromName(__name__)

View file

@ -24,7 +24,8 @@ from test import helper
import beets.library
from beets import dbcore
from beets.dbcore import types
from beets.dbcore.query import NoneQuery, InvalidQueryError
from beets.dbcore.query import (NoneQuery, ParsingError,
InvalidQueryArgumentTypeError)
from beets.library import Library, Item
@ -282,14 +283,15 @@ class GetTest(DummyDataTestCase):
self.assertFalse(results)
def test_invalid_query(self):
with self.assertRaises(InvalidQueryError) as raised:
with self.assertRaises(InvalidQueryArgumentTypeError) as raised:
dbcore.query.NumericQuery('year', '199a')
self.assertIn('not an int', unicode(raised.exception))
with self.assertRaises(InvalidQueryError) as raised:
with self.assertRaises(InvalidQueryArgumentTypeError) as raised:
dbcore.query.RegexpQuery('year', '199(')
self.assertIn('not a regular expression', unicode(raised.exception))
self.assertIn('unbalanced parenthesis', unicode(raised.exception))
self.assertIsInstance(raised.exception, ParsingError)
class MatchTest(_common.TestCase):