From c93e7e443e9f6e33103c63829f8dd503dca76445 Mon Sep 17 00:00:00 2001 From: Steve Dougherty Date: Sun, 29 Apr 2012 11:07:53 -0400 Subject: [PATCH] Run functions and substitute fields in list format strings. --- beets/library.py | 80 +++++++++++++++++++++++++------------------- beets/ui/commands.py | 4 ++- 2 files changed, 49 insertions(+), 35 deletions(-) diff --git a/beets/library.py b/beets/library.py index efa8f0c68..449331478 100644 --- a/beets/library.py +++ b/beets/library.py @@ -829,6 +829,51 @@ class Library(BaseLibrary): self.conn.executescript(setup_sql) self.conn.commit() + def substitute_template(self, item, template, pathmod=None): + """Runs functions and substitutes fields in template. If a pathmod is + specified, all values are path-sanitized. + """ + # Get the item's Album if it has one. + album = self.get_album(item) + + # Build the mapping for substitution in the template, + # beginning with the values from the database. + mapping = {} + for key in ITEM_KEYS_META: + # Get the values from either the item or its album. + if key in ALBUM_KEYS_ITEM and album is not None: + # From album. + value = getattr(album, key) + else: + # From Item. + value = getattr(item, key) + if pathmod is not None: + mapping[key] = util.sanitize_for_path(value, pathmod, key) + else: + mapping[key] = value + + # Use the album artist if the track artist is not set and + # vice-versa. + if not mapping['artist']: + mapping['artist'] = mapping['albumartist'] + if not mapping['albumartist']: + mapping['albumartist'] = mapping['artist'] + + # Get values from plugins. + for key, value in plugins.template_values(item).iteritems(): + if pathmod is not None: + mapping[key] = util.sanitize_for_path(value, pathmod, key) + else: + mapping[key] = value + + # Get template functions. + funcs = DefaultTemplateFunctions(self, item, pathmod).functions() + funcs.update(plugins.template_funcs()) + + # Perform substitution. + return template.substitute(mapping, funcs) + + def destination(self, item, pathmod=None, in_album=False, fragment=False, basedir=None, platform=None): """Returns the path in the library directory designated for item @@ -867,41 +912,8 @@ class Library(BaseLibrary): break else: assert False, "no default path format" - subpath_tmpl = Template(path_format) - # Get the item's Album if it has one. - album = self.get_album(item) - - # Build the mapping for substitution in the path template, - # beginning with the values from the database. - mapping = {} - for key in ITEM_KEYS_META: - # Get the values from either the item or its album. - if key in ALBUM_KEYS_ITEM and album is not None: - # From album. - value = getattr(album, key) - else: - # From Item. - value = getattr(item, key) - mapping[key] = util.sanitize_for_path(value, pathmod, key) - - # Use the album artist if the track artist is not set and - # vice-versa. - if not mapping['artist']: - mapping['artist'] = mapping['albumartist'] - if not mapping['albumartist']: - mapping['albumartist'] = mapping['artist'] - - # Get values from plugins. - for key, value in plugins.template_values(item).iteritems(): - mapping[key] = util.sanitize_for_path(value, pathmod, key) - - # Get template functions. - funcs = DefaultTemplateFunctions(self, item, pathmod).functions() - funcs.update(plugins.template_funcs()) - - # Perform substitution. - subpath = subpath_tmpl.substitute(mapping, funcs) + subpath = self.substitute_template(item, Template(path_format), pathmod=pathmod) # Prepare path for output: normalize Unicode characters. if platform == 'darwin': diff --git a/beets/ui/commands.py b/beets/ui/commands.py index 9c8fb0e98..790bcbe67 100644 --- a/beets/ui/commands.py +++ b/beets/ui/commands.py @@ -809,6 +809,7 @@ def list_items(lib, query, album, path, fmt): fmt = u'$albumartist - $album' else: fmt = u'$artist - $album - $title' + template = Template(fmt) if album: @@ -816,13 +817,14 @@ def list_items(lib, query, album, path, fmt): if path: print_(album.item_dir()) elif fmt is not None: + #TODO: Support functions and plugin fields in album mode. print_(template.substitute(album._record)) else: for item in lib.items(query): if path: print_(item.path) elif fmt is not None: - print_(template.substitute(item.record)) + print_(lib.substitute_template(item, template)) list_cmd = ui.Subcommand('list', help='query the library', aliases=('ls',)) list_cmd.parser.add_option('-a', '--album', action='store_true',