Skip to content

Commit

Permalink
switch from lockfile to filelock
Browse files Browse the repository at this point in the history
lockfile has long been deprecated, among the advantages of filelock are
that locks are automatically released on process exit
  • Loading branch information
dimbleby committed Sep 10, 2022
1 parent 6155c19 commit f0cd6b4
Show file tree
Hide file tree
Showing 7 changed files with 20 additions and 42 deletions.
24 changes: 7 additions & 17 deletions cachecontrol/caches/file_cache.py
Expand Up @@ -66,33 +66,23 @@ def __init__(
forever=False,
filemode=0o0600,
dirmode=0o0700,
use_dir_lock=None,
lock_class=None,
):

if use_dir_lock is not None and lock_class is not None:
raise ValueError("Cannot use use_dir_lock and lock_class together")

try:
from lockfile import LockFile
from lockfile.mkdirlockfile import MkdirLockFile
if lock_class is None:
from filelock import FileLock
lock_class = FileLock
except ImportError:
notice = dedent(
"""
NOTE: In order to use the FileCache you must have
lockfile installed. You can install it via pip:
pip install lockfile
filelock installed. You can install it via pip:
pip install filelock
"""
)
raise ImportError(notice)

else:
if use_dir_lock:
lock_class = MkdirLockFile

elif lock_class is None:
lock_class = LockFile

self.directory = directory
self.forever = forever
self.filemode = filemode
Expand Down Expand Up @@ -133,9 +123,9 @@ def _write(self, path, data: bytes):
except (IOError, OSError):
pass

with self.lock_class(path) as lock:
with self.lock_class(path + ".lock"):
# Write our actual file
with _secure_open_write(lock.path, self.filemode) as fh:
with _secure_open_write(path, self.filemode) as fh:
fh.write(data)

def _delete(self, key, suffix):
Expand Down
2 changes: 1 addition & 1 deletion dev_requirements.txt
Expand Up @@ -11,7 +11,7 @@ mock
cherrypy
sphinx
redis
lockfile
filelock
bumpversion
twine
black
Expand Down
6 changes: 3 additions & 3 deletions docs/storage.rst
Expand Up @@ -28,7 +28,7 @@ FileCache
=========

The `FileCache` is similar to the caching mechanism provided by
httplib2_. It requires `lockfile`_ be installed as it prevents
httplib2_. It requires `filelock`_ be installed as it prevents
multiple threads from writing to the same file at the same time.

.. note::
Expand Down Expand Up @@ -64,7 +64,7 @@ This is similar to ``FileCache``, but far more memory efficient, and therefore r

The body of the request is stored in a separate file than metadata, and streamed in and out.

It requires `lockfile`_ be installed as it prevents multiple threads from writing to the same file at the same time.
It requires `filelock`_ be installed as it prevents multiple threads from writing to the same file at the same time.

.. note::

Expand Down Expand Up @@ -127,7 +127,7 @@ Third-Party Cache Providers


.. _httplib2: https://github.com/httplib2/httplib2
.. _lockfile: https://github.com/smontanaro/pylockfile
.. _filelock: https://github.com/tox-dev/py-filelock
.. _requests 2.1: http://docs.python-requests.org/en/latest/community/updates/#id2
.. _redis: https://github.com/andymccurdy/redis-py
.. _cachecontrol-django: https://github.com/glassesdirect/cachecontrol-django
Expand Down
2 changes: 1 addition & 1 deletion docs/usage.rst
Expand Up @@ -62,7 +62,7 @@ the provided `FileCache` from CacheControl: ::

from cachecontrol import CacheControl

# NOTE: This requires lockfile be installed
# NOTE: This requires filelock be installed
from cachecontrol.caches import FileCache

sess = CacheControl(requests.Session(),
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Expand Up @@ -22,7 +22,7 @@
description="httplib2 caching for requests",
long_description=long_description,
install_requires=["requests", "msgpack>=0.5.2"],
extras_require={"filecache": ["lockfile>=0.9"], "redis": ["redis>=2.10.5"]},
extras_require={"filecache": ["filelock>=3.8.0"], "redis": ["redis>=2.10.5"]},
entry_points={"console_scripts": ["doesitcache = cachecontrol._cmd:main"]},
python_requires=">=3.6",
classifiers=[
Expand Down
24 changes: 6 additions & 18 deletions tests/test_storage_filecache.py
Expand Up @@ -14,8 +14,7 @@
import requests
from cachecontrol import CacheControl
from cachecontrol.caches import FileCache, SeparateBodyFileCache
from lockfile import LockFile
from lockfile.mkdirlockfile import MkdirLockFile
from filelock import FileLock


def randomdata():
Expand Down Expand Up @@ -94,21 +93,10 @@ def test_key_length(self, sess):
assert len(self.cache.encode(url0)) < 200
assert len(self.cache.encode(url0)) == len(self.cache.encode(url1))

def test_cant_use_dir_and_lock_class(self, tmpdir):
with pytest.raises(ValueError):
self.FileCacheClass(str(tmpdir), use_dir_lock=True, lock_class=object())

@pytest.mark.parametrize(
("value", "expected"),
[(None, LockFile), (True, MkdirLockFile), (False, LockFile)],
)
def test_simple_lockfile_arg(self, tmpdir, value, expected):
if value is not None:
cache = self.FileCacheClass(str(tmpdir), use_dir_lock=value)
else:
cache = self.FileCacheClass(str(tmpdir))

assert issubclass(cache.lock_class, expected)
def test_simple_lockfile_arg(self, tmpdir):
cache = self.FileCacheClass(str(tmpdir))

assert issubclass(cache.lock_class, FileLock)
cache.close()

def test_lock_class(self, tmpdir):
Expand All @@ -134,7 +122,7 @@ class TestFileCache(FileCacheTestsMixin):
"""
Tests for ``FileCache``.
"""

FileCacheClass = FileCache

def test_body_stored_inline(self, sess):
Expand Down
2 changes: 1 addition & 1 deletion tox.ini
Expand Up @@ -18,5 +18,5 @@ deps = pytest
mock
cherrypy
redis
lockfile
filelock
commands = py.test {posargs:tests/}

0 comments on commit f0cd6b4

Please sign in to comment.