1
0
mirror of https://github.com/nvbn/thefuck.git synced 2025-02-21 20:38:54 +00:00

Move special data types to types

This commit is contained in:
nvbn 2015-04-22 23:04:22 +02:00
parent 54c408a6b5
commit d3d1f99232
17 changed files with 89 additions and 88 deletions

View File

@ -1,4 +1,4 @@
from thefuck.main import Command from thefuck.types import Command
from thefuck.rules.cd_parent import match, get_new_command from thefuck.rules.cd_parent import match, get_new_command

View File

@ -1,5 +1,5 @@
import pytest import pytest
from thefuck.main import Command from thefuck.types import Command
from thefuck.rules.git_not_command import match, get_new_command from thefuck.rules.git_not_command import match, get_new_command

View File

@ -1,5 +1,5 @@
import pytest import pytest
from thefuck.main import Command from thefuck.types import Command
from thefuck.rules.git_push import match, get_new_command from thefuck.rules.git_push import match, get_new_command

View File

@ -1,5 +1,5 @@
from mock import Mock, patch from mock import Mock, patch
from thefuck.rules. has_exists_script import match, get_new_command from thefuck.rules.has_exists_script import match, get_new_command
def test_match(): def test_match():

View File

@ -1,4 +1,4 @@
from thefuck.main import Command from thefuck.types import Command
from thefuck.rules.mkdir_p import match, get_new_command from thefuck.rules.mkdir_p import match, get_new_command

View File

@ -1,9 +1,11 @@
from thefuck.main import Command from thefuck.types import Command
from thefuck.rules.python_command import match, get_new_command from thefuck.rules.python_command import match, get_new_command
def test_match(): def test_match():
assert match(Command('temp.py', '', 'Permission denied'), None) assert match(Command('temp.py', '', 'Permission denied'), None)
assert not match(Command('', '', ''), None) assert not match(Command('', '', ''), None)
def test_get_new_command(): def test_get_new_command():
assert get_new_command(Command('./test_sudo.py', '', ''), None) == 'python ./test_sudo.py' assert get_new_command(Command('./test_sudo.py', '', ''), None) == 'python ./test_sudo.py'

View File

@ -1,4 +1,4 @@
from thefuck.main import Command from thefuck.types import Command
from thefuck.rules.rm_dir import match, get_new_command from thefuck.rules.rm_dir import match, get_new_command

View File

@ -1,7 +1,7 @@
import os import os
import pytest import pytest
from mock import Mock from mock import Mock
from thefuck.main import Command from thefuck.types import Command
from thefuck.rules.ssh_known_hosts import match, get_new_command, remove_offending_keys from thefuck.rules.ssh_known_hosts import match, get_new_command, remove_offending_keys

View File

@ -1,4 +1,4 @@
from thefuck.main import Command from thefuck.types import Command
from thefuck.rules.sudo import match, get_new_command from thefuck.rules.sudo import match, get_new_command

View File

@ -1,15 +1,8 @@
from mock import patch, Mock from mock import patch, Mock
from thefuck.main import Rule from thefuck.types import Rule
from thefuck import conf from thefuck import conf
def test_rules_names_list():
assert conf.RulesNamesList(['bash', 'lisp']) == ['bash', 'lisp']
assert conf.RulesNamesList(['bash', 'lisp']) == conf.RulesNamesList(['bash', 'lisp'])
assert Rule('lisp', None, None, False) in conf.RulesNamesList(['lisp'])
assert Rule('bash', None, None, False) not in conf.RulesNamesList(['lisp'])
def test_default(): def test_default():
assert Rule('test', None, None, True) in conf.DEFAULT_RULES assert Rule('test', None, None, True) in conf.DEFAULT_RULES
assert Rule('test', None, None, False) not in conf.DEFAULT_RULES assert Rule('test', None, None, False) not in conf.DEFAULT_RULES
@ -66,10 +59,3 @@ def test_settings_from_env_with_DEFAULT():
patch('thefuck.conf.os.environ', new_callable=lambda: {'THEFUCK_RULES': 'DEFAULT_RULES:bash:lisp'}): patch('thefuck.conf.os.environ', new_callable=lambda: {'THEFUCK_RULES': 'DEFAULT_RULES:bash:lisp'}):
settings = conf.get_settings(Mock()) settings = conf.get_settings(Mock())
assert settings.rules == conf.DEFAULT_RULES + ['bash', 'lisp'] assert settings.rules == conf.DEFAULT_RULES + ['bash', 'lisp']
def test_update_settings():
settings = conf.Settings({'key': 'val'})
new_settings = settings.update(key='new-val')
assert new_settings.key == 'new-val'
assert settings.key == 'val'

