Widen usage of InvalidQueryError

Replace previous InvalidQueryError with InvalidQueryArgumentTypeError
which extends the former as TypeError. However they lack context: the
query that caused the error.

Raise an InvalidQueryError when a shell-like expression cannot be parsed
by shlex.

Improve #1290.
This commit is contained in:
Bruno Cauet 2015-02-01 09:37:36 +01:00
parent bbc6d0906b
commit 54887e7655
5 changed files with 25 additions and 9 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

@ -24,11 +24,17 @@ from datetime import datetime, timedelta
class InvalidQueryError(ValueError):
def __init__(self, query, explanation):
message = "Invalid query '{0}': {1}".format(query, explanation)
super(InvalidQueryError, self).__init__(message)
class InvalidQueryArgumentTypeError(InvalidQueryError, TypeError):
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__(None, message)
class Query(object):
@ -160,8 +166,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 +235,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)

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
from beets import util
from beets import plugins
from beets import config
@ -1171,6 +1172,12 @@ class ItemReadTest(unittest.TestCase):
item.read('/thisfiledoesnotexist')
class ParseQueryTest(unittest.TestCase):
def test_parse_invalid_query_string(self):
with self.assertRaises(beets.dbcore.InvalidQueryError):
beets.library.parse_query_string('foo"', None)
def suite():
return unittest.TestLoader().loadTestsFromName(__name__)

View file

@ -23,8 +23,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 import types, InvalidQueryError
from beets.dbcore.query import NoneQuery, InvalidQueryArgumentTypeError
from beets.library import Library, Item
@ -282,14 +282,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, (InvalidQueryError, TypeError))
class MatchTest(_common.TestCase):