feat: add option to run with cache support

fixes #601
This commit is contained in:
Noortheen Raja 2021-01-15 01:08:16 +05:30
parent 6de8252c03
commit 0b20e68e12
4 changed files with 66 additions and 0 deletions

29
src/flake8/cacher.py Normal file
View file

@ -0,0 +1,29 @@
"""Cache files manager"""
import hashlib
import os
import pickle
class Cacher(object):
def __init__(self, file_name, cache_path):
# type: (str, str) -> None
self.file_name = file_name
enc = hashlib.md5(file_name.encode())
self.cache_path = os.path.join(cache_path, str(enc.hexdigest()))
def get(self):
if not os.path.exists(self.cache_path):
return
with open(self.cache_path, "rb") as fr:
mtime, results = pickle.load(fr)
# if the mtime doesn't change then return cache.
# otherwise it is invalid
current_mtime = os.path.getmtime(self.file_name)
if mtime == current_mtime:
return results
def save(self, results):
"""saves the given result to the cache file"""
with open(self.cache_path, "wb") as fw:
current_mtime = os.path.getmtime(self.file_name)
pickle.dump((current_mtime, results), fw)

View file

@ -14,6 +14,7 @@ except ImportError:
multiprocessing = None # type: ignore multiprocessing = None # type: ignore
from flake8 import defaults from flake8 import defaults
from flake8 import cacher
from flake8 import exceptions from flake8 import exceptions
from flake8 import processor from flake8 import processor
from flake8 import utils from flake8 import utils
@ -360,6 +361,7 @@ class FileChecker(object):
self.options = options self.options = options
self.filename = filename self.filename = filename
self.checks = checks self.checks = checks
self.cacher = cacher.Cacher(filename, self.options.cache_location)
# fmt: off # fmt: off
self.results = [] # type: List[Tuple[str, int, int, str, Optional[str]]] # noqa: E501 self.results = [] # type: List[Tuple[str, int, int, str, Optional[str]]] # noqa: E501
# fmt: on # fmt: on
@ -583,6 +585,22 @@ class FileChecker(object):
self.run_logical_checks() self.run_logical_checks()
def run_checks(self): def run_checks(self):
"""cached wrapper of self.run_checks"""
# handle both cases where cache is enabled/disabled or invalid
cache_available = False
if self.options.cache:
saved = self.cacher.get()
if saved is not None:
self.filename, self.results, self.statistics = saved
cache_available = True
if cache_available is False:
result = self._run_checks()
if self.options.cache:
self.cacher.save(result)
return self.filename, self.results, self.statistics
def _run_checks(self):
"""Run checks against the file.""" """Run checks against the file."""
try: try:
self.process_tokens() self.process_tokens()

View file

@ -3,6 +3,7 @@ from __future__ import print_function
import argparse import argparse
import logging import logging
import os
import sys import sys
import time import time
from typing import Dict, List, Optional, Set, Tuple from typing import Dict, List, Optional, Set, Tuple
@ -336,6 +337,9 @@ class Application(object):
self.make_formatter() self.make_formatter()
self.make_guide() self.make_guide()
self.make_file_checker_manager() self.make_file_checker_manager()
if self.options.cache:
if not os.path.exists(self.options.cache_location):
os.makedirs(self.options.cache_location)
def report(self): def report(self):
"""Report errors, statistics, and benchmarks.""" """Report errors, statistics, and benchmarks."""

View file

@ -298,6 +298,21 @@ def register_default_options(option_manager):
) )
# Flake8 options # Flake8 options
add_option(
"--cache",
default=False,
parse_from_config=False,
action="store_true",
help="Cache flake8 results on consecutive runs.",
)
add_option(
"--cache-location",
default=".cache/flake8",
parse_from_config=True,
help="Location to store cached results.",
)
add_option( add_option(
"--enable-extensions", "--enable-extensions",
default="", default="",