Skip to content

Commit 7241a76

Browse files
committed
Sort out various lint/test issue. Do not depend directly on redis.
1 parent 84b2661 commit 7241a76

File tree

12 files changed

+166
-94
lines changed

12 files changed

+166
-94
lines changed

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ repos:
1010
hooks:
1111
- id: ruff
1212
# Using --unsafe-fixes can change code behavior
13-
args: [--fix, --exit-non-zero-on-fix, --show-fixes] # , --unsafe-fixes]
13+
args: [--fix, --exit-non-zero-on-fix, --show-fixes, --unsafe-fixes]
1414
- id: ruff-format
1515
- repo: https://github.com/tombi-toml/tombi-pre-commit
1616
rev: v0.9.16

examples/bench.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ def run():
7676
t = round(time.time()) + 1
7777
load = [(t, duration, type_) for _ in range(concurrency)]
7878
logging.info('Running %s', load)
79-
ret = [i for i in pool.map(test, load)]
79+
ret = list(pool.map(test, load))
8080
if concurrency > 1:
8181
logging.critical(
8282
'%14s %12.3fs %11s %20s %10.2f %10s %10s',

examples/plain.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@
1515
# Probably Windows.
1616
try:
1717
import msvcrt
18-
except ImportError:
18+
except ImportError as exc:
1919
# FIXME what to do on other platforms?
2020
# Just give up here.
21-
raise ImportError('getch not available')
21+
raise ImportError('getch not available') from exc
2222
else:
2323
getch = msvcrt.getch
2424
else:

examples/test-tmux.py

100644100755
Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,30 +5,30 @@
55
subprocess.check_call('tox -e py38-dj3-nocov --notest'.split())
66

77
left_commands = [
8-
'.tox/py38-dj3-nocov/bin/python examples/plain.py %s' % sys.argv[1],
9-
'.tox/py38-dj3-nocov/bin/python examples/plain.py %s' % sys.argv[1],
10-
'.tox/py38-dj3-nocov/bin/python examples/plain.py %s' % sys.argv[1],
11-
'.tox/py38-dj3-nocov/bin/python examples/plain.py %s' % sys.argv[1],
12-
'.tox/py38-dj3-nocov/bin/python examples/plain.py %s' % sys.argv[1],
13-
'.tox/py38-dj3-nocov/bin/python examples/plain.py %s' % sys.argv[1],
14-
'.tox/py38-dj3-nocov/bin/python examples/plain.py %s' % sys.argv[1],
15-
'.tox/py38-dj3-nocov/bin/python examples/plain.py %s' % sys.argv[1],
16-
'.tox/py38-dj3-nocov/bin/python examples/plain.py %s' % sys.argv[1],
17-
'.tox/py38-dj3-nocov/bin/python examples/plain.py %s' % sys.argv[1],
18-
'.tox/py38-dj3-nocov/bin/python examples/plain.py %s' % sys.argv[1],
19-
'.tox/py38-dj3-nocov/bin/python examples/plain.py %s' % sys.argv[1],
20-
'.tox/py38-dj3-nocov/bin/python examples/plain.py %s' % sys.argv[1],
8+
f'.tox/py38-dj3-nocov/bin/python examples/plain.py {sys.argv[1]}',
9+
f'.tox/py38-dj3-nocov/bin/python examples/plain.py {sys.argv[1]}',
10+
f'.tox/py38-dj3-nocov/bin/python examples/plain.py {sys.argv[1]}',
11+
f'.tox/py38-dj3-nocov/bin/python examples/plain.py {sys.argv[1]}',
12+
f'.tox/py38-dj3-nocov/bin/python examples/plain.py {sys.argv[1]}',
13+
f'.tox/py38-dj3-nocov/bin/python examples/plain.py {sys.argv[1]}',
14+
f'.tox/py38-dj3-nocov/bin/python examples/plain.py {sys.argv[1]}',
15+
f'.tox/py38-dj3-nocov/bin/python examples/plain.py {sys.argv[1]}',
16+
f'.tox/py38-dj3-nocov/bin/python examples/plain.py {sys.argv[1]}',
17+
f'.tox/py38-dj3-nocov/bin/python examples/plain.py {sys.argv[1]}',
18+
f'.tox/py38-dj3-nocov/bin/python examples/plain.py {sys.argv[1]}',
19+
f'.tox/py38-dj3-nocov/bin/python examples/plain.py {sys.argv[1]}',
20+
f'.tox/py38-dj3-nocov/bin/python examples/plain.py {sys.argv[1]}',
2121
]
2222
right_commands = left_commands
2323
session = ''
2424

2525
if right_commands:
26-
session += 'tmux selectp -t0;tmux splitw -hd -p50 "%s"; ' % right_commands[-1]
26+
session += f'tmux selectp -t0;tmux splitw -hd -p50 "{right_commands[-1]}"; '
2727
for index, command in enumerate(right_commands[:-1]):
28-
session += 'tmux selectp -t1;tmux splitw -d -p%i "%s"; ' % (100 / (len(right_commands) - index), command)
28+
session += 'tmux selectp -t1;tmux splitw -d -p%i "%s"; ' % (100 / (len(right_commands) - index), command) # noqa: UP031
2929

3030
for index, command in enumerate(left_commands[1:]):
31-
session += 'tmux selectp -t0;tmux splitw -d -p%i "%s"; ' % (100 / (len(left_commands) - index), command)
31+
session += 'tmux selectp -t0;tmux splitw -d -p%i "%s"; ' % (100 / (len(left_commands) - index), command) # noqa: UP031
3232
if left_commands:
3333
session += left_commands[0]
3434

pyproject.toml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,6 @@ classifiers = [
3434
# "Programming Language :: Python :: Implementation :: Stackless",
3535
"Topic :: Utilities",
3636
]
37-
dependencies = [
38-
"redis>=2.10.0",
39-
]
4037
dynamic = [
4138
"readme",
4239
]
@@ -52,6 +49,12 @@ dynamic = [
5249
django = [
5350
"django-redis>=3.8.0",
5451
]
52+
redis = [
53+
"redis>=2.10.0",
54+
]
55+
valkey = [
56+
"valkey",
57+
]
5558

5659
[build-system]
5760
requires = [

src/redis_lock/__init__.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ class Lock:
102102
_lock_renewal_interval: float
103103
_lock_renewal_thread: Union[threading.Thread, None]
104104

105-
def __init__(self, redis_client, name, expire=None, id=None, auto_renewal=False, strict=True, signal_expire=1000, blocking=True):
105+
def __init__(self, redis_client, name, expire=None, id=None, auto_renewal=False, signal_expire=1000, blocking=True):
106106
"""
107107
:param redis_client:
108108
An instance of :class:`~StrictRedis`.
@@ -126,8 +126,6 @@ def __init__(self, redis_client, name, expire=None, id=None, auto_renewal=False,
126126
an interval of ``expire*2/3``. If wishing to use a different renewal
127127
time, subclass Lock, call ``super().__init__()`` then set
128128
``self._lock_renewal_interval`` to your desired interval.
129-
:param strict:
130-
If set ``True`` then the ``redis_client`` needs to be an instance of ``redis.StrictRedis``.
131129
:param signal_expire:
132130
Advanced option to override signal list expiration in milliseconds. Increase it for very slow clients. Default: ``1000``.
133131
:param blocking:
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
from django.core.cache.backends.base import DEFAULT_TIMEOUT
2+
from django_valkey.cache import ValkeyCache as PlainValkeyCache
3+
4+
from redis_lock import Lock
5+
from redis_lock import reset_all
6+
7+
8+
class ValkeyCache(PlainValkeyCache):
9+
@property
10+
def __client(self):
11+
try:
12+
return self.client.get_client()
13+
except Exception as exc:
14+
raise NotImplementedError(
15+
f"ValkeyCache doesn't have a raw client: {exc}. Use 'redis_cache.client.DefaultClient' as the CLIENT_CLASS !"
16+
) from exc
17+
18+
def lock(self, key, expire=None, id=None, auto_renewal=False):
19+
return Lock(self.__client, key, expire=expire, id=id, auto_renewal=auto_renewal)
20+
21+
def locked_get_or_set(self, key, value_creator, version=None, expire=None, id=None, lock_key=None, timeout=DEFAULT_TIMEOUT):
22+
"""
23+
Fetch a given key from the cache. If the key does not exist, the key is added and
24+
set to the value returned when calling `value_creator`. The creator function
25+
is invoked inside of a lock.
26+
"""
27+
if lock_key is None:
28+
lock_key = 'get_or_set:' + key
29+
30+
val = self.get(key, version=version)
31+
if val is not None:
32+
return val
33+
34+
with self.lock(lock_key, expire=expire, id=id):
35+
# Was the value set while we were trying to acquire the lock?
36+
val = self.get(key, version=version)
37+
if val is not None:
38+
return val
39+
40+
# Nope, create value now.
41+
val = value_creator()
42+
43+
if val is None:
44+
raise ValueError('`value_creator` must return a value')
45+
46+
self.set(key, val, timeout=timeout, version=version)
47+
return val
48+
49+
def reset_all(self):
50+
"""
51+
Forcibly deletes all locks if its remains (like a crash reason). Use this with care.
52+
"""
53+
reset_all(self.__client)

tests/helper.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828

2929
eventlet.monkey_patch()
3030
else:
31-
raise RuntimeError('Invalid effect spec %r.' % effect)
31+
raise RuntimeError(f'Invalid effect spec {effect!r}.')
3232
logging.info('threading.get_ident.__module__=%s', threading.get_ident.__module__)
3333
if test_name == 'test_simple':
3434
conn = StrictRedis(unix_socket_path=redis_socket)
@@ -82,5 +82,5 @@ def cb_no_overlap():
8282
for pid in pids:
8383
os.waitpid(pid, 0)
8484
else:
85-
raise RuntimeError('Invalid test spec %r.' % test_name)
85+
raise RuntimeError(f'Invalid test spec {test_name!r}.')
8686
logging.info('DIED.')

tests/test_django_integration.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import pytest
44

5+
import redis_lock
6+
57
try:
68
import django
79
except ImportError:
@@ -14,6 +16,7 @@
1416
def redis_socket_static(tmpdir_factory):
1517
path = str(tmpdir_factory.getbasetemp() / 'redis.sock')
1618
os.environ['REDIS_SOCKET'] = path
19+
redis_lock.reset_all_script = None
1720
return path
1821

1922

@@ -37,7 +40,7 @@ def none_creator():
3740
return None
3841

3942
def assert_false_creator():
40-
assert False
43+
raise AssertionError
4144

4245
assert cache.locked_get_or_set('foobar-aosl', creator_42) == 42
4346
assert cache.locked_get_or_set('foobar-aosl', assert_false_creator) == 42
@@ -47,7 +50,7 @@ def assert_false_creator():
4750
except ValueError:
4851
pass
4952
else:
50-
assert False
53+
raise AssertionError
5154

5255

5356
@pytest.mark.skipif('not django')

tests/test_django_valkey_integration.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import pytest
44

5+
import redis_lock
6+
57
try:
68
import django
79
except ImportError:
@@ -14,6 +16,7 @@
1416
def redis_socket_static(tmpdir_factory):
1517
path = str(tmpdir_factory.getbasetemp() / 'redis.sock')
1618
os.environ['REDIS_SOCKET'] = path
19+
redis_lock.reset_all_script = None
1720
return path
1821

1922

@@ -37,7 +40,7 @@ def none_creator():
3740
return None
3841

3942
def assert_false_creator():
40-
assert False
43+
raise AssertionError
4144

4245
assert caches['valkey'].locked_get_or_set('foobar-aosl', creator_42) == 42
4346
assert caches['valkey'].locked_get_or_set('foobar-aosl', assert_false_creator) == 42
@@ -47,7 +50,7 @@ def assert_false_creator():
4750
except ValueError:
4851
pass
4952
else:
50-
assert False
53+
raise AssertionError
5154

5255

5356
@pytest.mark.skipif('not django')

0 commit comments

Comments
 (0)