From f6f974ec871817cddd9f329b519e7f5768026e35 Mon Sep 17 00:00:00 2001 From: Thomas Scholtes Date: Thu, 10 Apr 2014 17:11:21 +0200 Subject: [PATCH] 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. --- beets/library.py | 151 +++++++++++++++++--------------------- beets/ui/commands.py | 4 +- beetsplug/bpd/__init__.py | 4 +- beetsplug/zero.py | 4 +- test/test_query.py | 6 +- 5 files changed, 78 insertions(+), 91 deletions(-) diff --git a/beets/library.py b/beets/library.py index f9285cabb..853f438df 100644 --- a/beets/library.py +++ b/beets/library.py @@ -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 diff --git a/beets/ui/commands.py b/beets/ui/commands.py index 1b1aab5b0..e1636f7bc 100644 --- a/beets/ui/commands.py +++ b/beets/ui/commands.py @@ -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(): diff --git a/beetsplug/bpd/__init__.py b/beetsplug/bpd/__init__.py index 13eb6fb97..d221c318c 100644 --- a/beetsplug/bpd/__init__.py +++ b/beetsplug/bpd/__init__.py @@ -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') diff --git a/beetsplug/zero.py b/beetsplug/zero.py index 1ea6d0e50..af6e350bd 100644 --- a/beetsplug/zero.py +++ b/beetsplug/zero.py @@ -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: diff --git a/test/test_query.py b/test/test_query.py index d9b636527..2ea60dfdd 100644 --- a/test/test_query.py +++ b/test/test_query.py @@ -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):