From 1173f9f59cfab3f78cca1fc9b6af37a48b3086ec Mon Sep 17 00:00:00 2001 From: nvbn Date: Tue, 8 Sep 2015 15:15:53 +0300 Subject: [PATCH] Organize settings initialization logic in `Settings` --- tests/test_conf.py | 22 +++---- thefuck/conf.py | 145 +++++++++++++++++++++++---------------------- thefuck/main.py | 22 +------ 3 files changed, 88 insertions(+), 101 deletions(-) diff --git a/tests/test_conf.py b/tests/test_conf.py index b5c50b56..86b2bf01 100644 --- a/tests/test_conf.py +++ b/tests/test_conf.py @@ -19,7 +19,7 @@ def environ(monkeypatch): @pytest.mark.usefixture('environ') def test_settings_defaults(load_source, settings): load_source.return_value = object() - conf.init_settings(Mock()) + settings.init() for key, val in conf.DEFAULT_SETTINGS.items(): assert getattr(settings, key) == val @@ -33,7 +33,7 @@ class TestSettingsFromFile(object): no_colors=True, priority={'vim': 100}, exclude_rules=['git']) - conf.init_settings(Mock()) + settings.init() assert settings.rules == ['test'] assert settings.wait_command == 10 assert settings.require_confirmation is True @@ -47,7 +47,7 @@ class TestSettingsFromFile(object): exclude_rules=[], require_confirmation=True, no_colors=True) - conf.init_settings(Mock()) + settings.init() assert settings.rules == conf.DEFAULT_RULES + ['test'] @@ -60,7 +60,7 @@ class TestSettingsFromEnv(object): 'THEFUCK_REQUIRE_CONFIRMATION': 'true', 'THEFUCK_NO_COLORS': 'false', 'THEFUCK_PRIORITY': 'bash=10:lisp=wrong:vim=15'}) - conf.init_settings(Mock()) + settings.init() assert settings.rules == ['bash', 'lisp'] assert settings.exclude_rules == ['git', 'vim'] assert settings.wait_command == 55 @@ -70,26 +70,26 @@ class TestSettingsFromEnv(object): def test_from_env_with_DEFAULT(self, environ, settings): environ.update({'THEFUCK_RULES': 'DEFAULT_RULES:bash:lisp'}) - conf.init_settings(Mock()) + settings.init() assert settings.rules == conf.DEFAULT_RULES + ['bash', 'lisp'] class TestInitializeSettingsFile(object): - def test_ignore_if_exists(self): + def test_ignore_if_exists(self, settings): settings_path_mock = Mock(is_file=Mock(return_value=True), open=Mock()) - user_dir_mock = Mock(joinpath=Mock(return_value=settings_path_mock)) - conf.initialize_settings_file(user_dir_mock) + settings.user_dir = Mock(joinpath=Mock(return_value=settings_path_mock)) + settings._init_settings_file() assert settings_path_mock.is_file.call_count == 1 assert not settings_path_mock.open.called - def test_create_if_doesnt_exists(self): + def test_create_if_doesnt_exists(self, settings): settings_file = six.StringIO() settings_path_mock = Mock( is_file=Mock(return_value=False), open=Mock(return_value=Mock( __exit__=lambda *args: None, __enter__=lambda *args: settings_file))) - user_dir_mock = Mock(joinpath=Mock(return_value=settings_path_mock)) - conf.initialize_settings_file(user_dir_mock) + settings.user_dir = Mock(joinpath=Mock(return_value=settings_path_mock)) + settings._init_settings_file() settings_file_contents = settings_file.getvalue() assert settings_path_mock.is_file.call_count == 1 assert settings_path_mock.open.call_count == 1 diff --git a/thefuck/conf.py b/thefuck/conf.py index 9df4bece..3e6e55f5 100644 --- a/thefuck/conf.py +++ b/thefuck/conf.py @@ -1,17 +1,10 @@ from imp import load_source import os import sys +from pathlib import Path from six import text_type -class Settings(dict): - def __getattr__(self, item): - return self.get(item) - - def __setattr__(self, key, value): - self[key] = value - - ALL_ENABLED = object() DEFAULT_RULES = [ALL_ENABLED] DEFAULT_PRIORITY = 1000 @@ -46,79 +39,89 @@ SETTINGS_HEADER = u"""# ~/.thefuck/settings.py: The Fuck settings file """ -def _settings_from_file(user_dir): - """Loads settings from file.""" - settings = load_source('settings', - text_type(user_dir.joinpath('settings.py'))) - return {key: getattr(settings, key) - for key in DEFAULT_SETTINGS.keys() - if hasattr(settings, key)} +class Settings(dict): + def __getattr__(self, item): + return self.get(item) + def __setattr__(self, key, value): + self[key] = value -def _rules_from_env(val): - """Transforms rules list from env-string to python.""" - val = val.split(':') - if 'DEFAULT_RULES' in val: - val = DEFAULT_RULES + [rule for rule in val if rule != 'DEFAULT_RULES'] - return val + def init(self): + """Fills `settings` with values from `settings.py` and env.""" + from .logs import exception + self._setup_user_dir() + self._init_settings_file() -def _priority_from_env(val): - """Gets priority pairs from env.""" - for part in val.split(':'): try: - rule, priority = part.split('=') - yield rule, int(priority) - except ValueError: - continue + self.update(self._settings_from_file()) + except Exception: + exception("Can't load settings from file", sys.exc_info()) + try: + self.update(self._settings_from_env()) + except Exception: + exception("Can't load settings from env", sys.exc_info()) -def _val_from_env(env, attr): - """Transforms env-strings to python.""" - val = os.environ[env] - if attr in ('rules', 'exclude_rules'): - return _rules_from_env(val) - elif attr == 'priority': - return dict(_priority_from_env(val)) - elif attr == 'wait_command': - return int(val) - elif attr in ('require_confirmation', 'no_colors', 'debug'): - return val.lower() == 'true' - else: + def _init_settings_file(self): + settings_path = self.user_dir.joinpath('settings.py') + if not settings_path.is_file(): + with settings_path.open(mode='w') as settings_file: + settings_file.write(SETTINGS_HEADER) + for setting in DEFAULT_SETTINGS.items(): + settings_file.write(u'# {} = {}\n'.format(*setting)) + + def _setup_user_dir(self): + """Returns user config dir, create it when it doesn't exist.""" + user_dir = Path(os.path.expanduser('~/.thefuck')) + rules_dir = user_dir.joinpath('rules') + if not rules_dir.is_dir(): + rules_dir.mkdir(parents=True) + self.user_dir = user_dir + + def _settings_from_file(self): + """Loads settings from file.""" + settings = load_source( + 'settings', text_type(self.user_dir.joinpath('settings.py'))) + return {key: getattr(settings, key) + for key in DEFAULT_SETTINGS.keys() + if hasattr(settings, key)} + + def _rules_from_env(self, val): + """Transforms rules list from env-string to python.""" + val = val.split(':') + if 'DEFAULT_RULES' in val: + val = DEFAULT_RULES + [rule for rule in val if rule != 'DEFAULT_RULES'] return val + def _priority_from_env(self, val): + """Gets priority pairs from env.""" + for part in val.split(':'): + try: + rule, priority = part.split('=') + yield rule, int(priority) + except ValueError: + continue -def _settings_from_env(): - """Loads settings from env.""" - return {attr: _val_from_env(env, attr) - for env, attr in ENV_TO_ATTR.items() - if env in os.environ} + def _val_from_env(self, env, attr): + """Transforms env-strings to python.""" + val = os.environ[env] + if attr in ('rules', 'exclude_rules'): + return self._rules_from_env(val) + elif attr == 'priority': + return dict(self._priority_from_env(val)) + elif attr == 'wait_command': + return int(val) + elif attr in ('require_confirmation', 'no_colors', 'debug'): + return val.lower() == 'true' + else: + return val + + def _settings_from_env(self): + """Loads settings from env.""" + return {attr: self._val_from_env(env, attr) + for env, attr in ENV_TO_ATTR.items() + if env in os.environ} settings = Settings(DEFAULT_SETTINGS) - - -def init_settings(user_dir): - """Fills `settings` with values from `settings.py` and env.""" - from .logs import exception - - settings.user_dir = user_dir - - try: - settings.update(_settings_from_file(user_dir)) - except Exception: - exception("Can't load settings from file", sys.exc_info()) - - try: - settings.update(_settings_from_env()) - except Exception: - exception("Can't load settings from env", sys.exc_info()) - - -def initialize_settings_file(user_dir): - settings_path = user_dir.joinpath('settings.py') - if not settings_path.is_file(): - with settings_path.open(mode='w') as settings_file: - settings_file.write(SETTINGS_HEADER) - for setting in DEFAULT_SETTINGS.items(): - settings_file.write(u'# {} = {}\n'.format(*setting)) diff --git a/thefuck/main.py b/thefuck/main.py index 9ae08fc1..617c4e10 100644 --- a/thefuck/main.py +++ b/thefuck/main.py @@ -1,34 +1,19 @@ from argparse import ArgumentParser from warnings import warn -from pathlib import Path -from os.path import expanduser from pprint import pformat import pkg_resources import sys import colorama from . import logs, types, shells -from .conf import initialize_settings_file, init_settings, settings +from .conf import settings from .corrector import get_corrected_commands from .exceptions import EmptyCommand from .ui import select_command -def setup_user_dir(): - """Returns user config dir, create it when it doesn't exist.""" - user_dir = Path(expanduser('~/.thefuck')) - rules_dir = user_dir.joinpath('rules') - if not rules_dir.is_dir(): - rules_dir.mkdir(parents=True) - initialize_settings_file(user_dir) - return user_dir - - -# Entry points: - def fix_command(): colorama.init() - user_dir = setup_user_dir() - init_settings(user_dir) + settings.init() with logs.debug_time('Total'): logs.debug(u'Run with settings: {}'.format(pformat(settings))) @@ -68,8 +53,7 @@ def how_to_configure_alias(): """ colorama.init() - user_dir = setup_user_dir() - init_settings(user_dir) + settings.init() logs.how_to_configure_alias(shells.how_to_configure())