1
0
mirror of https://github.com/nvbn/thefuck.git synced 2025-01-31 10:11:14 +00:00

#366 Add type annotations in core components

This commit is contained in:
nvbn 2015-09-08 15:54:07 +03:00
parent eb17e696c3
commit dfa22bc92b
4 changed files with 107 additions and 7 deletions

View File

@ -5,7 +5,12 @@ from . import logs
def get_loaded_rules(rules_paths): def get_loaded_rules(rules_paths):
"""Yields all available rules.""" """Yields all available rules.
:type rules_paths: [Path]
:rtype: Iterable[Rule]
"""
for path in rules_paths: for path in rules_paths:
if path.name != '__init__.py': if path.name != '__init__.py':
rule = Rule.from_path(path) rule = Rule.from_path(path)
@ -14,7 +19,11 @@ def get_loaded_rules(rules_paths):
def get_rules(): def get_rules():
"""Returns all enabled rules.""" """Returns all enabled rules.
:rtype: [Rule]
"""
bundled = Path(__file__).parent \ bundled = Path(__file__).parent \
.joinpath('rules') \ .joinpath('rules') \
.glob('*.py') .glob('*.py')
@ -24,7 +33,12 @@ def get_rules():
def organize_commands(corrected_commands): def organize_commands(corrected_commands):
"""Yields sorted commands without duplicates.""" """Yields sorted commands without duplicates.
:type corrected_commands: Iterable[thefuck.types.CorrectedCommand]
:rtype: Iterable[thefuck.types.CorrectedCommand]
"""
try: try:
first_command = next(corrected_commands) first_command = next(corrected_commands)
yield first_command yield first_command
@ -48,6 +62,12 @@ def organize_commands(corrected_commands):
def get_corrected_commands(command): def get_corrected_commands(command):
"""Returns generator with sorted and unique corrected commands.
:type command: thefuck.types.Command
:rtype: Iterable[thefuck.types.CorrectedCommand]
"""
corrected_commands = ( corrected_commands = (
corrected for rule in get_rules() corrected for rule in get_rules()
if rule.is_match(command) if rule.is_match(command)

View File

@ -26,6 +26,7 @@ def fix_command():
corrected_commands = get_corrected_commands(command) corrected_commands = get_corrected_commands(command)
selected_command = select_command(corrected_commands) selected_command = select_command(corrected_commands)
if selected_command: if selected_command:
selected_command.run(command) selected_command.run(command)

View File

@ -14,6 +14,13 @@ class Command(object):
"""Command that should be fixed.""" """Command that should be fixed."""
def __init__(self, script, stdout, stderr): def __init__(self, script, stdout, stderr):
"""Initializes command with given values.
:type script: basestring
:type stdout: basestring
:type stderr: basestring
"""
self.script = script self.script = script
self.stdout = stdout self.stdout = stdout
self.stderr = stderr self.stderr = stderr
@ -30,7 +37,11 @@ class Command(object):
self.script, self.stdout, self.stderr) self.script, self.stdout, self.stderr)
def update(self, **kwargs): def update(self, **kwargs):
"""Returns new command with replaced fields.""" """Returns new command with replaced fields.
:rtype: Command
"""
kwargs.setdefault('script', self.script) kwargs.setdefault('script', self.script)
kwargs.setdefault('stdout', self.stdout) kwargs.setdefault('stdout', self.stdout)
kwargs.setdefault('stderr', self.stderr) kwargs.setdefault('stderr', self.stderr)
@ -43,6 +54,9 @@ class Command(object):
Command will be killed if it wasn't finished in the time. Command will be killed if it wasn't finished in the time.
:type popen: Popen
:rtype: bool
""" """
proc = Process(popen.pid) proc = Process(popen.pid)
try: try:
@ -56,6 +70,12 @@ class Command(object):
@staticmethod @staticmethod
def _prepare_script(raw_script): def _prepare_script(raw_script):
"""Creates single script from a list of script parts.
:type raw_script: [basestring]
:rtype: basestring
"""
if six.PY2: if six.PY2:
script = ' '.join(arg.decode('utf-8') for arg in raw_script) script = ' '.join(arg.decode('utf-8') for arg in raw_script)
else: else:
@ -66,6 +86,13 @@ class Command(object):
@classmethod @classmethod
def from_raw_script(cls, raw_script): def from_raw_script(cls, raw_script):
"""Creates instance of `Command` from a list of script parts.
:type raw_script: [basestring]
:rtype: Command
:raises: EmptyCommand
"""
script = cls._prepare_script(raw_script) script = cls._prepare_script(raw_script)
if not script: if not script:
raise EmptyCommand raise EmptyCommand
@ -89,9 +116,22 @@ class Command(object):
class Rule(object): class Rule(object):
"""Rule for fixing commands."""
def __init__(self, name, match, get_new_command, def __init__(self, name, match, get_new_command,
enabled_by_default, side_effect, enabled_by_default, side_effect,
priority, requires_output): priority, requires_output):
"""Initializes rule with given fields.
:type name: basestring
:type match: (Command) -> bool
:type get_new_command: (Command) -> (basestring | [basestring])
:type enabled_by_default: boolean
:type side_effect: (Command, basestring) -> None
:type priority: int
:type requires_output: bool
"""
self.name = name self.name = name
self.match = match self.match = match
self.get_new_command = get_new_command self.get_new_command = get_new_command
@ -121,7 +161,12 @@ class Rule(object):
@classmethod @classmethod
def from_path(cls, path): def from_path(cls, path):
"""Creates rule instance from path.""" """Creates rule instance from path.
:type path: pathlib.Path
:rtype: Rule
"""
name = path.name[:-3] name = path.name[:-3]
with logs.debug_time(u'Importing rule: {};'.format(name)): with logs.debug_time(u'Importing rule: {};'.format(name)):
rule_module = load_source(name, str(path)) rule_module = load_source(name, str(path))
@ -135,6 +180,11 @@ class Rule(object):
@property @property
def is_enabled(self): def is_enabled(self):
"""Returns `True` when rule enabled.
:rtype: bool
"""
if self.name in settings.exclude_rules: if self.name in settings.exclude_rules:
return False return False
elif self.name in settings.rules: elif self.name in settings.rules:
@ -145,7 +195,12 @@ class Rule(object):
return False return False
def is_match(self, command): def is_match(self, command):
"""Returns `True` if rule matches the command.""" """Returns `True` if rule matches the command.
:type command: Command
:rtype: bool
"""
script_only = command.stdout is None and command.stderr is None script_only = command.stdout is None and command.stderr is None
if script_only and self.requires_output: if script_only and self.requires_output:
@ -159,6 +214,12 @@ class Rule(object):
logs.rule_failed(self, sys.exc_info()) logs.rule_failed(self, sys.exc_info())
def get_corrected_commands(self, command): def get_corrected_commands(self, command):
"""Returns generator with corrected commands.
:type command: Command
:rtype: Iterable[CorrectedCommand]
"""
new_commands = compatibility_call(self.get_new_command, command) new_commands = compatibility_call(self.get_new_command, command)
if not isinstance(new_commands, list): if not isinstance(new_commands, list):
new_commands = (new_commands,) new_commands = (new_commands,)
@ -169,7 +230,16 @@ class Rule(object):
class CorrectedCommand(object): class CorrectedCommand(object):
"""Corrected by rule command."""
def __init__(self, script, side_effect, priority): def __init__(self, script, side_effect, priority):
"""Initializes instance with given fields.
:type script: basestring
:type side_effect: (Command, basestring) -> None
:type priority: int
"""
self.script = script self.script = script
self.side_effect = side_effect self.side_effect = side_effect
self.priority = priority self.priority = priority
@ -190,7 +260,11 @@ class CorrectedCommand(object):
self.script, self.side_effect, self.priority) self.script, self.side_effect, self.priority)
def run(self, old_cmd): def run(self, old_cmd):
"""Runs command from rule for passed command.""" """Runs command from rule for passed command.
:type old_cmd: Command
"""
if self.side_effect: if self.side_effect:
compatibility_call(self.side_effect, old_cmd, self.script) compatibility_call(self.side_effect, old_cmd, self.script)
shells.put_to_history(self.script) shells.put_to_history(self.script)

View File

@ -54,6 +54,7 @@ class CommandSelector(object):
"""Helper for selecting rule from rules list.""" """Helper for selecting rule from rules list."""
def __init__(self, commands): def __init__(self, commands):
""":type commands: Iterable[thefuck.types.CorrectedCommand]"""
self._commands_gen = commands self._commands_gen = commands
try: try:
self._commands = [next(self._commands_gen)] self._commands = [next(self._commands_gen)]
@ -77,6 +78,7 @@ class CommandSelector(object):
@property @property
def value(self): def value(self):
""":rtype hefuck.types.CorrectedCommand"""
return self._commands[self._index] return self._commands[self._index]
@ -87,6 +89,9 @@ def select_command(corrected_commands):
- None when ctrl+c pressed; - None when ctrl+c pressed;
- selected command. - selected command.
:type corrected_commands: Iterable[thefuck.types.CorrectedCommand]
:rtype: thefuck.types.CorrectedCommand | None
""" """
try: try:
selector = CommandSelector(corrected_commands) selector = CommandSelector(corrected_commands)