def _update_completion(self): """Check if completions are available and activate them.""" completion = self.parent() if self._cmd.prefix() != ':': # This is a search or gibberish, so we don't need to complete # anything (yet) # FIXME complete searches # https://github.com/qutebrowser/qutebrowser/issues/32 completion.set_model(None) self._last_before_cursor = None return before_cursor, pattern, after_cursor = self._partition() log.completion.debug("Updating completion: {} {} {}".format( before_cursor, pattern, after_cursor)) pattern = pattern.strip("'\"") func = self._get_new_completion(before_cursor, pattern) if func is None: log.completion.debug('Clearing completion') completion.set_model(None) self._last_before_cursor = None return if before_cursor == self._last_before_cursor: # If the part before the cursor didn't change since the last # completion, we only need to filter existing matches without # having to regenerate completion results. completion.set_pattern(pattern) return self._last_before_cursor = before_cursor args = (x for x in before_cursor[1:] if not x.startswith('-')) cur_tab = objreg.get('tab', scope='tab', window=self._win_id, tab='current') with debug.log_time(log.completion, 'Starting {} completion'.format(func.__name__)): info = CompletionInfo(config=config.instance, keyconf=config.key_instance, win_id=self._win_id, cur_tab=cur_tab) model = func(*args, info=info) with debug.log_time(log.completion, 'Set completion model'): completion.set_model(model) completion.set_pattern(pattern)
def _init_url_completion(): """Initialize the URL completion model.""" log.completion.debug("Initializing URL completion.") with debug.log_time(log.completion, 'URL completion init'): model = _init_model(urlmodel.UrlCompletionModel, dumb_sort=Qt.DescendingOrder) _instances[usertypes.Completion.url] = model
def action(): with debug.log_time(log.init, 'Import old history file to sqlite'): try: self._read(path) except ValueError as ex: message.error('Failed to import history: {}'.format(ex)) else: self._write_backup(path)
def _update_completion(self): """Check if completions are available and activate them.""" if self._ignore_change: log.completion.debug("Ignoring completion update because " "ignore_change is True.") self._ignore_change = False return completion = self.parent() if self._cmd.prefix() != ':': # This is a search or gibberish, so we don't need to complete # anything (yet) # FIXME complete searches # https://github.com/qutebrowser/qutebrowser/issues/32 completion.set_model(None) self._last_completion_func = None return before_cursor, pattern, after_cursor = self._partition() log.completion.debug("Updating completion: {} {} {}".format( before_cursor, pattern, after_cursor)) pattern = pattern.strip("'\"") func = self._get_new_completion(before_cursor, pattern) if func is None: log.completion.debug('Clearing completion') completion.set_model(None) self._last_completion_func = None return if func != self._last_completion_func: self._last_completion_func = func args = (x for x in before_cursor[1:] if not x.startswith('-')) with debug.log_time(log.completion, 'Starting {} completion'.format( func.__name__)): info = CompletionInfo(config=config.instance, keyconf=config.key_instance) model = func(*args, info=info) with debug.log_time(log.completion, 'Set completion model'): completion.set_model(model) completion.set_pattern(pattern)
def _update_completion(self): """Check if completions are available and activate them.""" if self._ignore_change: log.completion.debug("Ignoring completion update because " "ignore_change is True.") self._ignore_change = False return completion = self.parent() if self._cmd.prefix() != ':': # This is a search or gibberish, so we don't need to complete # anything (yet) # FIXME complete searches # https://github.com/qutebrowser/qutebrowser/issues/32 completion.set_model(None) self._last_completion_func = None return before_cursor, pattern, after_cursor = self._partition() log.completion.debug("Updating completion: {} {} {}".format( before_cursor, pattern, after_cursor)) pattern = pattern.strip("'\"") func = self._get_new_completion(before_cursor, pattern) if func is None: log.completion.debug('Clearing completion') completion.set_model(None) self._last_completion_func = None return if func != self._last_completion_func: self._last_completion_func = func args = (x for x in before_cursor[1:] if not x.startswith('-')) with debug.log_time(log.completion, 'Starting {} completion'.format(func.__name__)): info = CompletionInfo(config=config.instance, keyconf=config.key_instance) model = func(*args, info=info) with debug.log_time(log.completion, 'Set completion model'): completion.set_model(model) completion.set_pattern(pattern)
def test_logger(self, caplog): """Test with an explicit logger instead of a name.""" logger_name = 'qt-tests' with caplog.at_level(logging.DEBUG, logger_name): with debug.log_time(logging.getLogger(logger_name)): pass assert len(caplog.records) == 1
def removeRows(self, row, _count, _parent=None): """Override QAbstractItemModel::removeRows to re-run sql query.""" # re-run query to reload updated table with debug.log_time('sql', 'Re-running completion query post-delete'): self._query.run() self.setQuery(self._query.query) while self.rowCount() < row: self.fetchMore() return True
def removeRows(self, row, _count, _parent=None): """Override QAbstractItemModel::removeRows to re-run sql query.""" # re-run query to reload updated table with debug.log_time('sql', 'Re-running completion query post-delete'): self._query.run() self.setQuery(self._query) while self.rowCount() < row: self.fetchMore() return True
def set_pattern(self, pattern): """Set the pattern on the underlying model.""" if not self.model(): return self.pattern = pattern with debug.log_time(log.completion, 'Set pattern {}'.format(pattern)): self.model().set_pattern(pattern) self.selectionModel().clear() self._maybe_update_geometry() self._maybe_show()
def action(): with debug.log_time(log.init, 'Import old history file to sqlite'): try: self._read(path) except ValueError as ex: message.error('Failed to import history: {}'.format(ex)) else: bakpath = path + '.bak' message.info('History import complete. Moving {} to {}' .format(path, bakpath)) os.rename(path, bakpath)
def historyContains(self, url_string): """Called by WebKit to determine if a URL is contained in the history. Args: url_string: The URL (as string) to check for. Return: True if the url is in the history, False otherwise. """ with debug.log_time('sql', 'historyContains'): return url_string in self._history
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 LIKE '%a%' OR title LIKE '%a%') AND # (url LIKE '%b%' OR title LIKE '%b%') where_clause = ' AND '.join( "(url LIKE :{val} escape '\\' OR title LIKE :{val} escape '\\')" .format(val=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("'", "`"))) try: if (not self._query or len(words) != len(self._query.bound_values())): # 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)}) except sql.KnownError as e: # Sometimes, the query we built up was invalid, for example, # due to a large amount of words. # Also catches failures in the DB we can't solve. message.error("Error with SQL query: {}".format(e.text())) return self.setQuery(self._query.query)
def _init_late_modules(args): """Initialize modules which can be inited after the window is shown.""" log.init.debug("Reading web history...") reader = objreg.get("web-history").async_read() with debug.log_time(log.init, "Reading history"): while True: QApplication.processEvents() try: next(reader) except StopIteration: break except (OSError, UnicodeDecodeError) as e: error.handle_fatal_exc(e, args, "Error while initializing!", pre_text="Error while initializing") sys.exit(usertypes.Exit.err_init)
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('_', '\\_') # treat spaces as wildcards to match any of the typed words pattern = re.sub(r' +', '%', pattern) pattern = '%{}%'.format(pattern) with debug.log_time('sql', 'Running completion query'): self._query.run(pat=pattern) self.setQuery(self._query)
def test_duration(self, caplog): logger_name = 'qt-tests' with caplog.at_level(logging.DEBUG, logger_name): with debug.log_time(logger_name, action='foobar'): time.sleep(0.1) assert len(caplog.records) == 1 pattern = re.compile(r'^Foobar took ([\d.]*) seconds\.$') match = pattern.match(caplog.records[0].msg) assert match duration = float(match.group(1)) assert 0 < duration < 30
def _init_late_modules(args): """Initialize modules which can be inited after the window is shown.""" log.init.debug("Reading web history...") reader = objreg.get('web-history').async_read() with debug.log_time(log.init, 'Reading history'): while True: QApplication.processEvents() try: next(reader) except StopIteration: break except (OSError, UnicodeDecodeError) as e: error.handle_fatal_exc(e, args, "Error while initializing!", pre_text="Error while initializing") sys.exit(usertypes.Exit.err_init)
def set_pattern(self, pattern: str) -> None: """Set the pattern on the underlying model.""" if not self.model(): return if self.pattern == pattern: # no changes, abort log.completion.debug( "Ignoring pattern set request as pattern has not changed.") return self.pattern = pattern with debug.log_time(log.completion, 'Set pattern {}'.format(pattern)): self.model().set_pattern(pattern) self.selectionModel().clear() self._maybe_update_geometry() self._maybe_show()
def set_pattern(self, val): """Setter for pattern. Invalidates the filter and re-sorts the model. Args: val: The value to set. """ with debug.log_time(log.completion, 'Setting filter pattern'): self.pattern = val val = re.escape(val) val = val.replace(r'\ ', r'.*') self.pattern_re = re.compile(val, re.IGNORECASE) self.invalidate() sortcol = 0 self.sort(sortcol)
def test_duration(self, caplog): logger_name = "qt-tests" with caplog.atLevel(logging.DEBUG, logger_name): with debug.log_time(logger_name, action="foobar"): time.sleep(0.1) records = caplog.records() assert len(records) == 1 pattern = re.compile(r"^Foobar took ([\d.]*) seconds\.$") match = pattern.match(records[0].msg) assert match duration = float(match.group(1)) assert 0 < duration < 30
def set_pattern(self, val): """Setter for pattern. Invalidates the filter and re-sorts the model. Args: val: The value to set. """ with debug.log_time(log.completion, "Setting filter pattern"): # empty value clears cache (not necessary for correctness, but # helps with keeping memory requirements relatively low) if not val: self.srcmodel.filtered_out_cache = {} self.pattern = val self.invalidate() sortcol = 0 self.sort(sortcol)
def test_log_time(caplog): """Test if log_time logs properly.""" logger_name = 'qt-tests' with caplog.atLevel(logging.DEBUG, logger=logger_name): with debug.log_time(logging.getLogger(logger_name), action='foobar'): time.sleep(0.1) records = caplog.records() assert len(records) == 1 pattern = re.compile(r'^Foobar took ([\d.]*) seconds\.$') match = pattern.match(records[0].msg) assert match duration = float(match.group(1)) assert 0 < duration < 1
def test_log_time(caplog): """Test if log_time logs properly.""" logger_name = 'qt-tests' with caplog.atLevel(logging.DEBUG, logger=logger_name): with debug.log_time(logging.getLogger(logger_name), action='foobar'): time.sleep(0.1) records = caplog.records() assert len(records) == 1 pattern = re.compile(r'^Foobar took ([\d.]*) seconds\.$') match = pattern.match(records[0].msg) assert match duration = float(match.group(1)) assert 0.08 <= duration <= 0.12
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.bound_values()): # 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.query)
def set_pattern(self, val): """Setter for pattern. Invalidates the filter and re-sorts the model. If the current completion model overrides sort(), it is used. If not, the default implementation in QCompletionFilterModel is called. Args: val: The value to set. """ with debug.log_time(log.completion, 'Setting filter pattern'): self.pattern = val self.invalidateFilter() sortcol = 0 try: self.srcmodel.sort(sortcol) except NotImplementedError: self.sort(sortcol) self.invalidate()
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.bound_values()): # 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.query)
def set_pattern(self, val): """Setter for pattern. Invalidates the filter and re-sorts the model. If the current completion model overrides sort(), it is used. If not, the default implementation in QCompletionFilterModel is called. Args: val: The value to set. """ with debug.log_time(log.completion, 'Setting filter pattern'): self.pattern = val val = re.escape(val) val = val.replace(r'\ ', r'.*') self.pattern_re = re.compile(val, re.IGNORECASE) self.invalidateFilter() sortcol = 0 if hasattr(self.srcmodel, 'sort'): self.srcmodel.sort(sortcol) else: self.sort(sortcol) self.invalidate()
def _init_tab_completion(): """Initialize the tab completion model.""" log.completion.debug("Initializing tab completion.") with debug.log_time(log.completion, 'tab completion init'): model = miscmodels.TabCompletionModel() _instances[usertypes.Completion.tab] = model
def _init_url_completion(): """Initialize the URL completion model.""" log.completion.debug("Initializing URL completion.") with debug.log_time(log.completion, 'URL completion init'): model = urlmodel.UrlCompletionModel() _instances[usertypes.Completion.url] = model
def _init_modules(*, args): """Initialize all 'modules' which need to be initialized. Args: args: The argparse namespace. """ log.init.debug("Initializing logging from config...") log.init_from_config(config.val) config.instance.changed.connect(_on_config_changed) log.init.debug("Initializing save manager...") save_manager = savemanager.SaveManager(objects.qapp) objreg.register('save-manager', save_manager) quitter.instance.shutting_down.connect(save_manager.shutdown) configinit.late_init(save_manager) log.init.debug("Checking backend requirements...") backendproblem.init(args=args, save_manager=save_manager) log.init.debug("Initializing prompts...") prompt.init() log.init.debug("Initializing network...") networkmanager.init() log.init.debug("Initializing proxy...") proxy.init() quitter.instance.shutting_down.connect(proxy.shutdown) log.init.debug("Initializing downloads...") downloads.init() quitter.instance.shutting_down.connect(downloads.shutdown) with debug.log_time("init", "Initializing SQL/history"): try: log.init.debug("Initializing web history...") history.init(db_path=pathlib.Path(standarddir.data()) / 'history.sqlite', parent=objects.qapp) except sql.KnownError as e: error.handle_fatal_exc(e, 'Error initializing SQL', pre_text='Error initializing SQL', no_err_windows=args.no_err_windows) sys.exit(usertypes.Exit.err_init) log.init.debug("Initializing command history...") cmdhistory.init() log.init.debug("Initializing websettings...") websettings.init(args) quitter.instance.shutting_down.connect(websettings.shutdown) log.init.debug("Initializing sessions...") sessions.init(objects.qapp) if not args.no_err_windows: crashsignal.crash_handler.display_faulthandler() log.init.debug("Initializing quickmarks...") quickmark_manager = urlmarks.QuickmarkManager(objects.qapp) objreg.register('quickmark-manager', quickmark_manager) log.init.debug("Initializing bookmarks...") bookmark_manager = urlmarks.BookmarkManager(objects.qapp) objreg.register('bookmark-manager', bookmark_manager) log.init.debug("Initializing cookies...") cookies.init(objects.qapp) log.init.debug("Initializing cache...") cache.init(objects.qapp) log.init.debug("Initializing downloads...") qtnetworkdownloads.init() log.init.debug("Initializing Greasemonkey...") greasemonkey.init() log.init.debug("Misc initialization...") macros.init() windowundo.init()