text: # This file is part of beets.
  # Copyright 2011, Adrian Sampson.
  #
  # Permission is hereby granted, free of charge, to any person obtaining
  # a copy of this software and associated documentation files (the
  # "Software"), to deal in the Software without restriction, including
  # without limitation the rights to use, copy, modify, merge, publish,
  # distribute, sublicense, and/or sell copies of the Software, and to
  # permit persons to whom the Software is furnished to do so, subject to
  # the following conditions:
  #
  # The above copyright notice and this permission notice shall be
  # included in all copies or substantial portions of the Software.
  
  """Allows inline path template customization code in the config file.
  """
  import logging
  import traceback
  
  from beets.plugins import BeetsPlugin
  
  log = logging.getLogger('beets')
  
  class InlineError(Exception):
      """Raised when a runtime error occurs in an inline expression.
      """
      def __init__(self, expr, exc):
          super(InlineError, self).__init__(
              (u"error in inline path field expression:\n" \
               u"%s\n%s: %s") % (expr, type(exc).__name__, unicode(exc))
          )
  
  def compile_expr(expr):
      """Given a Python expression, compile it as a path field function.
      The returned function takes a single argument, an Item, and returns
      a Unicode string. If the expression cannot be compiled, then an
      error is logged and this function returns None.
      """
      try:
          code = compile(u'(%s)' % expr, 'inline', 'eval')
      except SyntaxError:
          log.error(u'syntax error in field expression:\n%s' %
                    traceback.format_exc())
          return None
  
      def field_func(item):
          values = dict(item.record)
          try:
              return eval(code, values)
          except Exception as exc:
              raise InlineError(expr, exc)
      return field_func
  
  class InlinePlugin(BeetsPlugin):
      template_fields = {}
  
      def configure(self, config):
          cls = type(self)
  
          # Add field expressions.
          if config.has_section('pathfields'):
              for key, value in config.items('pathfields', True):
                  log.debug(u'adding template field %s' % key)
                  func = compile_expr(value)
                  if func is not None:
                      cls.template_fields[key] = func
  