diff --git a/tests/test_corrector.py b/tests/test_corrector.py index fb8cb94d..d28819df 100644 --- a/tests/test_corrector.py +++ b/tests/test_corrector.py @@ -8,14 +8,15 @@ from thefuck.types import Command from thefuck.corrector import get_corrected_commands, organize_commands -class TestGetRules(object): - @pytest.fixture - def glob(self, mocker): - results = {} - mocker.patch('thefuck.system.Path.glob', - new_callable=lambda: lambda *_: results.pop('value', [])) - return lambda value: results.update({'value': value}) +@pytest.fixture +def glob(mocker): + results = {} + mocker.patch('thefuck.system.Path.glob', + new_callable=lambda: lambda *_: results.pop('value', [])) + return lambda value: results.update({'value': value}) + +class TestGetRules(object): @pytest.fixture(autouse=True) def load_source(self, monkeypatch): monkeypatch.setattr('thefuck.types.load_source', @@ -39,6 +40,14 @@ class TestGetRules(object): self._compare_names(rules, loaded_rules) +def test_get_rules_rule_exception(mocker, glob): + load_source = mocker.patch('thefuck.types.load_source', + side_effect=ImportError("No module named foo...")) + glob([Path('git.py')]) + assert not corrector.get_rules() + load_source.assert_called_once_with('git', 'git.py') + + def test_get_corrected_commands(mocker): command = Command('test', 'test') rules = [Rule(match=lambda _: False), diff --git a/tests/test_types.py b/tests/test_types.py index 4d0f0f70..c9b293e9 100644 --- a/tests/test_types.py +++ b/tests/test_types.py @@ -45,6 +45,12 @@ class TestCorrectedCommand(object): class TestRule(object): + def test_from_path_rule_exception(self, mocker): + load_source = mocker.patch('thefuck.types.load_source', + side_effect=ImportError("No module named foo...")) + assert Rule.from_path(Path('git.py')) is None + load_source.assert_called_once_with('git', 'git.py') + def test_from_path(self, mocker): match = object() get_new_command = object() diff --git a/thefuck/corrector.py b/thefuck/corrector.py index 89d21ebf..fdd46983 100644 --- a/thefuck/corrector.py +++ b/thefuck/corrector.py @@ -15,7 +15,7 @@ def get_loaded_rules(rules_paths): for path in rules_paths: if path.name != '__init__.py': rule = Rule.from_path(path) - if rule.is_enabled: + if rule and rule.is_enabled: yield rule diff --git a/thefuck/types.py b/thefuck/types.py index 5d8c2cc7..027042ed 100644 --- a/thefuck/types.py +++ b/thefuck/types.py @@ -137,8 +137,12 @@ class Rule(object): """ name = path.name[:-3] with logs.debug_time(u'Importing rule: {};'.format(name)): - rule_module = load_source(name, str(path)) - priority = getattr(rule_module, 'priority', DEFAULT_PRIORITY) + try: + rule_module = load_source(name, str(path)) + except Exception: + logs.exception(u"Rule {} failed to load".format(name), sys.exc_info()) + return + priority = getattr(rule_module, 'priority', DEFAULT_PRIORITY) return cls(name, rule_module.match, rule_module.get_new_command, getattr(rule_module, 'enabled_by_default', True),