1
0
mirror of https://github.com/nvbn/thefuck.git synced 2025-01-18 20:11:17 +00:00

Don't mess with inheritance for filling settings

This commit is contained in:
nvbn 2015-04-22 22:29:23 +02:00
parent 69a9516477
commit 0553d57ec1
4 changed files with 74 additions and 70 deletions

View File

@ -19,8 +19,8 @@ def test_default():
def test_settings_defaults(): def test_settings_defaults():
with patch('thefuck.conf.load_source', return_value=object()), \ with patch('thefuck.conf.load_source', return_value=object()), \
patch('thefuck.conf.os.environ', new_callable=lambda: {}): patch('thefuck.conf.os.environ', new_callable=lambda: {}):
for key, val in conf.Settings.defaults.items(): for key, val in conf.DEFAULT_SETTINGS.items():
assert getattr(conf.Settings(Mock()), key) == val assert getattr(conf.get_settings(Mock()), key) == val
def test_settings_from_file(): def test_settings_from_file():
@ -29,7 +29,7 @@ def test_settings_from_file():
require_confirmation=True, require_confirmation=True,
no_colors=True)), \ no_colors=True)), \
patch('thefuck.conf.os.environ', new_callable=lambda: {}): patch('thefuck.conf.os.environ', new_callable=lambda: {}):
settings = conf.Settings(Mock()) settings = conf.get_settings(Mock())
assert settings.rules == ['test'] assert settings.rules == ['test']
assert settings.wait_command == 10 assert settings.wait_command == 10
assert settings.require_confirmation is True assert settings.require_confirmation is True
@ -42,7 +42,7 @@ def test_settings_from_file_with_DEFAULT():
require_confirmation=True, require_confirmation=True,
no_colors=True)), \ no_colors=True)), \
patch('thefuck.conf.os.environ', new_callable=lambda: {}): patch('thefuck.conf.os.environ', new_callable=lambda: {}):
settings = conf.Settings(Mock()) settings = conf.get_settings(Mock())
assert settings.rules == conf.DEFAULT + ['test'] assert settings.rules == conf.DEFAULT + ['test']
@ -54,7 +54,7 @@ def test_settings_from_env():
'THEFUCK_WAIT_COMMAND': '55', 'THEFUCK_WAIT_COMMAND': '55',
'THEFUCK_REQUIRE_CONFIRMATION': 'true', 'THEFUCK_REQUIRE_CONFIRMATION': 'true',
'THEFUCK_NO_COLORS': 'false'}): 'THEFUCK_NO_COLORS': 'false'}):
settings = conf.Settings(Mock()) settings = conf.get_settings(Mock())
assert settings.rules == ['bash', 'lisp'] assert settings.rules == ['bash', 'lisp']
assert settings.wait_command == 55 assert settings.wait_command == 55
assert settings.require_confirmation is True assert settings.require_confirmation is True
@ -64,12 +64,12 @@ def test_settings_from_env():
def test_settings_from_env_with_DEFAULT(): def test_settings_from_env_with_DEFAULT():
with patch('thefuck.conf.load_source', return_value=Mock()), \ with patch('thefuck.conf.load_source', return_value=Mock()), \
patch('thefuck.conf.os.environ', new_callable=lambda: {'THEFUCK_RULES': 'DEFAULT:bash:lisp'}): patch('thefuck.conf.os.environ', new_callable=lambda: {'THEFUCK_RULES': 'DEFAULT:bash:lisp'}):
settings = conf.Settings(Mock()) settings = conf.get_settings(Mock())
assert settings.rules == conf.DEFAULT + ['bash', 'lisp'] assert settings.rules == conf.DEFAULT + ['bash', 'lisp']
def test_update_settings(): def test_update_settings():
settings = conf.BaseSettings({'key': 'val'}) settings = conf.Settings({'key': 'val'})
new_settings = settings.update(key='new-val') new_settings = settings.update(key='new-val')
assert new_settings.key == 'new-val' assert new_settings.key == 'new-val'
assert settings.key == 'val' assert settings.key == 'val'

View File

@ -1,15 +1,15 @@
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.main import Command
from thefuck.conf import BaseSettings from thefuck.conf import Settings
def test_wrap_settings(): def test_wrap_settings():
fn = lambda _, settings: settings._conf fn = lambda _, settings: settings._conf
assert wrap_settings({'key': 'val'})(fn)(None, BaseSettings({})) \ 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)(
None, BaseSettings({'key': 'val'})) == {'key': 'new-val'} None, Settings({'key': 'val'})) == {'key': 'new-val'}
def test_sudo_support(): def test_sudo_support():

