Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit da8c435

Browse files
author
Anthony Sottile
committed
Improve performance on pre-commit -r pyflakes by 40%
1 parent 356e4ba commit da8c435

3 files changed

Lines changed: 59 additions & 5 deletions

File tree

pre_commit/git.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
import os
22
import pkg_resources
3-
43
from plumbum import local
54

5+
from pre_commit.util import memoize_by_cwd
6+
67

7-
# TODO: optimization: memoize based on local.cwd.getpath()
8+
@memoize_by_cwd
89
def get_root():
910
return local['git']['rev-parse', '--show-toplevel']().strip()
1011

1112

13+
@memoize_by_cwd
1214
def get_pre_commit_path():
1315
return os.path.join(get_root(), '.git/hooks/pre-commit')
1416

@@ -25,4 +27,4 @@ def remove_pre_commit():
2527

2628
def get_head_sha(git_repo_path):
2729
with local.cwd(git_repo_path):
28-
return (local['git']['rev-parse', 'HEAD'])().strip()
30+
return (local['git']['rev-parse', 'HEAD'])().strip()

pre_commit/util.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11

2+
import functools
3+
import os
4+
5+
26
class cached_property(object):
37
"""Like @property, but caches the value."""
48

@@ -14,3 +18,19 @@ def __get__(self, obj, cls):
1418
value = self._func(obj)
1519
obj.__dict__[self.__name__] = value
1620
return value
21+
22+
23+
def memoize_by_cwd(func):
24+
"""Memoize a function call based on os.getcwd()."""
25+
cache = {}
26+
@functools.wraps(func)
27+
def wrapper(*args):
28+
cwd = os.getcwd()
29+
key = (cwd,) + args
30+
try:
31+
return cache[key]
32+
except KeyError:
33+
ret = cache[key] = func(*args)
34+
return ret
35+
36+
return wrapper

tests/util_test.py

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11

22
import pytest
3-
import time
3+
import random
4+
from plumbum import local
45

56
from pre_commit.util import cached_property
7+
from pre_commit.util import memoize_by_cwd
68

79

810
@pytest.fixture
911
def class_with_cached_property():
1012
class Foo(object):
1113
@cached_property
1214
def foo(self):
13-
return "Foo" + str(time.time())
15+
return "Foo" + str(random.getrandbits(64))
1416

1517
return Foo
1618

@@ -27,3 +29,33 @@ def test_unbound_cached_property(class_with_cached_property):
2729
prop = class_with_cached_property.foo
2830
assert isinstance(prop, cached_property)
2931

32+
33+
@pytest.fixture
34+
def memoized_by_cwd():
35+
@memoize_by_cwd
36+
def func(arg):
37+
return arg + str(random.getrandbits(64))
38+
39+
return func
40+
41+
42+
def test_memoized_by_cwd_returns_same_twice_in_a_row(memoized_by_cwd):
43+
ret = memoized_by_cwd('baz')
44+
ret2 = memoized_by_cwd('baz')
45+
assert ret is ret2
46+
47+
48+
def test_memoized_by_cwd_returns_different_for_different_args(memoized_by_cwd):
49+
ret = memoized_by_cwd('baz')
50+
ret2 = memoized_by_cwd('bar')
51+
assert ret.startswith('baz')
52+
assert ret2.startswith('bar')
53+
assert ret != ret2
54+
55+
56+
def test_memoized_by_cwd_changes_with_different_cwd(memoized_by_cwd):
57+
ret = memoized_by_cwd('baz')
58+
with local.cwd('.git'):
59+
ret2 = memoized_by_cwd('baz')
60+
61+
assert ret != ret2

0 commit comments

Comments
 (0)