# Buggy code
def find_exact(tracks, query=None, uris=None):
    # TODO Only return results within URI roots given by ``uris``

    if query is None:
        query = {}

    _validate_query(query)

    for field, values in query.items():
        if not hasattr(values, "__iter__"):
            values = [values]
        # FIXME this is bound to be slow for large libraries
        for value in values:
            if field == "track_no":
                q = _convert_to_int(value)
            else:
                q = value.strip()

            uri_filter = lambda t: q == t.uri
            track_name_filter = lambda t: q == t.name
            album_filter = lambda t: q == getattr(t, "album", Album()).name
            artist_filter = lambda t: filter(lambda a: q == a.name, t.artists)
            albumartist_filter = lambda t: any(
                [q == a.name for a in getattr(t.album, "artists", [])]
            )
            composer_filter = lambda t: any(
                [q == a.name for a in getattr(t, "composers", [])]
            )
            performer_filter = lambda t: any(
                [q == a.name for a in getattr(t, "performers", [])]
            )
            track_no_filter = lambda t: q == t.track_no
            genre_filter = lambda t: t.genre and q == t.genre
            date_filter = lambda t: q == t.date
            comment_filter = lambda t: q == t.comment
            any_filter = lambda t: (
                uri_filter(t)
                or track_name_filter(t)
                or album_filter(t)
                or artist_filter(t)
                or albumartist_filter(t)
                or composer_filter(t)
                or performer_filter(t)
                or track_no_filter(t)
                or genre_filter(t)
                or date_filter(t)
                or comment_filter(t)
            )

            if field == "uri":
                tracks = filter(uri_filter, tracks)
            elif field == "track_name":
                tracks = filter(track_name_filter, tracks)
            elif field == "album":
                tracks = filter(album_filter, tracks)
            elif field == "artist":
                tracks = filter(artist_filter, tracks)
            elif field == "albumartist":
                tracks = filter(albumartist_filter, tracks)
            elif field == "composer":
                tracks = filter(composer_filter, tracks)
            elif field == "performer":
                tracks = filter(performer_filter, tracks)
            elif field == "track_no":
                tracks = filter(track_no_filter, tracks)
            elif field == "genre":
                tracks = filter(genre_filter, tracks)
            elif field == "date":
                tracks = filter(date_filter, tracks)
            elif field == "comment":
                tracks = filter(comment_filter, tracks)
            elif field == "any":
                tracks = filter(any_filter, tracks)
            else:
                raise LookupError("Invalid lookup field: %s" % field)

    # TODO: add local:search:<query>
    return SearchResult(uri="local:search", tracks=tracks)


# Traceback (AttributeError)
INFO     New MPD connection from [::1]:55924
ERROR    Unhandled exception in MpdSession (urn:uuid:127f99a4-9753-4960-9b72-368255948637):
Traceback (most recent call last):
File "/usr/local/lib/python2.7/site-packages/pykka/actor.py", line 200, in _actor_loop
response = self._handle_receive(message)
File "/usr/local/lib/python2.7/site-packages/pykka/actor.py", line 303, in _handle_receive
return self.on_receive(message)
File "/usr/local/lib/python2.7/site-packages/mopidy/utils/network.py", line 366, in on_receive
self.on_line_received(line)
File "/usr/local/lib/python2.7/site-packages/mopidy/mpd/session.py", line 33, in on_line_received
response = self.dispatcher.handle_request(line)
File "/usr/local/lib/python2.7/site-packages/mopidy/mpd/dispatcher.py", line 46, in handle_request
return self._call_next_filter(request, response, filter_chain)
File "/usr/local/lib/python2.7/site-packages/mopidy/mpd/dispatcher.py", line 67, in _call_next_filter
return next_filter(request, response, filter_chain)
File "/usr/local/lib/python2.7/site-packages/mopidy/mpd/dispatcher.py", line 75, in _catch_mpd_ack_errors_filter
return self._call_next_filter(request, response, filter_chain)
File "/usr/local/lib/python2.7/site-packages/mopidy/mpd/dispatcher.py", line 67, in _call_next_filter
return next_filter(request, response, filter_chain)
File "/usr/local/lib/python2.7/site-packages/mopidy/mpd/dispatcher.py", line 85, in _authenticate_filter
return self._call_next_filter(request, response, filter_chain)
File "/usr/local/lib/python2.7/site-packages/mopidy/mpd/dispatcher.py", line 67, in _call_next_filter
return next_filter(request, response, filter_chain)
File "/usr/local/lib/python2.7/site-packages/mopidy/mpd/dispatcher.py", line 104, in _command_list_filter
response = self._call_next_filter(request, response, filter_chain)
File "/usr/local/lib/python2.7/site-packages/mopidy/mpd/dispatcher.py", line 67, in _call_next_filter
return next_filter(request, response, filter_chain)
File "/usr/local/lib/python2.7/site-packages/mopidy/mpd/dispatcher.py", line 133, in _idle_filter
response = self._call_next_filter(request, response, filter_chain)
File "/usr/local/lib/python2.7/site-packages/mopidy/mpd/dispatcher.py", line 67, in _call_next_filter
return next_filter(request, response, filter_chain)
File "/usr/local/lib/python2.7/site-packages/mopidy/mpd/dispatcher.py", line 146, in _add_ok_filter
response = self._call_next_filter(request, response, filter_chain)
File "/usr/local/lib/python2.7/site-packages/mopidy/mpd/dispatcher.py", line 67, in _call_next_filter
return next_filter(request, response, filter_chain)
File "/usr/local/lib/python2.7/site-packages/mopidy/mpd/dispatcher.py", line 158, in _call_handler_filter
response = self._format_response(self._call_handler(request))
File "/usr/local/lib/python2.7/site-packages/mopidy/mpd/dispatcher.py", line 167, in _call_handler
return protocol.commands.call(tokens, context=self.context)
File "/usr/local/lib/python2.7/site-packages/mopidy/mpd/protocol/__init__.py", line 178, in call
return self.handlers[tokens[0]](context, *tokens[1:])
File "/usr/local/lib/python2.7/site-packages/mopidy/mpd/protocol/__init__.py", line 140, in validate
return func(*args, **kwargs)
File "/usr/local/lib/python2.7/site-packages/mopidy/mpd/protocol/music_db.py", line 135, in find
results = context.core.library.find_exact(**query).get()
File "/usr/local/lib/python2.7/site-packages/pykka/future.py", line 299, in get
exec('raise exc_info[0], exc_info[1], exc_info[2]')
File "/usr/local/lib/python2.7/site-packages/pykka/actor.py", line 200, in _actor_loop
response = self._handle_receive(message)
File "/usr/local/lib/python2.7/site-packages/pykka/actor.py", line 294, in _handle_receive
return callee(*message['args'], **message['kwargs'])
File "/usr/local/lib/python2.7/site-packages/mopidy/core/library.py", line 118, in find_exact
return [result for result in pykka.get_all(futures) if result]
File "/usr/local/lib/python2.7/site-packages/pykka/future.py", line 330, in get_all
return [future.get(timeout=timeout) for future in futures]
File "/usr/local/lib/python2.7/site-packages/pykka/future.py", line 299, in get
exec('raise exc_info[0], exc_info[1], exc_info[2]')
File "/usr/local/lib/python2.7/site-packages/pykka/actor.py", line 200, in _actor_loop
response = self._handle_receive(message)
File "/usr/local/lib/python2.7/site-packages/pykka/actor.py", line 294, in _handle_receive
return callee(*message['args'], **message['kwargs'])
File "/usr/local/lib/python2.7/site-packages/mopidy/local/library.py", line 47, in find_exact
return self._library.search(query=query, uris=uris, exact=True)
File "/usr/local/lib/python2.7/site-packages/mopidy/local/json.py", line 162, in search
return search.find_exact(tracks, query=query, uris=uris)
File "/usr/local/lib/python2.7/site-packages/mopidy/local/search.py", line 60, in find_exact
tracks = filter(album_filter, tracks)
File "/usr/local/lib/python2.7/site-packages/mopidy/local/search.py", line 26, in <lambda>
album_filter = lambda t: q == getattr(t, 'album', Album()).name
AttributeError: 'NoneType' object has no attribute 'name'
Traceback (most recent call last):
File "/usr/local/lib/python2.7/site-packages/mopidy/utils/network.py", line 272, in recv_callback
self.actor_ref.tell({'close': True})
File "/usr/local/lib/python2.7/site-packages/pykka/actor.py", line 437, in tell
raise _ActorDeadError('%s not found' % self)
pykka.exceptions.ActorDeadError: MpdSession (urn:uuid:127f99a4-9753-4960-9b72-368255948637) not found

