From 8a5fab4898675cac865f1202ddaa11f197e158d3 Mon Sep 17 00:00:00 2001 From: Aaron Loo Date: Sat, 3 Apr 2021 10:01:21 -0700 Subject: [PATCH] bug fix: clearing filter caches upon loading new settings --- detect_secrets/settings.py | 34 ++++++++++++++++++++++++++++-- tests/filters/regex_filter_test.py | 16 ++++++++++++++ 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/detect_secrets/settings.py b/detect_secrets/settings.py index 1098ac055..6218eb39c 100644 --- a/detect_secrets/settings.py +++ b/detect_secrets/settings.py @@ -88,10 +88,40 @@ def transient_settings(config: Dict[str, Any]) -> Generator['Settings', None, No def cache_bust() -> None: - get_settings.cache_clear() - get_filters.cache_clear() get_plugins.cache_clear() + get_filters.cache_clear() + for path, config in get_settings().filters.items(): + # Need to also clear the individual caches (e.g. cached regex patterns). + parts = urlparse(path) + if not parts.scheme: + module_path, _ = path.rsplit('.', 1) + try: + module = import_module(module_path) + except ModuleNotFoundError: + continue + elif parts.scheme == 'file': + file_path = path[len('file://'):].split('::')[0] + try: + module = import_file_as_module(file_path) + except (FileNotFoundError, InvalidFile): + continue + else: + continue + + for item_key in dir(module): + item = getattr(module, item_key) + try: + if item.__module__ != module_path: + # Make sure we only clear the cache specific to the module. + raise AttributeError + + item.cache_clear() + except AttributeError: + pass + + get_settings.cache_clear() + class Settings: DEFAULT_FILTERS = { diff --git a/tests/filters/regex_filter_test.py b/tests/filters/regex_filter_test.py index 80f27ed52..8c0814de3 100644 --- a/tests/filters/regex_filter_test.py +++ b/tests/filters/regex_filter_test.py @@ -2,6 +2,7 @@ from detect_secrets import filters from detect_secrets.core.usage import ParserBuilder +from detect_secrets.settings import default_settings from detect_secrets.settings import get_settings @@ -86,3 +87,18 @@ def test_should_exclude_secret(parser): ], }, ] + + +def test_cache_should_be_cleared_with_different_settings(parser): + with default_settings(): + parser.parse_args([ + '--exclude-lines', 'abcde', + ]) + + assert filters.regex.should_exclude_line('abcde') is True + + # Since the regex isn't cached anymore, it needs to be regenerated. However, + # we didn't configure the regex in the settings object, so it will raise a KeyError + # when trying to obtain the patterns. + with pytest.raises(KeyError): + assert filters.regex.should_exclude_line('abcde')