Remove ITEM_* constants

We might consider renaming `Item._fields` to `Item.fields` since other parts of
beets use it as a replacement for `ITEM_KEYS`.

See also #650.
This commit is contained in:
Thomas Scholtes 2014-04-10 17:11:21 +02:00
parent 883e3b3bc7
commit f6f974ec87
5 changed files with 78 additions and 91 deletions

View file

@ -110,84 +110,6 @@ class PathType(types.Type):
return normpath(bytestring_path(string))
# Model field lists.
# Fields in the "items" database table; all the metadata available for
# items in the library. These are used directly in SQL; they are
# vulnerable to injection if accessible to the user.
# Each tuple has the following values:
# - The name of the field.
# - The (Python) type of the field.
# - Is the field writable?
# - Does the field reflect an attribute of a MediaFile?
ITEM_FIELDS = [
('id', types.Id(True)),
('path', PathType()),
('album_id', types.Id(False)),
('title', types.String()),
('artist', types.String()),
('artist_sort', types.String()),
('artist_credit', types.String()),
('album', types.String()),
('albumartist', types.String()),
('albumartist_sort', types.String()),
('albumartist_credit', types.String()),
('genre', types.String()),
('composer', types.String()),
('grouping', types.String()),
('year', types.PaddedInt(4)),
('month', types.PaddedInt(2)),
('day', types.PaddedInt(2)),
('track', types.PaddedInt(2)),
('tracktotal', types.PaddedInt(2)),
('disc', types.PaddedInt(2)),
('disctotal', types.PaddedInt(2)),
('lyrics', types.String()),
('comments', types.String()),
('bpm', types.Integer()),
('comp', types.Boolean()),
('mb_trackid', types.String()),
('mb_albumid', types.String()),
('mb_artistid', types.String()),
('mb_albumartistid', types.String()),
('albumtype', types.String()),
('label', types.String()),
('acoustid_fingerprint', types.String()),
('acoustid_id', types.String()),
('mb_releasegroupid', types.String()),
('asin', types.String()),
('catalognum', types.String()),
('script', types.String()),
('language', types.String()),
('country', types.String()),
('albumstatus', types.String()),
('media', types.String()),
('albumdisambig', types.String()),
('disctitle', types.String()),
('encoder', types.String()),
('rg_track_gain', types.Float()),
('rg_track_peak', types.Float()),
('rg_album_gain', types.Float()),
('rg_album_peak', types.Float()),
('original_year', types.PaddedInt(4)),
('original_month', types.PaddedInt(2)),
('original_day', types.PaddedInt(2)),
('length', types.Float()),
('bitrate', types.ScaledInt(1000, u'kbps')),
('format', types.String()),
('samplerate', types.ScaledInt(1000, u'kHz')),
('bitdepth', types.Integer()),
('channels', types.Integer()),
('mtime', DateType()),
('added', DateType()),
]
ITEM_KEYS = [f[0] for f in ITEM_FIELDS]
# Database fields for the "albums" table.
# The third entry in each tuple indicates whether the field reflects an
# identically-named field in the items table.
@ -232,7 +154,6 @@ ALBUM_KEYS_ITEM = [f[0] for f in ALBUM_FIELDS if f[2]]
# Default search fields for each model.
ALBUM_DEFAULT_FIELDS = ('album', 'albumartist', 'genre')
ITEM_DEFAULT_FIELDS = ALBUM_DEFAULT_FIELDS + ('artist', 'title', 'comments')
# Special path format key.
@ -328,12 +249,76 @@ class LibModel(dbcore.Model):
class Item(LibModel):
_fields = dict((name, typ) for (name, typ) in ITEM_FIELDS)
_table = 'items'
_flex_table = 'item_attributes'
_search_fields = ITEM_DEFAULT_FIELDS
_fields = {
'id': types.Id(True),
'path': PathType(),
'album_id': types.Id(False),
_media_fields = set(MediaFile.readable_fields()).intersection(ITEM_KEYS)
'title': types.String(),
'artist': types.String(),
'artist_sort': types.String(),
'artist_credit': types.String(),
'album': types.String(),
'albumartist': types.String(),
'albumartist_sort': types.String(),
'albumartist_credit': types.String(),
'genre': types.String(),
'composer': types.String(),
'grouping': types.String(),
'year': types.PaddedInt(4),
'month': types.PaddedInt(2),
'day': types.PaddedInt(2),
'track': types.PaddedInt(2),
'tracktotal': types.PaddedInt(2),
'disc': types.PaddedInt(2),
'disctotal': types.PaddedInt(2),
'lyrics': types.String(),
'comments': types.String(),
'bpm': types.Integer(),
'comp': types.Boolean(),
'mb_trackid': types.String(),
'mb_albumid': types.String(),
'mb_artistid': types.String(),
'mb_albumartistid': types.String(),
'albumtype': types.String(),
'label': types.String(),
'acoustid_fingerprint': types.String(),
'acoustid_id': types.String(),
'mb_releasegroupid': types.String(),
'asin': types.String(),
'catalognum': types.String(),
'script': types.String(),
'language': types.String(),
'country': types.String(),
'albumstatus': types.String(),
'media': types.String(),
'albumdisambig': types.String(),
'disctitle': types.String(),
'encoder': types.String(),
'rg_track_gain': types.Float(),
'rg_track_peak': types.Float(),
'rg_album_gain': types.Float(),
'rg_album_peak': types.Float(),
'original_year': types.PaddedInt(4),
'original_month': types.PaddedInt(2),
'original_day': types.PaddedInt(2),
'length': types.Float(),
'bitrate': types.ScaledInt(1000, u'kbps'),
'format': types.String(),
'samplerate': types.ScaledInt(1000, u'kHz'),
'bitdepth': types.Integer(),
'channels': types.Integer(),
'mtime': DateType(),
'added': DateType(),
}
_search_fields = ALBUM_DEFAULT_FIELDS + ('artist', 'title', 'comments')
_media_fields = set(MediaFile.readable_fields()) \
.intersection(_fields.keys())
"""Set of item fields that are backed by `MediaFile` fields.
Any kind of field (fixed, flexible, and computed) may be a media
@ -563,7 +548,7 @@ class Item(LibModel):
album = self.get_album()
if album:
for key in album.keys(True):
if key in ALBUM_KEYS_ITEM or key not in ITEM_KEYS:
if key in ALBUM_KEYS_ITEM or key not in self._fields.keys():
mapping[key] = album._get_formatted(key, for_path)
# Use the album artist if the track artist is not set and

View file

@ -99,7 +99,7 @@ def fields_func(lib, opts, args):
_print_rows(plugin_fields)
print("Item fields:")
_print_rows(library.ITEM_KEYS)
_print_rows(library.Item._fields.keys())
_show_plugin_fields(False)
print("\nAlbum fields:")
@ -1401,7 +1401,7 @@ def completion_script(commands):
# Fields
yield " fields='%s'\n" % ' '.join(
set(library.ITEM_KEYS + library.ALBUM_KEYS))
set(library.Item._fields.keys() + library.ALBUM_KEYS))
# Command options
for cmd, opts in options.items():

View file

@ -30,7 +30,7 @@ from beets.plugins import BeetsPlugin
import beets.ui
from beets import vfs
from beets.util import bluelet
from beets.library import ITEM_KEYS
from beets.library import Item
from beets import dbcore
from beets.mediafile import MediaFile
@ -68,7 +68,7 @@ SAFE_COMMANDS = (
u'close', u'commands', u'notcommands', u'password', u'ping',
)
ITEM_KEYS_WRITABLE = set(MediaFile.fields()).intersection(ITEM_KEYS)
ITEM_KEYS_WRITABLE = set(MediaFile.fields()).intersection(Item._fields.keys())
# Loggers.
log = logging.getLogger('beets.bpd')

View file

@ -17,7 +17,7 @@
import re
import logging
from beets.plugins import BeetsPlugin
from beets.library import ITEM_KEYS
from beets.library import Item
from beets.importer import action
from beets.util import confit
@ -46,7 +46,7 @@ class ZeroPlugin(BeetsPlugin):
self.warned = False
for f in self.config['fields'].as_str_seq():
if f not in ITEM_KEYS:
if f not in Item._fields.keys():
self._log.error(u'[zero] invalid field: {0}'.format(f))
else:
try:

View file

@ -81,8 +81,10 @@ class QueryParseTest(_common.TestCase):
class AnyFieldQueryTest(_common.LibTestCase):
def test_no_restriction(self):
q = dbcore.query.AnyFieldQuery('title', beets.library.ITEM_KEYS,
dbcore.query.SubstringQuery)
q = dbcore.query.AnyFieldQuery(
'title', beets.library.Item._fields.keys(),
dbcore.query.SubstringQuery
)
self.assertEqual(self.lib.items(q).get().title, 'the title')
def test_restriction_completeness(self):