1
0
mirror of https://github.com/nvbn/thefuck.git synced 2025-03-20 09:39:01 +00:00

#215 Use memoize decorator for caching

This commit is contained in:
nvbn 2015-05-22 17:07:01 +03:00
parent 84a28d8c73
commit 190e47ecdb
3 changed files with 54 additions and 38 deletions

View File

@ -1,6 +1,6 @@
import pytest import pytest
from mock import Mock from mock import Mock
from thefuck.utils import sudo_support, wrap_settings from thefuck.utils import sudo_support, wrap_settings, memoize
from thefuck.types import Settings from thefuck.types import Settings
from tests.utils import Command from tests.utils import Command
@ -24,3 +24,11 @@ def test_sudo_support(return_value, command, called, result):
fn = Mock(return_value=return_value, __name__='') fn = Mock(return_value=return_value, __name__='')
assert sudo_support(fn)(Command(command), None) == result assert sudo_support(fn)(Command(command), None) == result
fn.assert_called_once_with(Command(called), None) fn.assert_called_once_with(Command(called), None)
def test_memoize():
fn = Mock(__name__='fn')
memoized = memoize(fn)
memoized()
memoized()
fn.assert_called_once_with()

View File

@ -8,14 +8,13 @@ from subprocess import Popen, PIPE
from time import time from time import time
import os import os
from psutil import Process from psutil import Process
from .utils import DEVNULL from .utils import DEVNULL, memoize
class Generic(object): class Generic(object):
_aliases = {}
def get_aliases(self): def get_aliases(self):
return self._aliases return {}
def _expand_aliases(self, command_script): def _expand_aliases(self, command_script):
aliases = self.get_aliases() aliases = self.get_aliases()
@ -63,17 +62,15 @@ class Bash(Generic):
value = value[1:-1] value = value[1:-1]
return name, value return name, value
@memoize
def get_aliases(self): def get_aliases(self):
if not self._aliases:
proc = Popen('bash -ic alias', stdout=PIPE, stderr=DEVNULL, proc = Popen('bash -ic alias', stdout=PIPE, stderr=DEVNULL,
shell=True) shell=True)
self._aliases = dict( return dict(
self._parse_alias(alias) self._parse_alias(alias)
for alias in proc.stdout.read().decode('utf-8').split('\n') for alias in proc.stdout.read().decode('utf-8').split('\n')
if alias and '=' in alias) if alias and '=' in alias)
return self._aliases
def _get_history_file_name(self): def _get_history_file_name(self):
return os.environ.get("HISTFILE", return os.environ.get("HISTFILE",
os.path.expanduser('~/.bash_history')) os.path.expanduser('~/.bash_history'))
@ -97,14 +94,12 @@ class Fish(Generic):
" end\n" " end\n"
"end") "end")
@memoize
def get_aliases(self): def get_aliases(self):
if not self._aliases:
proc = Popen('fish -ic functions', stdout=PIPE, stderr=DEVNULL, proc = Popen('fish -ic functions', stdout=PIPE, stderr=DEVNULL,
shell=True) shell=True)
functions = proc.stdout.read().decode('utf-8').strip().split('\n') functions = proc.stdout.read().decode('utf-8').strip().split('\n')
self._aliases = dict((function, function) for function in functions) return {function: function for function in functions}
return self._aliases
def _get_history_file_name(self): def _get_history_file_name(self):
return os.path.expanduser('~/.config/fish/fish_history') return os.path.expanduser('~/.config/fish/fish_history')
@ -126,17 +121,15 @@ class Zsh(Generic):
value = value[1:-1] value = value[1:-1]
return name, value return name, value
@memoize
def get_aliases(self): def get_aliases(self):
if not self._aliases:
proc = Popen('zsh -ic alias', stdout=PIPE, stderr=DEVNULL, proc = Popen('zsh -ic alias', stdout=PIPE, stderr=DEVNULL,
shell=True) shell=True)
self._aliases = dict( return dict(
self._parse_alias(alias) self._parse_alias(alias)
for alias in proc.stdout.read().decode('utf-8').split('\n') for alias in proc.stdout.read().decode('utf-8').split('\n')
if alias and '=' in alias) if alias and '=' in alias)
return self._aliases
def _get_history_file_name(self): def _get_history_file_name(self):
return os.environ.get("HISTFILE", return os.environ.get("HISTFILE",
os.path.expanduser('~/.zsh_history')) os.path.expanduser('~/.zsh_history'))
@ -153,17 +146,15 @@ class Tcsh(Generic):
name, value = alias.split("\t", 1) name, value = alias.split("\t", 1)
return name, value return name, value
@memoize
def get_aliases(self): def get_aliases(self):
if not self._aliases:
proc = Popen('tcsh -ic alias', stdout=PIPE, stderr=DEVNULL, proc = Popen('tcsh -ic alias', stdout=PIPE, stderr=DEVNULL,
shell=True) shell=True)
self._aliases = dict( return dict(
self._parse_alias(alias) self._parse_alias(alias)
for alias in proc.stdout.read().decode('utf-8').split('\n') for alias in proc.stdout.read().decode('utf-8').split('\n')
if alias and '\t' in alias) if alias and '\t' in alias)
return self._aliases
def _get_history_file_name(self): def _get_history_file_name(self):
return os.environ.get("HISTFILE", return os.environ.get("HISTFILE",
os.path.expanduser('~/.history')) os.path.expanduser('~/.history'))

View File

@ -1,5 +1,6 @@
from functools import wraps from functools import wraps
import os import os
import pickle
import six import six
from .types import Command from .types import Command
@ -62,3 +63,19 @@ def sudo_support(fn):
else: else:
return result return result
return wrapper return wrapper
def memoize(fn):
"""Caches previous calls to the function."""
memo = {}
@wraps(fn)
def wrapper(*args, **kwargs):
key = pickle.dumps((args, kwargs))
if key not in memo:
memo[key] = fn(*args, **kwargs)
return memo[key]
return wrapper