# Fixed code
def find_exact(tracks, query=None, uris=None):
    # TODO Only return results within URI roots given by ``uris``

    if query is None:
        query = {}

    _validate_query(query)

    for field, values in query.items():
        if not hasattr(values, "__iter__"):
            values = [values]
        # FIXME this is bound to be slow for large libraries
        for value in values:
            if field == "track_no":
                q = _convert_to_int(value)
            else:
                q = value.strip()

            uri_filter = lambda t: q == t.uri
            track_name_filter = lambda t: q == t.name
            album_filter = lambda t: q == getattr(
                getattr(t, "album", None), "name", None
            )
            artist_filter = lambda t: filter(lambda a: q == a.name, t.artists)
            albumartist_filter = lambda t: any(
                [q == a.name for a in getattr(t.album, "artists", [])]
            )
            composer_filter = lambda t: any(
                [q == a.name for a in getattr(t, "composers", [])]
            )
            performer_filter = lambda t: any(
                [q == a.name for a in getattr(t, "performers", [])]
            )
            track_no_filter = lambda t: q == t.track_no
            genre_filter = lambda t: t.genre and q == t.genre
            date_filter = lambda t: q == t.date
            comment_filter = lambda t: q == t.comment
            any_filter = lambda t: (
                uri_filter(t)
                or track_name_filter(t)
                or album_filter(t)
                or artist_filter(t)
                or albumartist_filter(t)
                or composer_filter(t)
                or performer_filter(t)
                or track_no_filter(t)
                or genre_filter(t)
                or date_filter(t)
                or comment_filter(t)
            )

            if field == "uri":
                tracks = filter(uri_filter, tracks)
            elif field == "track_name":
                tracks = filter(track_name_filter, tracks)
            elif field == "album":
                tracks = filter(album_filter, tracks)
            elif field == "artist":
                tracks = filter(artist_filter, tracks)
            elif field == "albumartist":
                tracks = filter(albumartist_filter, tracks)
            elif field == "composer":
                tracks = filter(composer_filter, tracks)
            elif field == "performer":
                tracks = filter(performer_filter, tracks)
            elif field == "track_no":
                tracks = filter(track_no_filter, tracks)
            elif field == "genre":
                tracks = filter(genre_filter, tracks)
            elif field == "date":
                tracks = filter(date_filter, tracks)
            elif field == "comment":
                tracks = filter(comment_filter, tracks)
            elif field == "any":
                tracks = filter(any_filter, tracks)
            else:
                raise LookupError("Invalid lookup field: %s" % field)

    # TODO: add local:search:<query>
    return SearchResult(uri="local:search", tracks=tracks)