# Buggy code
def searx_bang(full_query):
    """check if the searchQuery contain a bang, and create fitting autocompleter results"""
    # check if there is a query which can be parsed
    if len(full_query.getSearchQuery()) == 0:
        return []

    results = []

    # check if current query stats with !bang
    first_char = full_query.getSearchQuery()[0]
    if first_char == "!" or first_char == "?":
        if len(full_query.getSearchQuery()) == 1:
            # show some example queries
            # TODO, check if engine is not avaliable
            results.append(first_char + "images")
            results.append(first_char + "wikipedia")
            results.append(first_char + "osm")
        else:
            engine_query = full_query.getSearchQuery()[1:]

            # check if query starts with categorie name
            for categorie in categories:
                if categorie.startswith(engine_query):
                    results.append(
                        first_char + "{categorie}".format(categorie=categorie)
                    )

            # check if query starts with engine name
            for engine in engines:
                if engine.startswith(engine_query.replace("_", " ")):
                    results.append(
                        first_char + "{engine}".format(engine=engine.replace(" ", "_"))
                    )

            # check if query starts with engine shortcut
            for engine_shortcut in engine_shortcuts:
                if engine_shortcut.startswith(engine_query):
                    results.append(
                        first_char
                        + "{engine_shortcut}".format(engine_shortcut=engine_shortcut)
                    )

    # check if current query stats with :bang
    elif first_char == ":":
        if len(full_query.getSearchQuery()) == 1:
            # show some example queries
            results.append(":en")
            results.append(":en_us")
            results.append(":english")
            results.append(":united_kingdom")
        else:
            engine_query = full_query.getSearchQuery()[1:]

            for lc in language_codes:
                lang_id, lang_name, country, english_name = map(str.lower, lc)

                # check if query starts with language-id
                if lang_id.startswith(engine_query):
                    if len(engine_query) <= 2:
                        results.append(
                            ":{lang_id}".format(lang_id=lang_id.split("-")[0])
                        )
                    else:
                        results.append(":{lang_id}".format(lang_id=lang_id))

                # check if query starts with language name
                if lang_name.startswith(engine_query) or english_name.startswith(
                    engine_query
                ):
                    results.append(":{lang_name}".format(lang_name=lang_name))

                # check if query starts with country
                if country.startswith(engine_query.replace("_", " ")):
                    results.append(
                        ":{country}".format(country=country.replace(" ", "_"))
                    )

    # remove duplicates
    result_set = set(results)

    # remove results which are already contained in the query
    for query_part in full_query.query_parts:
        if query_part in result_set:
            result_set.remove(query_part)

    # convert result_set back to list
    return list(result_set)


# Traceback (TypeError)
INFO:werkzeug:127.0.0.1 - - [03/Jan/2017 12:02:01] "GET /autocompleter?q=%3Ae HTTP/1.1" 500 -
Traceback (most recent call last):
File "/home/alexandre/code/searx/query2/ve/lib/python2.7/site-packages/flask/app.py", line 1994, in __call__
return self.wsgi_app(environ, start_response)
File "/home/alexandre/code/searx/query2/searx/searx/webapp.py", line 818, in __call__
return self.app(environ, start_response)
File "/home/alexandre/code/searx/query2/ve/lib/python2.7/site-packages/werkzeug/contrib/fixers.py", line 152, in __call__
return self.app(environ, start_response)
File "/home/alexandre/code/searx/query2/ve/lib/python2.7/site-packages/flask/app.py", line 1985, in wsgi_app
response = self.handle_exception(e)
File "/home/alexandre/code/searx/query2/ve/lib/python2.7/site-packages/flask/app.py", line 1540, in handle_exception
reraise(exc_type, exc_value, tb)
File "/home/alexandre/code/searx/query2/ve/lib/python2.7/site-packages/flask/app.py", line 1982, in wsgi_app
response = self.full_dispatch_request()
File "/home/alexandre/code/searx/query2/ve/lib/python2.7/site-packages/flask/app.py", line 1614, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/home/alexandre/code/searx/query2/ve/lib/python2.7/site-packages/flask/app.py", line 1517, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/home/alexandre/code/searx/query2/ve/lib/python2.7/site-packages/flask/app.py", line 1612, in full_dispatch_request
rv = self.dispatch_request()
File "/home/alexandre/code/searx/query2/ve/lib/python2.7/site-packages/flask/app.py", line 1598, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/home/alexandre/code/searx/query2/searx/searx/webapp.py", line 554, in autocompleter
raw_results = searx_bang(raw_text_query)
File "/home/alexandre/code/searx/query2/searx/searx/autocomplete.py", line 84, in searx_bang
lang_id, lang_name, country, english_name = map(str.lower, lc)
TypeError: descriptor 'lower' requires a 'str' object but received a 'unicode'

# Fixed code
def searx_bang(full_query):
    """check if the searchQuery contain a bang, and create fitting autocompleter results"""
    # check if there is a query which can be parsed
    if len(full_query.getSearchQuery()) == 0:
        return []

    results = []

    # check if current query stats with !bang
    first_char = full_query.getSearchQuery()[0]
    if first_char == "!" or first_char == "?":
        if len(full_query.getSearchQuery()) == 1:
            # show some example queries
            # TODO, check if engine is not avaliable
            results.append(first_char + "images")
            results.append(first_char + "wikipedia")
            results.append(first_char + "osm")
        else:
            engine_query = full_query.getSearchQuery()[1:]

            # check if query starts with categorie name
            for categorie in categories:
                if categorie.startswith(engine_query):
                    results.append(
                        first_char + "{categorie}".format(categorie=categorie)
                    )

            # check if query starts with engine name
            for engine in engines:
                if engine.startswith(engine_query.replace("_", " ")):
                    results.append(
                        first_char + "{engine}".format(engine=engine.replace(" ", "_"))
                    )

            # check if query starts with engine shortcut
            for engine_shortcut in engine_shortcuts:
                if engine_shortcut.startswith(engine_query):
                    results.append(
                        first_char
                        + "{engine_shortcut}".format(engine_shortcut=engine_shortcut)
                    )

    # check if current query stats with :bang
    elif first_char == ":":
        if len(full_query.getSearchQuery()) == 1:
            # show some example queries
            results.append(":en")
            results.append(":en_us")
            results.append(":english")
            results.append(":united_kingdom")
        else:
            engine_query = full_query.getSearchQuery()[1:]

            for lc in language_codes:
                lang_id, lang_name, country, english_name = map(unicode.lower, lc)

                # check if query starts with language-id
                if lang_id.startswith(engine_query):
                    if len(engine_query) <= 2:
                        results.append(
                            ":{lang_id}".format(lang_id=lang_id.split("-")[0])
                        )
                    else:
                        results.append(":{lang_id}".format(lang_id=lang_id))

                # check if query starts with language name
                if lang_name.startswith(engine_query) or english_name.startswith(
                    engine_query
                ):
                    results.append(":{lang_name}".format(lang_name=lang_name))

                # check if query starts with country
                if country.startswith(engine_query.replace("_", " ")):
                    results.append(
                        ":{country}".format(country=country.replace(" ", "_"))
                    )

    # remove duplicates
    result_set = set(results)

    # remove results which are already contained in the query
    for query_part in full_query.query_parts:
        if query_part in result_set:
            result_set.remove(query_part)

    # convert result_set back to list
    return list(result_set)