diff --git a/libs/fcache/cache.py b/libs/fcache/cache.py index f6f1d9cb2..32a8a769b 100644 --- a/libs/fcache/cache.py +++ b/libs/fcache/cache.py @@ -40,7 +40,7 @@ class FileCache(MutableMapping): :param str appname: The app/script the cache should be associated with. :param str flag: How the cache should be opened. See below for details. - :param mode: The Unix mode for the cache files. + :param mode: The Unix mode for the cache files or False to prevent changing permissions. :param str keyencoding: The encoding the keys use, defaults to 'utf-8'. This is used if *serialize* is ``False``; the keys are treated as :class:`bytes` objects. @@ -247,7 +247,8 @@ class FileCache(MutableMapping): with os.fdopen(fh, self._flag) as f: f.write(self._dumps(bytesvalue)) rename(tmp, filename) - os.chmod(filename, self._mode) + if self._mode: + os.chmod(filename, self._mode) def _read_from_file(self, filename): """Read data from filename.""" @@ -256,7 +257,7 @@ class FileCache(MutableMapping): return self._loads(f.read()) except (IOError, OSError): logger.warning('Error opening file: {}'.format(filename)) - raise + return None def __setitem__(self, key, value): ekey = self._encode_key(key) diff --git a/libs/fcache/posixemulation.py b/libs/fcache/posixemulation.py index cf9ac63b7..03d6982c3 100644 --- a/libs/fcache/posixemulation.py +++ b/libs/fcache/posixemulation.py @@ -46,7 +46,15 @@ if os.name == 'nt': # pragma: no cover dst = unicode(dst, sys.getfilesystemencoding()) if _rename_atomic(src, dst): return True - return _MoveFileEx(src, dst, _MOVEFILE_REPLACE_EXISTING | _MOVEFILE_WRITE_THROUGH) + retry = 0 + rv = False + while not rv and retry < 100: + rv = _MoveFileEx(src, dst, _MOVEFILE_REPLACE_EXISTING | + _MOVEFILE_WRITE_THROUGH) + if not rv: + time.sleep(0.001) + retry += 1 + return rv # new in Vista and Windows Server 2008 _CreateTransaction = ctypes.windll.ktmw32.CreateTransaction @@ -60,11 +68,18 @@ if os.name == 'nt': # pragma: no cover if ta == -1: return False try: - rv = _MoveFileTransacted(src, dst, None, None, - _MOVEFILE_REPLACE_EXISTING | - _MOVEFILE_WRITE_THROUGH, ta) - if rv: - rv = _CommitTransaction(ta) + retry = 0 + rv = False + while not rv and retry < 100: + rv = _MoveFileTransacted(src, dst, None, None, + _MOVEFILE_REPLACE_EXISTING | + _MOVEFILE_WRITE_THROUGH, ta) + if rv: + rv = _CommitTransaction(ta) + break + else: + time.sleep(0.001) + retry += 1 return rv finally: _CloseHandle(ta) @@ -77,7 +92,7 @@ if os.name == 'nt': # pragma: no cover return # Fall back to "move away and replace" try: - shutil.move(src, dst) + os.rename(src, dst) except OSError as e: if e.errno != errno.EEXIST: raise diff --git a/libs/subzero/cache_backends/file.py b/libs/subzero/cache_backends/file.py index d72d7b84a..a97c8fad2 100644 --- a/libs/subzero/cache_backends/file.py +++ b/libs/subzero/cache_backends/file.py @@ -8,7 +8,8 @@ class SZFileBackend(CacheBackend): def __init__(self, arguments): self._cache = FileCache(arguments.pop("appname", None), flag=arguments.pop("flag", "c"), serialize=arguments.pop("serialize", True), - app_cache_dir=arguments.pop("app_cache_dir", None)) + app_cache_dir=arguments.pop("app_cache_dir", None), + mode=False) def get(self, key): value = self._cache.get(key, NO_VALUE) diff --git a/libs/version.txt b/libs/version.txt index 8316736be..13afd5a8e 100644 --- a/libs/version.txt +++ b/libs/version.txt @@ -128,7 +128,7 @@ webencodings==0.5.1 # Required-by: subzero backports.functools-lru-cache==1.6.4 -fcache==0.4.7 +fcache==0.4.7 # https://github.com/tsroten/fcache/pull/34 json_tricks==3.16.1 tld==0.12.6 # https://github.com/barseghyanartur/tld/pull/119