mirror of
https://github.com/nvbn/thefuck.git
synced 2025-02-20 20:09:07 +00:00
Remove obscure SortedCorrectedCommandsSequence
This commit is contained in:
parent
1fb6dd925b
commit
bf80d97062
@ -3,7 +3,8 @@ from pathlib import PosixPath, Path
|
||||
from mock import Mock
|
||||
from thefuck import corrector, conf
|
||||
from tests.utils import Rule, Command, CorrectedCommand
|
||||
from thefuck.corrector import make_corrected_commands, get_corrected_commands, is_rule_enabled
|
||||
from thefuck.corrector import make_corrected_commands, get_corrected_commands,\
|
||||
is_rule_enabled, organize_commands
|
||||
|
||||
|
||||
def test_load_rule(mocker):
|
||||
@ -111,3 +112,13 @@ def test_get_corrected_commands(mocker):
|
||||
mocker.patch('thefuck.corrector.get_rules', return_value=rules)
|
||||
assert [cmd.script for cmd in get_corrected_commands(command)] \
|
||||
== ['test!', 'test@', 'test;']
|
||||
|
||||
|
||||
def test_organize_commands():
|
||||
"""Ensures that the function removes duplicates and sorts commands."""
|
||||
commands = [CorrectedCommand('ls'), CorrectedCommand('ls -la', priority=9000),
|
||||
CorrectedCommand('ls -lh', priority=100),
|
||||
CorrectedCommand('ls -lh', priority=9999)]
|
||||
assert list(organize_commands(iter(commands))) \
|
||||
== [CorrectedCommand('ls'), CorrectedCommand('ls -lh', priority=100),
|
||||
CorrectedCommand('ls -la', priority=9000)]
|
||||
|
@ -1,37 +1,6 @@
|
||||
from thefuck.types import SortedCorrectedCommandsSequence
|
||||
from tests.utils import CorrectedCommand
|
||||
|
||||
|
||||
class TestSortedCorrectedCommandsSequence(object):
|
||||
def test_realises_generator_only_on_demand(self, settings):
|
||||
should_realise = False
|
||||
|
||||
def gen():
|
||||
yield CorrectedCommand('git commit')
|
||||
yield CorrectedCommand('git branch', priority=200)
|
||||
assert should_realise
|
||||
yield CorrectedCommand('git checkout', priority=100)
|
||||
|
||||
commands = SortedCorrectedCommandsSequence(gen())
|
||||
assert commands[0] == CorrectedCommand('git commit')
|
||||
should_realise = True
|
||||
assert commands[1] == CorrectedCommand('git checkout', priority=100)
|
||||
assert commands[2] == CorrectedCommand('git branch', priority=200)
|
||||
|
||||
def test_remove_duplicates(self):
|
||||
side_effect = lambda *_: None
|
||||
seq = SortedCorrectedCommandsSequence(
|
||||
iter([CorrectedCommand('ls', priority=100),
|
||||
CorrectedCommand('ls', priority=200),
|
||||
CorrectedCommand('ls', side_effect, 300)]))
|
||||
assert set(seq) == {CorrectedCommand('ls', priority=100),
|
||||
CorrectedCommand('ls', side_effect, 300)}
|
||||
|
||||
def test_with_blank(self):
|
||||
seq = SortedCorrectedCommandsSequence(iter([]))
|
||||
assert list(seq) == []
|
||||
|
||||
|
||||
class TestCorrectedCommand(object):
|
||||
|
||||
def test_equality(self):
|
||||
|
@ -1,10 +1,9 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
|
||||
from mock import Mock
|
||||
import pytest
|
||||
from itertools import islice
|
||||
from thefuck import ui
|
||||
from thefuck.types import CorrectedCommand, SortedCorrectedCommandsSequence
|
||||
from thefuck.types import CorrectedCommand
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@ -41,7 +40,7 @@ def test_read_actions(patch_getch):
|
||||
|
||||
|
||||
def test_command_selector():
|
||||
selector = ui.CommandSelector([1, 2, 3])
|
||||
selector = ui.CommandSelector(iter([1, 2, 3]))
|
||||
assert selector.value == 1
|
||||
selector.next()
|
||||
assert selector.value == 2
|
||||
@ -57,51 +56,49 @@ def test_command_selector():
|
||||
class TestSelectCommand(object):
|
||||
@pytest.fixture
|
||||
def commands_with_side_effect(self):
|
||||
return SortedCorrectedCommandsSequence(
|
||||
iter([CorrectedCommand('ls', lambda *_: None, 100),
|
||||
CorrectedCommand('cd', lambda *_: None, 100)]))
|
||||
return [CorrectedCommand('ls', lambda *_: None, 100),
|
||||
CorrectedCommand('cd', lambda *_: None, 100)]
|
||||
|
||||
@pytest.fixture
|
||||
def commands(self):
|
||||
return SortedCorrectedCommandsSequence(
|
||||
iter([CorrectedCommand('ls', None, 100),
|
||||
CorrectedCommand('cd', None, 100)]))
|
||||
return [CorrectedCommand('ls', None, 100),
|
||||
CorrectedCommand('cd', None, 100)]
|
||||
|
||||
def test_without_commands(self, capsys):
|
||||
assert ui.select_command([]) is None
|
||||
assert ui.select_command(iter([])) is None
|
||||
assert capsys.readouterr() == ('', 'No fucks given\n')
|
||||
|
||||
def test_without_confirmation(self, capsys, commands, settings):
|
||||
settings.require_confirmation = False
|
||||
assert ui.select_command(commands) == commands[0]
|
||||
assert ui.select_command(iter(commands)) == commands[0]
|
||||
assert capsys.readouterr() == ('', 'ls\n')
|
||||
|
||||
def test_without_confirmation_with_side_effects(
|
||||
self, capsys, commands_with_side_effect, settings):
|
||||
settings.require_confirmation = False
|
||||
assert ui.select_command(commands_with_side_effect) \
|
||||
assert ui.select_command(iter(commands_with_side_effect)) \
|
||||
== commands_with_side_effect[0]
|
||||
assert capsys.readouterr() == ('', 'ls (+side effect)\n')
|
||||
|
||||
def test_with_confirmation(self, capsys, patch_getch, commands):
|
||||
patch_getch(['\n'])
|
||||
assert ui.select_command(commands) == commands[0]
|
||||
assert ui.select_command(iter(commands)) == commands[0]
|
||||
assert capsys.readouterr() == ('', u'\x1b[1K\rls [enter/↑/↓/ctrl+c]\n')
|
||||
|
||||
def test_with_confirmation_abort(self, capsys, patch_getch, commands):
|
||||
patch_getch([KeyboardInterrupt])
|
||||
assert ui.select_command(commands) is None
|
||||
assert ui.select_command(iter(commands)) is None
|
||||
assert capsys.readouterr() == ('', u'\x1b[1K\rls [enter/↑/↓/ctrl+c]\nAborted\n')
|
||||
|
||||
def test_with_confirmation_with_side_effct(self, capsys, patch_getch,
|
||||
commands_with_side_effect):
|
||||
patch_getch(['\n'])
|
||||
assert ui.select_command(commands_with_side_effect)\
|
||||
assert ui.select_command(iter(commands_with_side_effect))\
|
||||
== commands_with_side_effect[0]
|
||||
assert capsys.readouterr() == ('', u'\x1b[1K\rls (+side effect) [enter/↑/↓/ctrl+c]\n')
|
||||
|
||||
def test_with_confirmation_select_second(self, capsys, patch_getch, commands):
|
||||
patch_getch(['\x1b', '[', 'B', '\n'])
|
||||
assert ui.select_command(commands) == commands[1]
|
||||
assert ui.select_command(iter(commands)) == commands[1]
|
||||
assert capsys.readouterr() == (
|
||||
'', u'\x1b[1K\rls [enter/↑/↓/ctrl+c]\x1b[1K\rcd [enter/↑/↓/ctrl+c]\n')
|
||||
|
@ -2,7 +2,7 @@ import sys
|
||||
from imp import load_source
|
||||
from pathlib import Path
|
||||
from .conf import settings, DEFAULT_PRIORITY, ALL_ENABLED
|
||||
from .types import Rule, CorrectedCommand, SortedCorrectedCommandsSequence
|
||||
from .types import Rule, CorrectedCommand
|
||||
from .utils import compatibility_call
|
||||
from . import logs
|
||||
|
||||
@ -76,10 +76,33 @@ def make_corrected_commands(command, rule):
|
||||
side_effect=rule.side_effect,
|
||||
priority=(n + 1) * rule.priority)
|
||||
|
||||
def organize_commands(corrected_commands):
|
||||
"""Yields sorted commands without duplicates."""
|
||||
try:
|
||||
first_command = next(corrected_commands)
|
||||
yield first_command
|
||||
except StopIteration:
|
||||
return
|
||||
|
||||
without_duplicates = {
|
||||
command for command in sorted(
|
||||
corrected_commands, key=lambda command: command.priority)
|
||||
if command != first_command}
|
||||
|
||||
sorted_commands = sorted(
|
||||
without_duplicates,
|
||||
key=lambda corrected_command: corrected_command.priority)
|
||||
|
||||
logs.debug('Corrected commands: '.format(
|
||||
', '.join(str(cmd) for cmd in [first_command] + sorted_commands)))
|
||||
|
||||
for command in sorted_commands:
|
||||
yield command
|
||||
|
||||
|
||||
def get_corrected_commands(command):
|
||||
corrected_commands = (
|
||||
corrected for rule in get_rules()
|
||||
if is_rule_match(command, rule)
|
||||
for corrected in make_corrected_commands(command, rule))
|
||||
return SortedCorrectedCommandsSequence(corrected_commands)
|
||||
return organize_commands(corrected_commands)
|
||||
|
@ -1,5 +1,4 @@
|
||||
from collections import namedtuple
|
||||
from traceback import format_stack
|
||||
|
||||
Command = namedtuple('Command', ('script', 'stdout', 'stderr'))
|
||||
|
||||
@ -36,62 +35,3 @@ class Settings(dict):
|
||||
|
||||
def __setattr__(self, key, value):
|
||||
self[key] = value
|
||||
|
||||
|
||||
class SortedCorrectedCommandsSequence(object):
|
||||
"""List-like collection/wrapper around generator, that:
|
||||
|
||||
- immediately gives access to the first commands through [];
|
||||
- realises generator and sorts commands on first access to other
|
||||
commands through [], or when len called.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, commands):
|
||||
self._commands = commands
|
||||
self._cached = self._realise_first()
|
||||
self._realised = False
|
||||
|
||||
def _realise_first(self):
|
||||
try:
|
||||
return [next(self._commands)]
|
||||
except StopIteration:
|
||||
return []
|
||||
|
||||
def _remove_duplicates(self, corrected_commands):
|
||||
"""Removes low-priority duplicates."""
|
||||
commands = {command
|
||||
for command in sorted(corrected_commands,
|
||||
key=lambda command: -command.priority)
|
||||
if command.script != self._cached[0]}
|
||||
return commands
|
||||
|
||||
def _realise(self):
|
||||
"""Realises generator, removes duplicates and sorts commands."""
|
||||
from .logs import debug
|
||||
|
||||
if self._cached:
|
||||
commands = self._remove_duplicates(self._commands)
|
||||
self._cached = [self._cached[0]] + sorted(
|
||||
commands, key=lambda corrected_command: corrected_command.priority)
|
||||
self._realised = True
|
||||
debug('SortedCommandsSequence was realised with: {}, after: {}'.format(
|
||||
self._cached, '\n'.join(format_stack())))
|
||||
|
||||
def __getitem__(self, item):
|
||||
if item != 0 and not self._realised:
|
||||
self._realise()
|
||||
return self._cached[item]
|
||||
|
||||
def __bool__(self):
|
||||
return bool(self._cached)
|
||||
|
||||
def __len__(self):
|
||||
if not self._realised:
|
||||
self._realise()
|
||||
return len(self._cached)
|
||||
|
||||
def __iter__(self):
|
||||
if not self._realised:
|
||||
self._realise()
|
||||
return iter(self._cached)
|
||||
|
@ -50,14 +50,25 @@ def read_actions():
|
||||
|
||||
|
||||
class CommandSelector(object):
|
||||
"""Helper for selecting rule from rules list."""
|
||||
|
||||
def __init__(self, commands):
|
||||
self._commands = commands
|
||||
self._commands_gen = commands
|
||||
self._commands = [next(self._commands_gen)]
|
||||
self._realised = False
|
||||
self._index = 0
|
||||
|
||||
def _realise(self):
|
||||
if not self._realised:
|
||||
self._commands += list(self._commands_gen)
|
||||
self._realised = True
|
||||
|
||||
def next(self):
|
||||
self._realise()
|
||||
self._index = (self._index + 1) % len(self._commands)
|
||||
|
||||
def previous(self):
|
||||
self._realise()
|
||||
self._index = (self._index - 1) % len(self._commands)
|
||||
|
||||
@property
|
||||
@ -73,11 +84,12 @@ def select_command(corrected_commands):
|
||||
- selected command.
|
||||
|
||||
"""
|
||||
if not corrected_commands:
|
||||
try:
|
||||
selector = CommandSelector(corrected_commands)
|
||||
except StopIteration:
|
||||
logs.failed('No fucks given')
|
||||
return
|
||||
|
||||
selector = CommandSelector(corrected_commands)
|
||||
if not settings.require_confirmation:
|
||||
logs.show_corrected_command(selector.value)
|
||||
return selector.value
|
||||
|
Loading…
x
Reference in New Issue
Block a user