# Buggy code
def set_pattern(self, pattern):
    """Set the pattern used to filter results.

    Args:
        pattern: string pattern to filter by.
    """
    # escape to treat a user input % or _ as a literal, not a wildcard
    pattern = pattern.replace("%", "\\%")
    pattern = pattern.replace("_", "\\_")
    words = ["%{}%".format(w) for w in pattern.split(" ")]

    # build a where clause to match all of the words in any order
    # given the search term "a b", the WHERE clause would be:
    # ((url || title) LIKE '%a%') AND ((url || title) LIKE '%b%')
    where_clause = " AND ".join(
        "(url || title) LIKE :{} escape '\\'".format(i) for i in range(len(words))
    )

    # replace ' in timestamp-format to avoid breaking the query
    timestamp_format = config.val.completion.timestamp_format
    timefmt = "strftime('{}', last_atime, 'unixepoch', 'localtime')".format(
        timestamp_format.replace("'", "`")
    )

    if not self._query or len(words) != len(self._query.boundValues()):
        # if the number of words changed, we need to generate a new query
        # otherwise, we can reuse the prepared query for performance
        self._query = sql.Query(
            " ".join(
                [
                    "SELECT url, title, {}".format(timefmt),
                    "FROM CompletionHistory",
                    # the incoming pattern will have literal % and _ escaped
                    # we need to tell sql to treat '\' as an escape character
                    "WHERE ({})".format(where_clause),
                    self._atime_expr(),
                    "ORDER BY last_atime DESC",
                ]
            ),
            forward_only=False,
        )

    with debug.log_time("sql", "Running completion query"):
        self._query.run(**{str(i): w for i, w in enumerate(words)})
    self.setQuery(self._query)


# Traceback (AttributeError)
17:26:29 ERROR    misc       crashsignal:exception_hook:216 Uncaught exception
Traceback (most recent call last):
File "/home/florian/proj/qutebrowser/git/qutebrowser/completion/completer.py", line 260, in _update_completion
completion.set_pattern(pattern)
File "/home/florian/proj/qutebrowser/git/qutebrowser/completion/completionwidget.py", line 320, in set_pattern
self.model().set_pattern(pattern)
File "/home/florian/proj/qutebrowser/git/qutebrowser/completion/models/completionmodel.py", line 185, in set_pattern
cat.set_pattern(pattern)
File "/home/florian/proj/qutebrowser/git/qutebrowser/completion/models/histcategory.py", line 85, in set_pattern
.format(timestamp_format.replace("'", "`")))
AttributeError: 'NoneType' object has no attribute 'replace'

# Fixed code
def set_pattern(self, pattern):
    """Set the pattern used to filter results.

    Args:
        pattern: string pattern to filter by.
    """
    # escape to treat a user input % or _ as a literal, not a wildcard
    pattern = pattern.replace("%", "\\%")
    pattern = pattern.replace("_", "\\_")
    words = ["%{}%".format(w) for w in pattern.split(" ")]

    # build a where clause to match all of the words in any order
    # given the search term "a b", the WHERE clause would be:
    # ((url || title) LIKE '%a%') AND ((url || title) LIKE '%b%')
    where_clause = " AND ".join(
        "(url || title) LIKE :{} escape '\\'".format(i) for i in range(len(words))
    )

    # replace ' in timestamp-format to avoid breaking the query
    timestamp_format = config.val.completion.timestamp_format or ""
    timefmt = "strftime('{}', last_atime, 'unixepoch', 'localtime')".format(
        timestamp_format.replace("'", "`")
    )

    if not self._query or len(words) != len(self._query.boundValues()):
        # if the number of words changed, we need to generate a new query
        # otherwise, we can reuse the prepared query for performance
        self._query = sql.Query(
            " ".join(
                [
                    "SELECT url, title, {}".format(timefmt),
                    "FROM CompletionHistory",
                    # the incoming pattern will have literal % and _ escaped
                    # we need to tell sql to treat '\' as an escape character
                    "WHERE ({})".format(where_clause),
                    self._atime_expr(),
                    "ORDER BY last_atime DESC",
                ]
            ),
            forward_only=False,
        )

    with debug.log_time("sql", "Running completion query"):
        self._query.run(**{str(i): w for i, w in enumerate(words)})
    self.setQuery(self._query)