View File

@ -40,7 +40,7 @@ class _DefaultRules(RulesList):
DEFAULT = _DefaultRules([]) DEFAULT = _DefaultRules([])
class BaseSettings(object): class Settings(object):
def __init__(self, conf): def __init__(self, conf):
self._conf = conf self._conf = conf
@ -51,70 +51,74 @@ class BaseSettings(object):
"""Returns new settings with new values from `kwargs`.""" """Returns new settings with new values from `kwargs`."""
conf = copy(self._conf) conf = copy(self._conf)
conf.update(kwargs) conf.update(kwargs)
return BaseSettings(conf) return Settings(conf)
class Settings(BaseSettings): DEFAULT_SETTINGS = {'rules': DEFAULT,
"""Settings loaded from defaults/file/env.""" 'wait_command': 3,
defaults = {'rules': DEFAULT, 'require_confirmation': False,
'wait_command': 3, 'no_colors': False}
'require_confirmation': False,
'no_colors': False}
env_to_attr = {'THEFUCK_RULES': 'rules', ENV_TO_ATTR = {'THEFUCK_RULES': 'rules',
'THEFUCK_WAIT_COMMAND': 'wait_command', 'THEFUCK_WAIT_COMMAND': 'wait_command',
'THEFUCK_REQUIRE_CONFIRMATION': 'require_confirmation', 'THEFUCK_REQUIRE_CONFIRMATION': 'require_confirmation',
'THEFUCK_NO_COLORS': 'no_colors'} 'THEFUCK_NO_COLORS': 'no_colors'}
def __init__(self, user_dir):
super(Settings, self).__init__(self._load_conf(user_dir))
def _load_conf(self, user_dir): def _settings_from_file(user_dir):
conf = copy(self.defaults) """Loads settings from file."""
try: settings = load_source('settings',
conf.update(self._load_from_file(user_dir)) text_type(user_dir.joinpath('settings.py')))
except: return {key: getattr(settings, key)
logs.exception("Can't load settings from file", for key in DEFAULT_SETTINGS.keys()
sys.exc_info(), if hasattr(settings, key)}
BaseSettings(conf))
try:
conf.update(self._load_from_env())
except:
logs.exception("Can't load settings from env",
sys.exc_info(),
BaseSettings(conf))
if not isinstance(conf['rules'], RulesList):
conf['rules'] = RulesList(conf['rules'])
return conf
def _load_from_file(self, 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 self.defaults.keys()
if hasattr(settings, key)}
def _load_from_env(self): def _rules_from_env(val):
"""Loads settings from env.""" """Transforms rules list from env-string to python."""
return {attr: self._val_from_env(env, attr) val = val.split(':')
for env, attr in self.env_to_attr.items() if 'DEFAULT' in val:
if env in os.environ} val = DEFAULT + [rule for rule in val if rule != 'DEFAULT']
return val
def _val_from_env(self, env, attr):
"""Transforms env-strings to python."""
val = os.environ[env]
if attr == 'rules':
val = self._rules_from_env(val)
elif attr == 'wait_command':
val = int(val)
elif attr in ('require_confirmation', 'no_colors'):
val = val.lower() == 'true'
return val
def _rules_from_env(self, val): def _val_from_env(env, attr):
"""Transforms rules list from env-string to python.""" """Transforms env-strings to python."""
val = val.split(':') val = os.environ[env]
if 'DEFAULT' in val: if attr == 'rules':
val = DEFAULT + [rule for rule in val if rule != 'DEFAULT'] val = _rules_from_env(val)
return val elif attr == 'wait_command':
val = int(val)
elif attr in ('require_confirmation', 'no_colors'):
val = val.lower() == 'true'
return val
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 get_settings(user_dir):
"""Returns settings filled with values from `settings.py` and env."""
conf = copy(DEFAULT_SETTINGS)
try:
conf.update(_settings_from_file(user_dir))
except Exception:
logs.exception("Can't load settings from file",
sys.exc_info(),
Settings(conf))
try:
conf.update(_settings_from_env())
except Exception:
logs.exception("Can't load settings from env",
sys.exc_info(),
Settings(conf))
if not isinstance(conf['rules'], RulesList):
conf['rules'] = RulesList(conf['rules'])
return Settings(conf)

View File

@ -121,7 +121,7 @@ def is_second_run(command):
def main(): def main():
colorama.init() colorama.init()
user_dir = setup_user_dir() user_dir = setup_user_dir()
settings = conf.Settings(user_dir) settings = conf.get_settings(user_dir)
command = get_command(settings, sys.argv) command = get_command(settings, sys.argv)
if command: if command: