mirror of
https://github.com/beetbox/beets.git
synced 2025-12-15 13:07:09 +01:00
Unify similar code from Type subclasses in base class
Instead of implementing the `parse()` and `format()` methods and setting the `null` attribute in subclasses, we set the `model_type` field and the generic implementations of the two methods take care of the rest. Again: No change in behaviour!
This commit is contained in:
parent
30addc12b4
commit
fafc56c95b
2 changed files with 42 additions and 39 deletions
|
|
@ -34,30 +34,42 @@ class Type(object):
|
|||
"""The `Query` subclass to be used when querying the field.
|
||||
"""
|
||||
|
||||
null = None
|
||||
"""The value to be exposed when the underlying value is None.
|
||||
model_type = unicode
|
||||
"""The python type that is used to represent the value in the model.
|
||||
|
||||
The model is guaranteed to return a value of this type if the field
|
||||
is accessed. To this end, the constructor is used by the `normalize`
|
||||
and `from_sql` methods and the `default` property.
|
||||
"""
|
||||
|
||||
@property
|
||||
def null(self):
|
||||
"""The value to be exposed when the underlying value is None.
|
||||
"""
|
||||
return self.model_type()
|
||||
|
||||
def format(self, value):
|
||||
"""Given a value of this type, produce a Unicode string
|
||||
representing the value. This is used in template evaluation.
|
||||
"""
|
||||
# Fallback formatter. Convert to Unicode at all cost.
|
||||
if value is None:
|
||||
return u''
|
||||
elif isinstance(value, basestring):
|
||||
if isinstance(value, bytes):
|
||||
return value.decode('utf8', 'ignore')
|
||||
else:
|
||||
return value
|
||||
else:
|
||||
return unicode(value)
|
||||
value = self.null
|
||||
if value is None:
|
||||
value = u''
|
||||
if isinstance(value, bytes):
|
||||
value = value.decode('utf8', 'ignore')
|
||||
|
||||
return unicode(value)
|
||||
|
||||
def parse(self, string):
|
||||
"""Parse a (possibly human-written) string and return the
|
||||
indicated value of this type.
|
||||
"""
|
||||
return string
|
||||
try:
|
||||
return self.model_type(string)
|
||||
except ValueError:
|
||||
return self.null
|
||||
|
||||
def normalize(self, value):
|
||||
"""Given a value that will be assigned into a field of this
|
||||
|
|
@ -67,17 +79,29 @@ class Type(object):
|
|||
if value is None:
|
||||
return self.null
|
||||
else:
|
||||
# TODO This should eventually be replaced by
|
||||
# `self.model_type(value)`
|
||||
return value
|
||||
|
||||
def from_sql(self, sql_value):
|
||||
"""Convert a value received from the database adapter to a value
|
||||
stored in the model object.
|
||||
"""Receives the value stored in the SQL backend and return the
|
||||
value to be stored in the model.
|
||||
|
||||
For fixed fields the type of `value` is determined by the column
|
||||
type given in the `sql` property and the SQL to Python mapping
|
||||
given here:
|
||||
https://docs.python.org/2/library/sqlite3.html#sqlite-and-python-types
|
||||
|
||||
For flexible field the value is a unicode object. The method
|
||||
must therefore be able to parse them.
|
||||
"""
|
||||
return self.normalize(sql_value)
|
||||
|
||||
def to_sql(self, model_value):
|
||||
"""Convert a value as stored in the model object to a value used
|
||||
by the database adapter.
|
||||
For flexible field the value is a unicode object. The method
|
||||
must therefore be able to parse them.
|
||||
"""
|
||||
return model_value
|
||||
|
||||
|
|
@ -85,7 +109,7 @@ class Type(object):
|
|||
# Reusable types.
|
||||
|
||||
class Default(Type):
|
||||
pass
|
||||
null = None
|
||||
|
||||
|
||||
class Integer(Type):
|
||||
|
|
@ -93,16 +117,7 @@ class Integer(Type):
|
|||
"""
|
||||
sql = u'INTEGER'
|
||||
query = query.NumericQuery
|
||||
null = 0
|
||||
|
||||
def format(self, value):
|
||||
return unicode(value or 0)
|
||||
|
||||
def parse(self, string):
|
||||
try:
|
||||
return int(string)
|
||||
except ValueError:
|
||||
return 0
|
||||
model_type = int
|
||||
|
||||
|
||||
class PaddedInt(Integer):
|
||||
|
|
@ -144,17 +159,11 @@ class Float(Type):
|
|||
"""
|
||||
sql = u'REAL'
|
||||
query = query.NumericQuery
|
||||
null = 0.0
|
||||
model_type = float
|
||||
|
||||
def format(self, value):
|
||||
return u'{0:.1f}'.format(value or 0.0)
|
||||
|
||||
def parse(self, string):
|
||||
try:
|
||||
return float(string)
|
||||
except ValueError:
|
||||
return 0.0
|
||||
|
||||
|
||||
class NullFloat(Float):
|
||||
"""Same as `Float`, but does not normalize `None` to `0.0`.
|
||||
|
|
@ -167,13 +176,6 @@ class String(Type):
|
|||
"""
|
||||
sql = u'TEXT'
|
||||
query = query.SubstringQuery
|
||||
null = u''
|
||||
|
||||
def format(self, value):
|
||||
return unicode(value) if value else u''
|
||||
|
||||
def parse(self, string):
|
||||
return string
|
||||
|
||||
|
||||
class Boolean(Type):
|
||||
|
|
@ -181,7 +183,7 @@ class Boolean(Type):
|
|||
"""
|
||||
sql = u'INTEGER'
|
||||
query = query.BooleanQuery
|
||||
null = False
|
||||
model_type = bool
|
||||
|
||||
def format(self, value):
|
||||
return unicode(bool(value))
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@ class DateType(types.Float):
|
|||
class PathType(types.Type):
|
||||
sql = u'BLOB'
|
||||
query = PathQuery
|
||||
model_type = str
|
||||
|
||||
def format(self, value):
|
||||
return util.displayable_path(value)
|
||||
|
|
|
|||
Loading…
Reference in a new issue