From 3a851aac8cb1a252ca947c5d8ba20a2908501dce Mon Sep 17 00:00:00 2001 From: Andy Lee Date: Thu, 9 Feb 2017 11:38:44 -0800 Subject: [PATCH 1/2] Catch FileNotFoundError when opening file cache --- jedi/parser/utils.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/jedi/parser/utils.py b/jedi/parser/utils.py index 3cf318bc..82e0e349 100644 --- a/jedi/parser/utils.py +++ b/jedi/parser/utils.py @@ -10,6 +10,7 @@ import pickle from jedi import settings from jedi import debug +from jedi._compatibility import FileNotFoundError def underscore_memoization(func): @@ -127,12 +128,15 @@ class ParserPickling(object): # the pickle file is outdated return None - with open(self._get_hashed_path(path), 'rb') as f: - try: - gc.disable() - parser_cache_item = pickle.load(f) - finally: - gc.enable() + try: + with open(self._get_hashed_path(path), 'rb') as f: + try: + gc.disable() + parser_cache_item = pickle.load(f) + finally: + gc.enable() + except FileNotFoundError: + return None debug.dbg('pickle loaded: %s', path) parser_cache[path] = parser_cache_item From eb9af19559620a0b57c50c61253e66cadcee17e8 Mon Sep 17 00:00:00 2001 From: Andy Lee Date: Wed, 22 Mar 2017 15:10:16 -0700 Subject: [PATCH 2/2] Add test for loading deleted cache file --- test/test_cache.py | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/test/test_cache.py b/test/test_cache.py index 7cff4d4c..ceea3efb 100644 --- a/test/test_cache.py +++ b/test/test_cache.py @@ -3,6 +3,7 @@ Test all things related to the ``jedi.cache`` module. """ import time +from os import unlink import pytest @@ -62,6 +63,36 @@ def test_modulepickling_delete_incompatible_cache(): assert cached2 is None +@pytest.mark.usefixtures("isolated_jedi_cache") +def test_modulepickling_simulate_deleted_cache(): + """ + Tests loading from a cache file after it is deleted. + According to macOS `dev docs`__, + + Note that the system may delete the Caches/ directory to free up disk + space, so your app must be able to re-create or download these files as + needed. + + It is possible that other supported platforms treat cache files the same + way. + + __ https://developer.apple.com/library/content/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html + """ + item = ParserCacheItem('fake parser') + path = 'fake path' + + cache = ParserPicklingCls() + cache.version = 1 + cache.save_parser(path, item) + cached1 = load_stored_item(cache, path, item) + assert cached1 == item.parser + + unlink(cache._get_hashed_path(path)) + + cached2 = load_stored_item(cache, path, item) + assert cached2 is None + + @pytest.mark.skipif('True', message='Currently the star import cache is not enabled.') def test_star_import_cache_duration(): new = 0.01