def test_completion_show(show, rows, quick_complete, completionview, config_stub): """Test that the completion widget is shown at appropriate times. Args: show: The completion show config setting. rows: Each entry represents a completion category with only one item. quick_complete: The completion quick-complete config setting. """ config_stub.data['completion']['show'] = show config_stub.data['completion']['quick-complete'] = quick_complete model = base.BaseCompletionModel() for name in rows: cat = QStandardItem() model.appendRow(cat) cat.appendRow(QStandardItem(name)) filtermodel = sortfilter.CompletionFilterModel(model, parent=completionview) assert not completionview.isVisible() completionview.set_model(filtermodel) assert completionview.isVisible() == (show == 'always' and len(rows) > 0) completionview.completion_item_focus('next') expected = (show != 'never' and len(rows) > 0 and not (quick_complete and len(rows) == 1)) assert completionview.isVisible() == expected completionview.set_model(None) completionview.completion_item_focus('next') assert not completionview.isVisible()
def test_completion_item_focus(which, tree, count, expected, completionview, qtbot): """Test that on_next_prev_item moves the selection properly. Args: tree: Each list represents a completion category, with each string being an item under that category. count: Number of times to go forward (or back if negative). expected: item data that should be selected after going back/forward. """ model = base.BaseCompletionModel() for catdata in tree: cat = QStandardItem() model.appendRow(cat) for name in catdata: cat.appendRow(QStandardItem(name)) filtermodel = sortfilter.CompletionFilterModel(model, parent=completionview) completionview.set_model(filtermodel) if expected is None: for _ in range(count): completionview.completion_item_focus(which) else: with qtbot.waitSignal(completionview.selection_changed): for _ in range(count): completionview.completion_item_focus(which) idx = completionview.selectionModel().currentIndex() assert filtermodel.data(idx) == expected
def test_completion_item_focus(which, tree, expected, completionview, qtbot): """Test that on_next_prev_item moves the selection properly. Args: which: the direction in which to move the selection. tree: Each list represents a completion category, with each string being an item under that category. expected: expected argument from on_selection_changed for each successive movement. None implies no signal should be emitted. """ model = base.BaseCompletionModel() for catdata in tree: cat = QStandardItem() model.appendRow(cat) for name in catdata: cat.appendRow(QStandardItem(name)) filtermodel = sortfilter.CompletionFilterModel(model, parent=completionview) completionview.set_model(filtermodel) for entry in expected: if entry is None: with qtbot.assertNotEmitted(completionview.selection_changed): completionview.completion_item_focus(which) else: with qtbot.waitSignal(completionview.selection_changed) as sig: completionview.completion_item_focus(which) assert sig.args == [entry]
def _get_completion_model(self, completion, parts, cursor_part): """Get a completion model based on an enum member. Args: completion: A usertypes.Completion member. parts: The parts currently in the commandline. cursor_part: The part the cursor is in. Return: A completion model or None. """ if completion == usertypes.Completion.option: section = parts[cursor_part - 1] model = instances.get(completion).get(section) elif completion == usertypes.Completion.value: section = parts[cursor_part - 2] option = parts[cursor_part - 1] try: model = instances.get(completion)[section][option] except KeyError: # No completion model for this section/option. model = None else: model = instances.get(completion) if model is None: return None else: return sortfilter.CompletionFilterModel(source=model, parent=self)
def _get_completion_model(self, completion, pos_args): """Get a completion model based on an enum member. Args: completion: A usertypes.Completion member. pos_args: The positional args entered before the cursor. Return: A completion model or None. """ if completion == usertypes.Completion.option: section = pos_args[0] model = instances.get(completion).get(section) elif completion == usertypes.Completion.value: section = pos_args[0] option = pos_args[1] try: model = instances.get(completion)[section][option] except KeyError: # No completion model for this section/option. model = None else: model = instances.get(completion) if model is None: return None else: return sortfilter.CompletionFilterModel(source=model, parent=self)
def test_set_pattern(pattern, dumb_sort, filter_cols, before, after): """Validate the filtering and sorting results of set_pattern.""" model = _create_model(before) model.DUMB_SORT = dumb_sort model.columns_to_filter = filter_cols filter_model = sortfilter.CompletionFilterModel(model) filter_model.set_pattern(pattern) actual = _extract_model_data(filter_model) assert actual == after
def bench(): model = urlmodel.UrlCompletionModel() filtermodel = sortfilter.CompletionFilterModel(model) filtermodel.set_pattern('') filtermodel.set_pattern('e') filtermodel.set_pattern('ex') filtermodel.set_pattern('ex ') filtermodel.set_pattern('ex 1') filtermodel.set_pattern('ex 12') filtermodel.set_pattern('ex 123')
def test_set_model(completionview): """Ensure set_model actually sets the model and expands all categories.""" model = base.BaseCompletionModel() filtermodel = sortfilter.CompletionFilterModel(model) for i in range(3): model.appendRow(QStandardItem(str(i))) completionview.set_model(filtermodel) assert completionview.model() is filtermodel for i in range(model.rowCount()): assert completionview.isExpanded(filtermodel.index(i, 0))
def test_filter_accepts_row(pattern, data, expected): source_model = base.BaseCompletionModel() cat = source_model.new_category('test') source_model.new_item(cat, data) filter_model = sortfilter.CompletionFilterModel(source_model) filter_model.set_pattern(pattern) assert filter_model.rowCount() == 1 # "test" category idx = filter_model.index(0, 0) assert idx.isValid() row_count = filter_model.rowCount(idx) assert row_count == (1 if expected else 0)
def test_first_last_item(tree, first, last): """Test that first() and last() return indexes to the first and last items. Args: tree: Each list represents a completion category, with each string being an item under that category. first: text of the first item last: text of the last item """ model = _create_model(tree) filter_model = sortfilter.CompletionFilterModel(model) assert filter_model.data(filter_model.first_item()) == first assert filter_model.data(filter_model.last_item()) == last
def test_completion_item_focus_no_model(which, completionview, qtbot): """Test that selectionChanged is not fired when the model is None. Validates #1812: help completion repeatedly completes """ with qtbot.assertNotEmitted(completionview.selection_changed): completionview.completion_item_focus(which) model = base.BaseCompletionModel() filtermodel = sortfilter.CompletionFilterModel(model, parent=completionview) completionview.set_model(filtermodel) completionview.set_model(None) with qtbot.assertNotEmitted(completionview.selection_changed): completionview.completion_item_focus(which)
def _get_new_completion(self, parts, cursor_part): """Get a new completion. Args: parts: The command chunks to get a completion for. cursor_part: The part the cursor is over currently. Return: A completion model. """ try: if parts[cursor_part].startswith('-'): # cursor on a flag return except IndexError: pass log.completion.debug("Before filtering flags: parts {}, cursor_part " "{}".format(parts, cursor_part)) parts, cursor_part = self._filter_cmdline_parts(parts, cursor_part) log.completion.debug("After filtering flags: parts {}, cursor_part " "{}".format(parts, cursor_part)) if not parts: return None if cursor_part == 0: # '|' or 'set|' model = instances.get(usertypes.Completion.command) return sortfilter.CompletionFilterModel(source=model, parent=self) # delegate completion to command try: completions = cmdutils.cmd_dict[parts[0]].completion except KeyError: # entering an unknown command return None if completions is None: # command without any available completions return None dbg_completions = [c.name for c in completions] try: idx = cursor_part - 1 completion = completions[idx] except IndexError: # More arguments than completions log.completion.debug("completions: {}".format( ', '.join(dbg_completions))) return None dbg_completions[idx] = '*' + dbg_completions[idx] + '*' log.completion.debug("completions: {}".format( ', '.join(dbg_completions))) model = self._get_completion_model(completion, parts, cursor_part) return model
def test_set_source_model(): """Ensure setSourceModel sets source_model and clears the pattern.""" model1 = base.BaseCompletionModel() model2 = base.BaseCompletionModel() filter_model = sortfilter.CompletionFilterModel(model1) filter_model.set_pattern('foo') # sourceModel() is cached as srcmodel, so make sure both match assert filter_model.srcmodel is model1 assert filter_model.sourceModel() is model1 assert filter_model.pattern == 'foo' filter_model.setSourceModel(model2) assert filter_model.srcmodel is model2 assert filter_model.sourceModel() is model2 assert not filter_model.pattern
def test_sort(): """Ensure that a sort argument passed to sort overrides DUMB_SORT. While test_set_pattern above covers most of the sorting logic, this particular case is easier to test separately. """ model = _create_model([[('B', '', '', 1), ('C', '', '', 2), ('A', '', '', 0)]]) filter_model = sortfilter.CompletionFilterModel(model) filter_model.sort(0, Qt.AscendingOrder) actual = _extract_model_data(filter_model) assert actual == [[('A', '', ''), ('B', '', ''), ('C', '', '')]] filter_model.sort(0, Qt.DescendingOrder) actual = _extract_model_data(filter_model) assert actual == [[('C', '', ''), ('B', '', ''), ('A', '', '')]]
def _get_new_completion(self, parts, cursor_part): """Get a new completion. Args: parts: The command chunks to get a completion for. cursor_part: The part the cursor is over currently. Return: A completion model. """ try: if parts[cursor_part].startswith('-'): # cursor on a flag return except IndexError: pass log.completion.debug("Before filtering flags: parts {}, cursor_part " "{}".format(parts, cursor_part)) parts, cursor_part = self._filter_cmdline_parts(parts, cursor_part) log.completion.debug("After filtering flags: parts {}, cursor_part " "{}".format(parts, cursor_part)) if not parts: return None if cursor_part == 0: # '|' or 'set|' model = instances.get(usertypes.Completion.command) return sortfilter.CompletionFilterModel(source=model, parent=self) # delegate completion to command try: cmd = cmdutils.cmd_dict[parts[0]] except KeyError: # entering an unknown command return None try: idx = cursor_part - 1 completion = cmd.get_pos_arg_info(idx).completion except IndexError: # user provided more positional arguments than the command takes return None if completion is None: return None model = self._get_completion_model(completion, parts, cursor_part) return model
def _get_new_completion(self, before_cursor, under_cursor): """Get a new completion. Args: before_cursor: The command chunks before the cursor. under_cursor: The command chunk under the cursor. Return: A completion model. """ if '--' in before_cursor or under_cursor.startswith('-'): # cursor on a flag or after an explicit split (--) return None log.completion.debug("Before removing flags: {}".format(before_cursor)) before_cursor = [x for x in before_cursor if not x.startswith('-')] log.completion.debug("After removing flags: {}".format(before_cursor)) if not before_cursor: # '|' or 'set|' model = instances.get(usertypes.Completion.command) return sortfilter.CompletionFilterModel(source=model, parent=self) try: cmd = cmdutils.cmd_dict[before_cursor[0]] except KeyError: log.completion.debug( "No completion for unknown command: {}".format( before_cursor[0])) return None argpos = len(before_cursor) - 1 try: completion = cmd.get_pos_arg_info(argpos).completion except IndexError: log.completion.debug("No completion in position {}".format(argpos)) return None if completion is None: return None model = self._get_completion_model(completion, before_cursor[1:]) return model
def test_set_pattern(completionview): model = sortfilter.CompletionFilterModel(base.BaseCompletionModel()) model.set_pattern = unittest.mock.Mock() completionview.set_model(model, 'foo') model.set_pattern.assert_called_with('foo')
def test_count(tree, expected): model = _create_model(tree) filter_model = sortfilter.CompletionFilterModel(model) assert filter_model.count() == expected