prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  smartplaylist: Respect sort terms in queries
  It would be nice to be able sort items in smart playlists, like so:
  
  ```
  smartplaylist:
    relative_to: ~/music
    playlist_dir: ~/.mpd/playlists
    playlists:
      - name: '2014.m3u'
        query: 'year:2014 added+'
      - name: 'imported-%time{$added,%Y-%m}.m3u'
        query: "added:: path+"
  ```
  
  I'm unfamiliar with the code but it looks like the smartplaylist plugin [discards the query `sort` field](https://github.com/sampsyo/beets/blob/master/beetsplug/smartplaylist.py#L45) when building playlists. Would it be possible to keep the custom sort?
  
  
  </issue>
  <code>
  [start of beetsplug/smartplaylist.py]
  1 # This file is part of beets.
  2 # Copyright 2013, Dang Mai <contact@dangmai.net>.
  3 #
  4 # Permission is hereby granted, free of charge, to any person obtaining
  5 # a copy of this software and associated documentation files (the
  6 # "Software"), to deal in the Software without restriction, including
  7 # without limitation the rights to use, copy, modify, merge, publish,
  8 # distribute, sublicense, and/or sell copies of the Software, and to
  9 # permit persons to whom the Software is furnished to do so, subject to
  10 # the following conditions:
  11 #
  12 # The above copyright notice and this permission notice shall be
  13 # included in all copies or substantial portions of the Software.
  14 
  15 """Generates smart playlists based on beets queries.
  16 """
  17 from __future__ import print_function
  18 
  19 from beets.plugins import BeetsPlugin
  20 from beets import config, ui, library
  21 from beets import dbcore
  22 from beets.util import normpath, syspath
  23 import os
  24 
  25 # Global variable so that smartplaylist can detect database changes and run
  26 # only once before beets exits.
  27 database_changed = False
  28 
  29 
  30 def _items_for_query(lib, playlist, album=False):
  31     """Get the matching items for a playlist's configured queries.
  32     `album` indicates whether to process the item-level query or the
  33     album-level query (if any).
  34     """
  35     key = 'album_query' if album else 'query'
  36     if key not in playlist:
  37         return []
  38 
  39     # Parse quer(ies). If it's a list, join the queries with OR.
  40     query_strings = playlist[key]
  41     if not isinstance(query_strings, (list, tuple)):
  42         query_strings = [query_strings]
  43     model = library.Album if album else library.Item
  44     query = dbcore.OrQuery(
  45         [library.parse_query_string(q, model)[0] for q in query_strings]
  46     )
  47 
  48     # Execute query, depending on type.
  49     if album:
  50         result = []
  51         for album in lib.albums(query):
  52             result.extend(album.items())
  53         return result
  54     else:
  55         return lib.items(query)
  56 
  57 
  58 def update_playlists(lib):
  59     ui.print_("Updating smart playlists...")
  60     playlists = config['smartplaylist']['playlists'].get(list)
  61     playlist_dir = config['smartplaylist']['playlist_dir'].as_filename()
  62     relative_to = config['smartplaylist']['relative_to'].get()
  63     if relative_to:
  64         relative_to = normpath(relative_to)
  65 
  66     for playlist in playlists:
  67         items = []
  68         items.extend(_items_for_query(lib, playlist, True))
  69         items.extend(_items_for_query(lib, playlist, False))
  70 
  71         m3us = {}
  72         basename = playlist['name'].encode('utf8')
  73         # As we allow tags in the m3u names, we'll need to iterate through
  74         # the items and generate the correct m3u file names.
  75         for item in items:
  76             m3u_name = item.evaluate_template(basename, True)
  77             if not (m3u_name in m3us):
  78                 m3us[m3u_name] = []
  79             item_path = item.path
  80             if relative_to:
  81                 item_path = os.path.relpath(item.path, relative_to)
  82             if item_path not in m3us[m3u_name]:
  83                 m3us[m3u_name].append(item_path)
  84         # Now iterate through the m3us that we need to generate
  85         for m3u in m3us:
  86             m3u_path = normpath(os.path.join(playlist_dir, m3u))
  87             with open(syspath(m3u_path), 'w') as f:
  88                 for path in m3us[m3u]:
  89                     f.write(path + '\n')
  90     ui.print_("... Done")
  91 
  92 
  93 class SmartPlaylistPlugin(BeetsPlugin):
  94     def __init__(self):
  95         super(SmartPlaylistPlugin, self).__init__()
  96         self.config.add({
  97             'relative_to': None,
  98             'playlist_dir': u'.',
  99             'auto': True,
  100             'playlists': []
  101         })
  102 
  103     def commands(self):
  104         def update(lib, opts, args):
  105             update_playlists(lib)
  106         spl_update = ui.Subcommand('splupdate',
  107                                    help='update the smart playlists')
  108         spl_update.func = update
  109         return [spl_update]
  110 
  111 
  112 @SmartPlaylistPlugin.listen('database_change')
  113 def handle_change(lib):
  114     global database_changed
  115     database_changed = True
  116 
  117 
  118 @SmartPlaylistPlugin.listen('cli_exit')
  119 def update(lib):
  120     auto = config['smartplaylist']['auto']
  121     if database_changed and auto:
  122         update_playlists(lib)
  123
  [end of beetsplug/smartplaylist.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/beetsplug/smartplaylist.py b/beetsplug/smartplaylist.py
  --- a/beetsplug/smartplaylist.py
  +++ b/beetsplug/smartplaylist.py
  @@ -18,7 +18,6 @@
   
   from beets.plugins import BeetsPlugin
   from beets import config, ui, library
  -from beets import dbcore
   from beets.util import normpath, syspath
   import os
   
  @@ -36,23 +35,21 @@
       if key not in playlist:
           return []
   
  -    # Parse quer(ies). If it's a list, join the queries with OR.
  +    # Parse quer(ies). If it's a list, perform the queries and manually
  +    # concatenate the results
       query_strings = playlist[key]
       if not isinstance(query_strings, (list, tuple)):
           query_strings = [query_strings]
       model = library.Album if album else library.Item
  -    query = dbcore.OrQuery(
  -        [library.parse_query_string(q, model)[0] for q in query_strings]
  -    )
  -
  -    # Execute query, depending on type.
  -    if album:
  -        result = []
  -        for album in lib.albums(query):
  -            result.extend(album.items())
  -        return result
  -    else:
  -        return lib.items(query)
  +    results = []
  +    for q in query_strings:
  +        querystr, sort = library.parse_query_string(q, model)
  +        if album:
  +            new = lib.albums(querystr, sort)
  +        else:
  +            new = lib.items(querystr, sort)
  +        results.extend(new)
  +    return results
   
   
   def update_playlists(lib):
  
verification_info: {"golden_diff": "diff --git a/beetsplug/smartplaylist.py b/beetsplug/smartplaylist.py\n--- a/beetsplug/smartplaylist.py\n+++ b/beetsplug/smartplaylist.py\n@@ -18,7 +18,6 @@\n \n from beets.plugins import BeetsPlugin\n from beets import config, ui, library\n-from beets import dbcore\n from beets.util import normpath, syspath\n import os\n \n@@ -36,23 +35,21 @@\n     if key not in playlist:\n         return []\n \n-    # Parse quer(ies). If it's a list, join the queries with OR.\n+    # Parse quer(ies). If it's a list, perform the queries and manually\n+    # concatenate the results\n     query_strings = playlist[key]\n     if not isinstance(query_strings, (list, tuple)):\n         query_strings = [query_strings]\n     model = library.Album if album else library.Item\n-    query = dbcore.OrQuery(\n-        [library.parse_query_string(q, model)[0] for q in query_strings]\n-    )\n-\n-    # Execute query, depending on type.\n-    if album:\n-        result = []\n-        for album in lib.albums(query):\n-            result.extend(album.items())\n-        return result\n-    else:\n-        return lib.items(query)\n+    results = []\n+    for q in query_strings:\n+        querystr, sort = library.parse_query_string(q, model)\n+        if album:\n+            new = lib.albums(querystr, sort)\n+        else:\n+            new = lib.items(querystr, sort)\n+        results.extend(new)\n+    return results\n \n \n def update_playlists(lib):\n", "issue": "smartplaylist: Respect sort terms in queries\nIt would be nice to be able sort items in smart playlists, like so:\n\n```\nsmartplaylist:\n  relative_to: ~/music\n  playlist_dir: ~/.mpd/playlists\n  playlists:\n    - name: '2014.m3u'\n      query: 'year:2014 added+'\n    - name: 'imported-%time{$added,%Y-%m}.m3u'\n      query: \"added:: path+\"\n```\n\nI'm unfamiliar with the code but it looks like the smartplaylist plugin [discards the query `sort` field](https://github.com/sampsyo/beets/blob/master/beetsplug/smartplaylist.py#L45) when building playlists. Would it be possible to keep the custom sort?\n\n", "before_files": [{"content": "# This file is part of beets.\n# Copyright 2013, Dang Mai <contact@dangmai.net>.\n#\n# Permission is hereby granted, free of charge, to any person obtaining\n# a copy of this software and associated documentation files (the\n# \"Software\"), to deal in the Software without restriction, including\n# without limitation the rights to use, copy, modify, merge, publish,\n# distribute, sublicense, and/or sell copies of the Software, and to\n# permit persons to whom the Software is furnished to do so, subject to\n# the following conditions:\n#\n# The above copyright notice and this permission notice shall be\n# included in all copies or substantial portions of the Software.\n\n\"\"\"Generates smart playlists based on beets queries.\n\"\"\"\nfrom __future__ import print_function\n\nfrom beets.plugins import BeetsPlugin\nfrom beets import config, ui, library\nfrom beets import dbcore\nfrom beets.util import normpath, syspath\nimport os\n\n# Global variable so that smartplaylist can detect database changes and run\n# only once before beets exits.\ndatabase_changed = False\n\n\ndef _items_for_query(lib, playlist, album=False):\n    \"\"\"Get the matching items for a playlist's configured queries.\n    `album` indicates whether to process the item-level query or the\n    album-level query (if any).\n    \"\"\"\n    key = 'album_query' if album else 'query'\n    if key not in playlist:\n        return []\n\n    # Parse quer(ies). If it's a list, join the queries with OR.\n    query_strings = playlist[key]\n    if not isinstance(query_strings, (list, tuple)):\n        query_strings = [query_strings]\n    model = library.Album if album else library.Item\n    query = dbcore.OrQuery(\n        [library.parse_query_string(q, model)[0] for q in query_strings]\n    )\n\n    # Execute query, depending on type.\n    if album:\n        result = []\n        for album in lib.albums(query):\n            result.extend(album.items())\n        return result\n    else:\n        return lib.items(query)\n\n\ndef update_playlists(lib):\n    ui.print_(\"Updating smart playlists...\")\n    playlists = config['smartplaylist']['playlists'].get(list)\n    playlist_dir = config['smartplaylist']['playlist_dir'].as_filename()\n    relative_to = config['smartplaylist']['relative_to'].get()\n    if relative_to:\n        relative_to = normpath(relative_to)\n\n    for playlist in playlists:\n        items = []\n        items.extend(_items_for_query(lib, playlist, True))\n        items.extend(_items_for_query(lib, playlist, False))\n\n        m3us = {}\n        basename = playlist['name'].encode('utf8')\n        # As we allow tags in the m3u names, we'll need to iterate through\n        # the items and generate the correct m3u file names.\n        for item in items:\n            m3u_name = item.evaluate_template(basename, True)\n            if not (m3u_name in m3us):\n                m3us[m3u_name] = []\n            item_path = item.path\n            if relative_to:\n                item_path = os.path.relpath(item.path, relative_to)\n            if item_path not in m3us[m3u_name]:\n                m3us[m3u_name].append(item_path)\n        # Now iterate through the m3us that we need to generate\n        for m3u in m3us:\n            m3u_path = normpath(os.path.join(playlist_dir, m3u))\n            with open(syspath(m3u_path), 'w') as f:\n                for path in m3us[m3u]:\n                    f.write(path + '\\n')\n    ui.print_(\"... Done\")\n\n\nclass SmartPlaylistPlugin(BeetsPlugin):\n    def __init__(self):\n        super(SmartPlaylistPlugin, self).__init__()\n        self.config.add({\n            'relative_to': None,\n            'playlist_dir': u'.',\n            'auto': True,\n            'playlists': []\n        })\n\n    def commands(self):\n        def update(lib, opts, args):\n            update_playlists(lib)\n        spl_update = ui.Subcommand('splupdate',\n                                   help='update the smart playlists')\n        spl_update.func = update\n        return [spl_update]\n\n\n@SmartPlaylistPlugin.listen('database_change')\ndef handle_change(lib):\n    global database_changed\n    database_changed = True\n\n\n@SmartPlaylistPlugin.listen('cli_exit')\ndef update(lib):\n    auto = config['smartplaylist']['auto']\n    if database_changed and auto:\n        update_playlists(lib)\n", "path": "beetsplug/smartplaylist.py"}]}