Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-dogpile.cache for
openSUSE:Factory checked in at 2024-03-18 16:47:27
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-dogpile.cache (Old)
and /work/SRC/openSUSE:Factory/.python-dogpile.cache.new.1905 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-dogpile.cache"
Mon Mar 18 16:47:27 2024 rev:42 rq:1158983 version:1.3.2
Changes:
--------
---
/work/SRC/openSUSE:Factory/python-dogpile.cache/python-dogpile.cache.changes
2024-02-08 19:03:33.822131284 +0100
+++
/work/SRC/openSUSE:Factory/.python-dogpile.cache.new.1905/python-dogpile.cache.changes
2024-03-18 16:47:52.482295886 +0100
@@ -1,0 +2,11 @@
+Mon Mar 18 12:15:51 UTC 2024 - Dirk Müller <[email protected]>
+
+- update to 1.3.2:
+ * Added a new backend RedisClusterBackend, allowing support for
+ Redis Cluster.
+ * Added support for additional Redis client parameters
+ RedisBackend.socket_connect_timeout,
+ RedisBackend.socket_keepalive and
+ RedisBackend.socket_keepalive_options.
+
+-------------------------------------------------------------------
Old:
----
dogpile.cache-1.3.1.tar.gz
New:
----
dogpile.cache-1.3.2.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-dogpile.cache.spec ++++++
--- /var/tmp/diff_new_pack.OEBt85/_old 2024-03-18 16:47:53.126319630 +0100
+++ /var/tmp/diff_new_pack.OEBt85/_new 2024-03-18 16:47:53.130319777 +0100
@@ -18,10 +18,10 @@
%{?sle15_python_module_pythons}
Name: python-dogpile.cache
-Version: 1.3.1
+Version: 1.3.2
Release: 0
%define modname dogpile.cache
-%define modver 1_3_1
+%define modver 1_3_2
Summary: A caching front-end based on the Dogpile lock
License: BSD-3-Clause
URL: https://github.com/sqlalchemy/dogpile.cache
++++++ dogpile.cache-1.3.1.tar.gz -> dogpile.cache-1.3.2.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/dogpile.cache-rel_1_3_1/docs/build/changelog.rst
new/dogpile.cache-rel_1_3_2/docs/build/changelog.rst
--- old/dogpile.cache-rel_1_3_1/docs/build/changelog.rst 2024-02-07
23:54:36.000000000 +0100
+++ new/dogpile.cache-rel_1_3_2/docs/build/changelog.rst 2024-02-21
20:40:59.000000000 +0100
@@ -3,6 +3,28 @@
=========
.. changelog::
+ :version: 1.3.2
+ :released: Wed Feb 21 2024
+
+ .. change::
+ :tags: usecase, redis
+ :tickets: 250
+
+ Added a new backend :class:`.RedisClusterBackend`, allowing support for
+ Redis Cluster. Pull request courtesy Maël Naccache Tüfekçi.
+
+
+ .. change::
+ :tags: usecase, redis
+ :tickets: 252
+
+ Added support for additional Redis client parameters
+ :paramref:`.RedisBackend.socket_connect_timeout`,
+ :paramref:`.RedisBackend.socket_keepalive` and
+ :paramref:`.RedisBackend.socket_keepalive_options`. Pull request
courtesy
+ Takashi Kajinami.
+
+.. changelog::
:version: 1.3.1
:released: Wed Feb 7 2024
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/dogpile.cache-rel_1_3_1/docs/build/conf.py
new/dogpile.cache-rel_1_3_2/docs/build/conf.py
--- old/dogpile.cache-rel_1_3_1/docs/build/conf.py 2024-02-07
23:54:36.000000000 +0100
+++ new/dogpile.cache-rel_1_3_2/docs/build/conf.py 2024-02-21
20:40:59.000000000 +0100
@@ -74,7 +74,7 @@
# The short X.Y version.
version = dogpile.__version__
# The full version, including alpha/beta/rc tags.
-release = "1.3.1"
+release = "1.3.2"
# The language for content autogenerated by Sphinx. Refer to documentation
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/dogpile.cache-rel_1_3_1/dogpile/__init__.py
new/dogpile.cache-rel_1_3_2/dogpile/__init__.py
--- old/dogpile.cache-rel_1_3_1/dogpile/__init__.py 2024-02-07
23:54:36.000000000 +0100
+++ new/dogpile.cache-rel_1_3_2/dogpile/__init__.py 2024-02-21
20:40:59.000000000 +0100
@@ -1,4 +1,4 @@
-__version__ = "1.3.1"
+__version__ = "1.3.2"
from .lock import Lock # noqa
from .lock import NeedRegenerationException # noqa
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/dogpile.cache-rel_1_3_1/dogpile/cache/backends/__init__.py
new/dogpile.cache-rel_1_3_2/dogpile/cache/backends/__init__.py
--- old/dogpile.cache-rel_1_3_1/dogpile/cache/backends/__init__.py
2024-02-07 23:54:36.000000000 +0100
+++ new/dogpile.cache-rel_1_3_2/dogpile/cache/backends/__init__.py
2024-02-21 20:40:59.000000000 +0100
@@ -45,3 +45,8 @@
"dogpile.cache.backends.redis",
"RedisSentinelBackend",
)
+register_backend(
+ "dogpile.cache.redis_cluster",
+ "dogpile.cache.backends.redis",
+ "RedisClusterBackend",
+)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/dogpile.cache-rel_1_3_1/dogpile/cache/backends/redis.py
new/dogpile.cache-rel_1_3_2/dogpile/cache/backends/redis.py
--- old/dogpile.cache-rel_1_3_1/dogpile/cache/backends/redis.py 2024-02-07
23:54:36.000000000 +0100
+++ new/dogpile.cache-rel_1_3_2/dogpile/cache/backends/redis.py 2024-02-21
20:40:59.000000000 +0100
@@ -18,12 +18,12 @@
# delayed import
redis = None # noqa F811
-__all__ = ("RedisBackend", "RedisSentinelBackend")
+__all__ = ("RedisBackend", "RedisSentinelBackend", "RedisClusterBackend")
class RedisBackend(BytesBackend):
r"""A `Redis <http://redis.io/>`_ backend, using the
- `redis-py <http://pypi.python.org/pypi/redis/>`_ backend.
+ `redis-py <http://pypi.python.org/pypi/redis/>`_ driver.
Example configuration::
@@ -52,6 +52,8 @@
:param username: string, default is no username.
+ .. versionadded:: 1.3.1
+
:param password: string, default is no password.
:param port: integer, default is ``6379``.
@@ -74,6 +76,21 @@
:param socket_timeout: float, seconds for socket timeout.
Default is None (no timeout).
+ :param socket_connect_timeout: float, seconds for socket connection
+ timeout. Default is None (no timeout).
+
+ .. versionadded:: 1.3.2
+
+ :param socket_keepalive: boolean, when True, socket keepalive is enabled.
+ Default is False.
+
+ .. versionadded:: 1.3.2
+
+ :param socket_keepalive_options: dict, socket keepalive options.
+ Default is None (no options).
+
+ .. versionadded:: 1.3.2
+
:param lock_sleep: integer, number of seconds to sleep when failed to
acquire a lock. This argument is only valid when
``distributed_lock`` is ``True``.
@@ -95,9 +112,10 @@
directly, including parameters like ``ssl``, ``ssl_certfile``,
``charset``, etc.
- .. versionadded:: 1.1.6 Added ``connection_kwargs`` parameter.
+ .. versionadded:: 1.1.6
+
+
- .. versionadded:: 1.3.1 Added ``username`` parameter.
"""
@@ -112,6 +130,13 @@
self.db = arguments.pop("db", 0)
self.distributed_lock = arguments.pop("distributed_lock", False)
self.socket_timeout = arguments.pop("socket_timeout", None)
+ self.socket_connect_timeout = arguments.pop(
+ "socket_connect_timeout", None
+ )
+ self.socket_keepalive = arguments.pop("socket_keepalive", False)
+ self.socket_keepalive_options = arguments.pop(
+ "socket_keepalive_options", None
+ )
self.lock_timeout = arguments.pop("lock_timeout", None)
self.lock_sleep = arguments.pop("lock_sleep", 0.1)
self.thread_local_lock = arguments.pop("thread_local_lock", True)
@@ -144,8 +169,16 @@
else:
args = {}
args.update(self.connection_kwargs)
- if self.socket_timeout:
+ if self.socket_timeout is not None:
args["socket_timeout"] = self.socket_timeout
+ if self.socket_connect_timeout is not None:
+ args["socket_connect_timeout"] = self.socket_connect_timeout
+ if self.socket_keepalive:
+ args["socket_keepalive"] = True
+ if self.socket_keepalive_options is not None:
+ args[
+ "socket_keepalive_options"
+ ] = self.socket_keepalive_options
if self.url is not None:
args.update(url=self.url)
@@ -227,8 +260,9 @@
class RedisSentinelBackend(RedisBackend):
"""A `Redis <http://redis.io/>`_ backend, using the
- `redis-py <http://pypi.python.org/pypi/redis/>`_ backend.
- It will use the Sentinel of a Redis cluster.
+ `redis-py <http://pypi.python.org/pypi/redis/>`_ driver.
+ This backend is to be used when using
+ `Redis Sentinel <https://redis.io/docs/management/sentinel/>`_.
.. versionadded:: 1.0.0
@@ -255,6 +289,8 @@
:param username: string, default is no username.
+ .. versionadded:: 1.3.1
+
:param password: string, default is no password.
:param db: integer, default is ``0``.
@@ -275,6 +311,21 @@
:param socket_timeout: float, seconds for socket timeout.
Default is None (no timeout).
+ .. versionadded:: 1.3.2
+
+ :param socket_connect_timeout: float, seconds for socket connection
+ timeout. Default is None (no timeout).
+
+ .. versionadded:: 1.3.2
+
+ :param socket_keepalive: boolean, when True, socket keepalive is enabled
+ Default is False.
+
+ .. versionadded:: 1.3.2
+
+ :param socket_keepalive_options: dict, socket keepalive options.
+ Default is {} (no options).
+
:param sentinels: is a list of sentinel nodes. Each node is represented by
a pair (hostname, port).
Default is None (not in sentinel mode).
@@ -302,7 +353,6 @@
asynchronous runners, as they run in a different thread than the one
used to create the lock.
- .. versionadded:: 1.3.1 Added ``username`` parameter.
"""
@@ -342,6 +392,16 @@
sentinel_kwargs.setdefault("db", self.db)
if self.socket_timeout is not None:
connection_kwargs.setdefault("socket_timeout", self.socket_timeout)
+ if self.socket_connect_timeout is not None:
+ connection_kwargs.setdefault(
+ "socket_connect_timeout", self.socket_connect_timeout
+ )
+ if self.socket_keepalive:
+ connection_kwargs.setdefault("socket_keepalive", True)
+ if self.socket_keepalive_options is not None:
+ connection_kwargs.setdefault(
+ "socket_keepalive_options", self.socket_keepalive_options
+ )
sentinel = redis.sentinel.Sentinel(
self.sentinels,
@@ -350,3 +410,160 @@
)
self.writer_client = sentinel.master_for(self.service_name)
self.reader_client = sentinel.slave_for(self.service_name)
+
+
+class RedisClusterBackend(RedisBackend):
+ r"""A `Redis <http://redis.io/>`_ backend, using the
+ `redis-py <http://pypi.python.org/pypi/redis/>`_ driver.
+ This backend is to be used when connecting to a
+ `Redis Cluster <https://redis.io/docs/management/scaling/>`_ which
+ will use the
+ `RedisCluster Client
+ <https://redis.readthedocs.io/en/stable/connections.html#cluster-client>`_.
+
+ .. seealso::
+
+ `Clustering <https://redis.readthedocs.io/en/stable/clustering.html>`_
+ in the redis-py documentation.
+
+ Requires redis-py version >=4.1.0.
+
+ .. versionadded:: 1.3.2
+
+ Connecting to the cluster requires one of:
+
+ * Passing a list of startup nodes
+ * Passing only one node of the cluster, Redis will use automatic discovery
+ to find the other nodes.
+
+ Example configuration, using startup nodes::
+
+ from dogpile.cache import make_region
+ from redis.cluster import ClusterNode
+
+ region = make_region().configure(
+ 'dogpile.cache.redis_cluster',
+ arguments = {
+ "startup_nodes": [
+ ClusterNode('localhost', 6379),
+ ClusterNode('localhost', 6378)
+ ]
+ }
+ )
+
+ It is recommended to use startup nodes, so that connections will be
+ successful as at least one node will always be present. Connection
+ arguments such as password, username or
+ CA certificate may be passed using ``connection_kwargs``::
+
+ from dogpile.cache import make_region
+ from redis.cluster import ClusterNode
+
+ connection_kwargs = {
+ "username": "admin",
+ "password": "averystrongpassword",
+ "ssl": True,
+ "ssl_ca_certs": "redis.pem",
+ }
+
+ nodes = [
+ ClusterNode("localhost", 6379),
+ ClusterNode("localhost", 6380),
+ ClusterNode("localhost", 6381),
+ ]
+
+ region = make_region().configure(
+ "dogpile.cache.redis_cluster",
+ arguments={
+ "startup_nodes": nodes,
+ "connection_kwargs": connection_kwargs,
+ },
+ )
+
+ Passing a URL to one node only will allow the driver to discover the whole
+ cluster automatically::
+
+ from dogpile.cache import make_region
+
+ region = make_region().configure(
+ 'dogpile.cache.redis_cluster',
+ arguments = {
+ "url": "localhost:6379/0"
+ }
+ )
+
+ A caveat of the above approach is that if the single node targeting
+ is not available, this would prevent the connection from being successful.
+
+ Parameters accepted include:
+
+ :param startup_nodes: List of ClusterNode. The list of nodes in
+ the cluster that the client will try to connect to.
+
+ :param url: string. If provided, will override separate
+ host/password/port/db params. The format is that accepted by
+ ``RedisCluster.from_url()``.
+
+ :param db: integer, default is ``0``.
+
+ :param redis_expiration_time: integer, number of seconds after setting
+ a value that Redis should expire it. This should be larger than dogpile's
+ cache expiration. By default no expiration is set.
+
+ :param distributed_lock: boolean, when True, will use a
+ redis-lock as the dogpile lock. Use this when multiple processes will be
+ talking to the same redis instance. When left at False, dogpile will
+ coordinate on a regular threading mutex.
+
+ :param lock_timeout: integer, number of seconds after acquiring a lock that
+ Redis should expire it. This argument is only valid when
+ ``distributed_lock`` is ``True``.
+
+ :param socket_timeout: float, seconds for socket timeout.
+ Default is None (no timeout).
+
+ :param socket_connect_timeout: float, seconds for socket connection
+ timeout. Default is None (no timeout).
+
+ :param socket_keepalive: boolean, when True, socket keepalive is enabled
+ Default is False.
+
+ :param lock_sleep: integer, number of seconds to sleep when failed to
+ acquire a lock. This argument is only valid when
+ ``distributed_lock`` is ``True``.
+
+ :param thread_local_lock: bool, whether a thread-local Redis lock object
+ should be used. This is the default, but is not compatible with
+ asynchronous runners, as they run in a different thread than the one
+ used to create the lock.
+
+ :param connection_kwargs: dict, additional keyword arguments are passed
+ along to the
+ ``RedisCluster.from_url()`` method or ``RedisCluster()`` constructor
+ directly, including parameters like ``ssl``, ``ssl_certfile``,
+ ``charset``, etc.
+
+ """
+
+ def __init__(self, arguments):
+ arguments = arguments.copy()
+ self.startup_nodes = arguments.pop("startup_nodes", None)
+ super().__init__(arguments)
+
+ def _imports(self):
+ global redis
+ import redis.cluster
+
+ def _create_client(self):
+ redis_cluster: redis.cluster.RedisCluster[typing.Any]
+ if self.url is not None:
+ redis_cluster = redis.cluster.RedisCluster.from_url(
+ self.url, **self.connection_kwargs
+ )
+ else:
+ redis_cluster = redis.cluster.RedisCluster(
+ startup_nodes=self.startup_nodes,
+ **self.connection_kwargs,
+ )
+ self.writer_client = typing.cast(redis.Redis[bytes], redis_cluster)
+ self.reader_client = self.writer_client
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/dogpile.cache-rel_1_3_1/tests/cache/test_redis_backend.py
new/dogpile.cache-rel_1_3_2/tests/cache/test_redis_backend.py
--- old/dogpile.cache-rel_1_3_1/tests/cache/test_redis_backend.py
2024-02-07 23:54:36.000000000 +0100
+++ new/dogpile.cache-rel_1_3_2/tests/cache/test_redis_backend.py
2024-02-21 20:40:59.000000000 +0100
@@ -202,6 +202,41 @@
expected.update({"username": None, "password": None})
self._test_helper(MockStrictRedis, expected, arguments)
+ def test_connect_with_socket_connect_timeout(self, MockStrictRedis):
+ arguments = {
+ "host": "127.0.0.1",
+ "port": 6379,
+ "socket_timeout": 1.0,
+ "db": 0,
+ }
+ expected = arguments.copy()
+ expected.update({"username": None, "password": None})
+ self._test_helper(MockStrictRedis, expected, arguments)
+
+ def test_connect_with_socket_keepalive(self, MockStrictRedis):
+ arguments = {
+ "host": "127.0.0.1",
+ "port": 6379,
+ "socket_keepalive": True,
+ "db": 0,
+ }
+ expected = arguments.copy()
+ expected.update({"username": None, "password": None})
+ self._test_helper(MockStrictRedis, expected, arguments)
+
+ def test_connect_with_socket_keepalive_options(self, MockStrictRedis):
+ arguments = {
+ "host": "127.0.0.1",
+ "port": 6379,
+ "socket_keepalive": True,
+ # 4 = socket.TCP_KEEPIDLE
+ "socket_keepalive_options": {4, 10.0},
+ "db": 0,
+ }
+ expected = arguments.copy()
+ expected.update({"username": None, "password": None})
+ self._test_helper(MockStrictRedis, expected, arguments)
+
def test_connect_with_connection_pool(self, MockStrictRedis):
pool = Mock()
arguments = {"connection_pool": pool, "socket_timeout": 0.5}