View File

@ -1,7 +1,7 @@
from subprocess import PIPE from subprocess import PIPE
from pathlib import PosixPath, Path from pathlib import PosixPath, Path
from mock import patch, Mock from mock import patch, Mock
from thefuck import main, conf from thefuck import main, conf, types
def test_load_rule(): def test_load_rule():
@ -13,7 +13,7 @@ def test_load_rule():
get_new_command=get_new_command, get_new_command=get_new_command,
enabled_by_default=True)) as load_source: enabled_by_default=True)) as load_source:
assert main.load_rule(Path('/rules/bash.py')) \ assert main.load_rule(Path('/rules/bash.py')) \
== main.Rule('bash', match, get_new_command, True) == types.Rule('bash', match, get_new_command, True)
load_source.assert_called_once_with('bash', '/rules/bash.py') load_source.assert_called_once_with('bash', '/rules/bash.py')
@ -26,15 +26,15 @@ def test_get_rules():
assert list(main.get_rules( assert list(main.get_rules(
Path('~'), Path('~'),
Mock(rules=conf.DEFAULT_RULES))) \ Mock(rules=conf.DEFAULT_RULES))) \
== [main.Rule('bash', 'bash', 'bash', True), == [types.Rule('bash', 'bash', 'bash', True),
main.Rule('lisp', 'lisp', 'lisp', True), types.Rule('lisp', 'lisp', 'lisp', True),
main.Rule('bash', 'bash', 'bash', True), types.Rule('bash', 'bash', 'bash', True),
main.Rule('lisp', 'lisp', 'lisp', True)] types.Rule('lisp', 'lisp', 'lisp', True)]
assert list(main.get_rules( assert list(main.get_rules(
Path('~'), Path('~'),
Mock(rules=conf.RulesNamesList(['bash'])))) \ Mock(rules=types.RulesNamesList(['bash'])))) \
== [main.Rule('bash', 'bash', 'bash', True), == [types.Rule('bash', 'bash', 'bash', True),
main.Rule('bash', 'bash', 'bash', True)] types.Rule('bash', 'bash', 'bash', True)]
def test_get_command(): def test_get_command():
@ -47,7 +47,7 @@ def test_get_command():
Popen.return_value.stderr.read.return_value = b'stderr' Popen.return_value.stderr.read.return_value = b'stderr'
assert main.get_command(Mock(), ['thefuck', 'apt-get', assert main.get_command(Mock(), ['thefuck', 'apt-get',
'search', 'vim']) \ 'search', 'vim']) \
== main.Command('apt-get search vim', 'stdout', 'stderr') == types.Command('apt-get search vim', 'stdout', 'stderr')
Popen.assert_called_once_with('apt-get search vim', Popen.assert_called_once_with('apt-get search vim',
shell=True, shell=True,
stdout=PIPE, stdout=PIPE,
@ -57,12 +57,12 @@ def test_get_command():
def test_get_matched_rule(capsys): def test_get_matched_rule(capsys):
rules = [main.Rule('', lambda x, _: x.script == 'cd ..', None, True), rules = [types.Rule('', lambda x, _: x.script == 'cd ..', None, True),
main.Rule('', lambda *_: False, None, True), types.Rule('', lambda *_: False, None, True),
main.Rule('rule', Mock(side_effect=OSError('Denied')), None, True)] types.Rule('rule', Mock(side_effect=OSError('Denied')), None, True)]
assert main.get_matched_rule(main.Command('ls', '', ''), assert main.get_matched_rule(types.Command('ls', '', ''),
rules, Mock(no_colors=True)) is None rules, Mock(no_colors=True)) is None
assert main.get_matched_rule(main.Command('cd ..', '', ''), assert main.get_matched_rule(types.Command('cd ..', '', ''),
rules, Mock(no_colors=True)) == rules[0] rules, Mock(no_colors=True)) == rules[0]
assert capsys.readouterr()[1].split('\n')[0] \ assert capsys.readouterr()[1].split('\n')[0] \
== '[WARN] Rule rule:' == '[WARN] Rule rule:'
@ -70,11 +70,11 @@ def test_get_matched_rule(capsys):
def test_run_rule(capsys): def test_run_rule(capsys):
with patch('thefuck.main.confirm', return_value=True): with patch('thefuck.main.confirm', return_value=True):
main.run_rule(main.Rule('', None, lambda *_: 'new-command', True), main.run_rule(types.Rule('', None, lambda *_: 'new-command', True),
None, None) None, None)
assert capsys.readouterr() == ('new-command\n', '') assert capsys.readouterr() == ('new-command\n', '')
with patch('thefuck.main.confirm', return_value=False): with patch('thefuck.main.confirm', return_value=False):
main.run_rule(main.Rule('', None, lambda *_: 'new-command', True), main.run_rule(types.Rule('', None, lambda *_: 'new-command', True),
None, None) None, None)
assert capsys.readouterr() == ('', '') assert capsys.readouterr() == ('', '')

15
tests/test_types.py Normal file
View File

@ -0,0 +1,15 @@
from thefuck.types import Rule, RulesNamesList, Settings
def test_rules_names_list():
assert RulesNamesList(['bash', 'lisp']) == ['bash', 'lisp']
assert RulesNamesList(['bash', 'lisp']) == RulesNamesList(['bash', 'lisp'])
assert Rule('lisp', None, None, False) in RulesNamesList(['lisp'])
assert Rule('bash', None, None, False) not in RulesNamesList(['lisp'])
def test_update_settings():
settings = Settings({'key': 'val'})
new_settings = settings.update(key='new-val')
assert new_settings.key == 'new-val'
assert settings.key == 'val'

View File

@ -1,11 +1,10 @@
from mock import Mock from mock import Mock
from thefuck.utils import sudo_support, wrap_settings from thefuck.utils import sudo_support, wrap_settings
from thefuck.main import Command from thefuck.types import Command, Settings
from thefuck.conf import Settings
def test_wrap_settings(): def test_wrap_settings():
fn = lambda _, settings: settings._conf fn = lambda _, settings: settings
assert wrap_settings({'key': 'val'})(fn)(None, Settings({})) \ assert wrap_settings({'key': 'val'})(fn)(None, Settings({})) \
== {'key': 'val'} == {'key': 'val'}
assert wrap_settings({'key': 'new-val'})(fn)( assert wrap_settings({'key': 'new-val'})(fn)(

View File

@ -3,17 +3,10 @@ from imp import load_source
import os import os
import sys import sys
from six import text_type from six import text_type
from . import logs from . import logs, types
class RulesNamesList(list): class _DefaultRulesNames(types.RulesNamesList):
"""Wrapper a top of list for string rules names."""
def __contains__(self, item):
return super(RulesNamesList, self).__contains__(item.name)
class _DefaultRulesNames(RulesNamesList):
def __add__(self, items): def __add__(self, items):
return _DefaultRulesNames(list(self) + items) return _DefaultRulesNames(list(self) + items)
@ -31,20 +24,6 @@ class _DefaultRulesNames(RulesNamesList):
DEFAULT_RULES = _DefaultRulesNames([]) DEFAULT_RULES = _DefaultRulesNames([])
class Settings(object):
def __init__(self, conf):
self._conf = conf
def __getattr__(self, item):
return self._conf.get(item)
def update(self, **kwargs):
"""Returns new settings with new values from `kwargs`."""
conf = copy(self._conf)
conf.update(kwargs)
return Settings(conf)
DEFAULT_SETTINGS = {'rules': DEFAULT_RULES, DEFAULT_SETTINGS = {'rules': DEFAULT_RULES,
'wait_command': 3, 'wait_command': 3,
'require_confirmation': False, 'require_confirmation': False,
@ -100,16 +79,16 @@ def get_settings(user_dir):
except Exception: except Exception:
logs.exception("Can't load settings from file", logs.exception("Can't load settings from file",
sys.exc_info(), sys.exc_info(),
Settings(conf)) types.Settings(conf))
try: try:
conf.update(_settings_from_env()) conf.update(_settings_from_env())
except Exception: except Exception:
logs.exception("Can't load settings from env", logs.exception("Can't load settings from env",
sys.exc_info(), sys.exc_info(),
Settings(conf)) types.Settings(conf))
if not isinstance(conf['rules'], RulesNamesList): if not isinstance(conf['rules'], types.RulesNamesList):
conf['rules'] = RulesNamesList(conf['rules']) conf['rules'] = types.RulesNamesList(conf['rules'])
return Settings(conf) return types.Settings(conf)

View File

@ -1,4 +1,3 @@
from collections import namedtuple
from imp import load_source from imp import load_source
from pathlib import Path from pathlib import Path
from os.path import expanduser from os.path import expanduser
@ -7,12 +6,7 @@ import os
import sys import sys
from psutil import Process, TimeoutExpired from psutil import Process, TimeoutExpired
import colorama import colorama
from . import logs, conf from . import logs, conf, types
Command = namedtuple('Command', ('script', 'stdout', 'stderr'))
Rule = namedtuple('Rule', ('name', 'match', 'get_new_command',
'enabled_by_default'))
def setup_user_dir(): def setup_user_dir():
@ -28,16 +22,16 @@ def setup_user_dir():
def load_rule(rule): def load_rule(rule):
"""Imports rule module and returns it.""" """Imports rule module and returns it."""
rule_module = load_source(rule.name[:-3], str(rule)) rule_module = load_source(rule.name[:-3], str(rule))
return Rule(rule.name[:-3], rule_module.match, return types.Rule(rule.name[:-3], rule_module.match,
rule_module.get_new_command, rule_module.get_new_command,
getattr(rule_module, 'enabled_by_default', True)) getattr(rule_module, 'enabled_by_default', True))
def get_rules(user_dir, settings): def get_rules(user_dir, settings):
"""Returns all enabled rules.""" """Returns all enabled rules."""
bundled = Path(__file__).parent\ bundled = Path(__file__).parent \
.joinpath('rules')\ .joinpath('rules') \
.glob('*.py') .glob('*.py')
user = user_dir.joinpath('rules').glob('*.py') user = user_dir.joinpath('rules').glob('*.py')
for rule in sorted(list(bundled)) + list(user): for rule in sorted(list(bundled)) + list(user):
if rule.name != '__init__.py': if rule.name != '__init__.py':
@ -77,8 +71,8 @@ def get_command(settings, args):
result = Popen(script, shell=True, stdout=PIPE, stderr=PIPE, result = Popen(script, shell=True, stdout=PIPE, stderr=PIPE,
env=dict(os.environ, LANG='C')) env=dict(os.environ, LANG='C'))
if wait_output(settings, result): if wait_output(settings, result):
return Command(script, result.stdout.read().decode('utf-8'), return types.Command(script, result.stdout.read().decode('utf-8'),
result.stderr.read().decode('utf-8')) result.stderr.read().decode('utf-8'))
def get_matched_rule(command, rules, settings): def get_matched_rule(command, rules, settings):

26
thefuck/types.py Normal file
View File

@ -0,0 +1,26 @@
from collections import namedtuple
Command = namedtuple('Command', ('script', 'stdout', 'stderr'))
Rule = namedtuple('Rule', ('name', 'match', 'get_new_command',
'enabled_by_default'))
class RulesNamesList(list):
"""Wrapper a top of list for string rules names."""
def __contains__(self, item):
return super(RulesNamesList, self).__contains__(item.name)
class Settings(dict):
def __getattr__(self, item):
return self.get(item)
def update(self, **kwargs):
"""Returns new settings with new values from `kwargs`."""
conf = dict(self)
conf.update(kwargs)
return Settings(conf)

View File

@ -1,7 +1,7 @@
from functools import wraps from functools import wraps
import os import os
import six import six
from thefuck.main import Command from .types import Command
def which(program): def which(program):