mirror of
https://github.com/beetbox/beets.git
synced 2025-12-15 21:14:19 +01:00
confit: fix unicode and numeric validation
This commit is contained in:
parent
fe2a68722f
commit
8bc563fafc
3 changed files with 55 additions and 19 deletions
|
|
@ -664,8 +664,8 @@ def _raw_main(args, configfh):
|
|||
config['library'].get(confit.as_filename),
|
||||
config['directory'].get(confit.as_filename),
|
||||
config['paths'].get(dict), # FIXME
|
||||
config['art_filename'].get(basestring),
|
||||
config['timeout'].get(float), # FIXME int okay
|
||||
config['art_filename'].get(unicode),
|
||||
config['timeout'].get(confit.as_number),
|
||||
config['replace'].get(dict),
|
||||
)
|
||||
except sqlite3.OperationalError:
|
||||
|
|
|
|||
|
|
@ -840,9 +840,9 @@ def list_func(lib, config, opts, args):
|
|||
if not fmt:
|
||||
# If no format is specified, fall back to a default.
|
||||
if opts.album:
|
||||
fmt = config['list_format_album'].get(basestring)
|
||||
fmt = config['list_format_album'].get(unicode)
|
||||
else:
|
||||
fmt = config['list_format_item'].get(basestring)
|
||||
fmt = config['list_format_item'].get(unicode)
|
||||
list_items(lib, decargs(args), opts.album, opts.path, fmt)
|
||||
list_cmd.func = list_func
|
||||
default_commands.append(list_cmd)
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ DEFAULT_FILENAME = 'config_default.yaml'
|
|||
|
||||
PY3 = sys.version_info[0] == 3
|
||||
STRING = str if PY3 else unicode
|
||||
NUMERIC_TYPES = [int, float] if PY3 else [int, float, long]
|
||||
|
||||
def iter_first(sequence):
|
||||
"""Get the first element from an iterable or raise a ValueError if
|
||||
|
|
@ -126,8 +127,8 @@ class ConfigView(object):
|
|||
# Check type of value.
|
||||
if not isinstance(value, typ):
|
||||
raise ConfigTypeError(
|
||||
"{0} must by of type {1}, not {2}".format(
|
||||
self.name, typ, type(value)
|
||||
"{0} must be of type {1}, not {2}".format(
|
||||
self.name, typ.__name__, type(value).__name__
|
||||
)
|
||||
)
|
||||
|
||||
|
|
@ -190,8 +191,11 @@ class ConfigView(object):
|
|||
try:
|
||||
cur_keys = dic.keys()
|
||||
except AttributeError:
|
||||
raise ConfigTypeError('%s must be a dict, not %s' %
|
||||
(self.name, STRING(type(dic))))
|
||||
raise ConfigTypeError(
|
||||
'{0} must be a dict, not {1}'.format(
|
||||
self.name, type(dic).__name__
|
||||
)
|
||||
)
|
||||
keys.update(cur_keys)
|
||||
return keys
|
||||
|
||||
|
|
@ -224,8 +228,11 @@ class ConfigView(object):
|
|||
try:
|
||||
it = iter(collection)
|
||||
except TypeError:
|
||||
raise ConfigTypeError('%s must be an iterable, not %s' %
|
||||
(self.name, STRING(type(collection))))
|
||||
raise ConfigTypeError(
|
||||
'{0} must be an iterable, not {1}'.format(
|
||||
self.name, type(collection).__name__
|
||||
)
|
||||
)
|
||||
for value in it:
|
||||
yield value
|
||||
|
||||
|
|
@ -275,9 +282,11 @@ class Subview(ConfigView):
|
|||
continue
|
||||
except TypeError:
|
||||
# Not subscriptable.
|
||||
raise ConfigTypeError("%s must be a collection, not %s" %
|
||||
(self.parent.name,
|
||||
STRING(type(collection))))
|
||||
raise ConfigTypeError(
|
||||
"{0} must be a collection, not {1}".format(
|
||||
self.parent.name, type(collection).__name__
|
||||
)
|
||||
)
|
||||
yield value
|
||||
|
||||
@property
|
||||
|
|
@ -358,6 +367,38 @@ def as_choice(choices):
|
|||
return value
|
||||
return f
|
||||
|
||||
def as_number(view, value):
|
||||
"""Ensure that a value is of numeric type."""
|
||||
for typ in NUMERIC_TYPES:
|
||||
if isinstance(value, typ):
|
||||
return value
|
||||
raise ConfigTypeError(
|
||||
'{0} must be numeric, not {1}'.format(
|
||||
view.name, type(value).__name__
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
# YAML.
|
||||
|
||||
class Loader(yaml.SafeLoader):
|
||||
"""A customized YAML safe loader that reads all strings as Unicode
|
||||
objects.
|
||||
"""
|
||||
def _construct_unicode(self, node):
|
||||
return self.construct_scalar(node)
|
||||
Loader.add_constructor('tag:yaml.org,2002:str', Loader._construct_unicode)
|
||||
|
||||
def load_yaml(filename):
|
||||
"""Read a YAML document from a file. If the file cannot be read or
|
||||
parsed, a ConfigReadError is raised.
|
||||
"""
|
||||
try:
|
||||
with open(filename, 'r') as f:
|
||||
return yaml.load(f, Loader=Loader)
|
||||
except (IOError, yaml.error.YAMLError) as exc:
|
||||
raise ConfigReadError(filename, exc)
|
||||
|
||||
|
||||
# Main interface.
|
||||
|
||||
|
|
@ -416,12 +457,7 @@ class Configuration(RootView):
|
|||
"""
|
||||
self.sources = []
|
||||
for filename in self._filenames():
|
||||
try:
|
||||
with open(filename, 'r') as f:
|
||||
data = yaml.load(f)
|
||||
except (IOError, yaml.error.YAMLError) as exc:
|
||||
raise ConfigReadError(filename, exc)
|
||||
self.sources.append(data)
|
||||
self.sources.append(load_yaml(filename))
|
||||
|
||||
def add_args(self, namespace):
|
||||
"""Add parsed command-line arguments, generated by a library
|
||||
|
|
|
|||
Loading…
Reference in a new issue