From 46a9372ab3aba81e46cddf88001d9bdc9bcdf0224e9676bff1ad1ea57322c8cd Mon Sep 17 00:00:00 2001 From: Dirk Mueller Date: Thu, 1 Feb 2024 21:20:21 +0000 Subject: [PATCH] - update to 1.62: * delete() return value now is 1 for "DELETED" and 0 for "NOT_FOUND" or server error. (Nick Pope PR #190) - update to 1.60: * Allow to use a datetime.timedelta parameter for Client.set * Fix cmemcahe_hash 0 values being translated to 1 * Fix tuple key support in multi methods * Add support for default value in get * test_memcache.py: try import unittest.mock * Use == as suggested by Python 3.8 (PR from @za) * Decoding in slab funcs, replacing "1" with "True" in while. * Tell PyPI to parse README as markdown (PR from @MartinThoma) * test_memcache.py: try import unittest.mock * Removed Python 2.7 from setup.cfg, adding 3.8-3.12 * Add support for default value in get() * Fix tuple key support in multi methods (regression in 1.55). * Removing six.PY2/3 conditionals * Removing "time" from delete and making expiry mandatory in touch. (port of @erankor's PR in #30 ) * Added quit() method. This method sends the 'quit' command to the servers and then closes the connections, reducing the number of TIME_WAIT sockets hanging around the OS. * Allow to use a datetime.timedelta parameter for Client.set * Allow keys to be encoded before use. * Removing historic python 2to3 code and deprecated socket.error (for OSError). * Updating to the latest PSF license - drop python-python-memcached-no-six.patch (upstream) * Bug #680359: useOldServerHashFunction() is broken. It now OBS-URL: https://build.opensuse.org/package/show/devel:languages:python/python-python-memcached?expand=0&rev=42 --- 1.59.tar.gz | 3 - 1.62.tar.gz | 3 + python-python-memcached-no-six.patch | 472 --------------------------- python-python-memcached.changes | 38 ++- python-python-memcached.spec | 22 +- 5 files changed, 46 insertions(+), 492 deletions(-) delete mode 100644 1.59.tar.gz create mode 100644 1.62.tar.gz delete mode 100644 python-python-memcached-no-six.patch diff --git a/1.59.tar.gz b/1.59.tar.gz deleted file mode 100644 index c1c3256..0000000 --- a/1.59.tar.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e39f5444b0eb5dcbdef1ce8f72bd73f3fb188a420fc33f23d039525efe523863 -size 32334 diff --git a/1.62.tar.gz b/1.62.tar.gz new file mode 100644 index 0000000..56707da --- /dev/null +++ b/1.62.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2877f0885ade0c4c6871c863914838d23c955621f1a9f56a9b941dd1facb250a +size 28598 diff --git a/python-python-memcached-no-six.patch b/python-python-memcached-no-six.patch deleted file mode 100644 index 5b776cc..0000000 --- a/python-python-memcached-no-six.patch +++ /dev/null @@ -1,472 +0,0 @@ -Index: python-memcached-1.59/memcache.py -=================================================================== ---- python-memcached-1.59.orig/memcache.py -+++ python-memcached-1.59/memcache.py -@@ -45,7 +45,6 @@ More detailed documentation is available - - """ - --from __future__ import print_function - - import binascii - from io import BytesIO -@@ -56,13 +55,7 @@ import threading - import time - import zlib - --import six -- --if six.PY2: -- # With Python 2, the faster C implementation has to be imported explicitly. -- import cPickle as pickle --else: -- import pickle -+import pickle - - - def cmemcache_hash(key): -@@ -107,7 +100,7 @@ _SOCKET_TIMEOUT = 3 # number of seconds - - - class Client(threading.local): -- """Object representing a pool of memcache servers. -+ r"""Object representing a pool of memcache servers. - - See L{memcache} for an overview. - -@@ -207,7 +200,7 @@ class Client(threading.local): - to ensure it is the correct length and composed of the right - characters. - """ -- super(Client, self).__init__() -+ super().__init__() - self.debug = debug - self.dead_retry = dead_retry - self.socket_timeout = socket_timeout -@@ -243,19 +236,18 @@ class Client(threading.local): - - def _encode_key(self, key): - if isinstance(key, tuple): -- if isinstance(key[1], six.text_type): -+ if isinstance(key[1], str): - return (key[0], key[1].encode('utf8')) -- elif isinstance(key, six.text_type): -+ elif isinstance(key, str): - return key.encode('utf8') - return key - - def _encode_cmd(self, cmd, key, headers, noreply, *args): -- cmd_bytes = cmd.encode('utf-8') if six.PY3 else cmd -+ cmd_bytes = cmd.encode('utf-8') - fullcmd = [cmd_bytes, b' ', key] - - if headers: -- if six.PY3: -- headers = headers.encode('utf-8') -+ headers = headers.encode('utf-8') - fullcmd.append(b' ') - fullcmd.append(headers) - -@@ -311,11 +303,11 @@ class Client(threading.local): - if not s.connect(): - continue - if s.family == socket.AF_INET: -- name = '%s:%s (%s)' % (s.ip, s.port, s.weight) -+ name = '{}:{} ({})'.format(s.ip, s.port, s.weight) - elif s.family == socket.AF_INET6: -- name = '[%s]:%s (%s)' % (s.ip, s.port, s.weight) -+ name = '[{}]:{} ({})'.format(s.ip, s.port, s.weight) - else: -- name = 'unix:%s (%s)' % (s.address, s.weight) -+ name = 'unix:{} ({})'.format(s.address, s.weight) - if not stat_args: - s.send_cmd('stats') - else: -@@ -338,11 +330,11 @@ class Client(threading.local): - if not s.connect(): - continue - if s.family == socket.AF_INET: -- name = '%s:%s (%s)' % (s.ip, s.port, s.weight) -+ name = '{}:{} ({})'.format(s.ip, s.port, s.weight) - elif s.family == socket.AF_INET6: -- name = '[%s]:%s (%s)' % (s.ip, s.port, s.weight) -+ name = '[{}]:{} ({})'.format(s.ip, s.port, s.weight) - else: -- name = 'unix:%s (%s)' % (s.address, s.weight) -+ name = 'unix:{} ({})'.format(s.address, s.weight) - serverData = {} - data.append((name, serverData)) - s.send_cmd('stats slabs') -@@ -369,11 +361,11 @@ class Client(threading.local): - if not s.connect(): - continue - if s.family == socket.AF_INET: -- name = '%s:%s (%s)' % (s.ip, s.port, s.weight) -+ name = '{}:{} ({})'.format(s.ip, s.port, s.weight) - elif s.family == socket.AF_INET6: -- name = '[%s]:%s (%s)' % (s.ip, s.port, s.weight) -+ name = '[{}]:{} ({})'.format(s.ip, s.port, s.weight) - else: -- name = 'unix:%s (%s)' % (s.address, s.weight) -+ name = 'unix:{} ({})'.format(s.address, s.weight) - serverData = {} - data.append((name, serverData)) - s.send_cmd('stats items') -@@ -434,7 +426,7 @@ class Client(threading.local): - # print("(using server %s)" % server,) - return server, key - serverhash = str(serverhash) + str(i) -- if isinstance(serverhash, six.text_type): -+ if isinstance(serverhash, str): - serverhash = serverhash.encode('ascii') - serverhash = serverHashFunction(serverhash) - return None, None -@@ -479,7 +471,7 @@ class Client(threading.local): - dead_servers = [] - - rc = 1 -- for server in six.iterkeys(server_keys): -+ for server in server_keys.keys(): - bigcmd = [] - write = bigcmd.append - if time is not None: -@@ -491,7 +483,7 @@ class Client(threading.local): - write(cmd) - try: - server.send_cmds(b''.join(bigcmd)) -- except socket.error as msg: -+ except OSError as msg: - rc = 0 - if isinstance(msg, tuple): - msg = msg[1] -@@ -506,11 +498,11 @@ class Client(threading.local): - for server in dead_servers: - del server_keys[server] - -- for server, keys in six.iteritems(server_keys): -+ for server, keys in server_keys.items(): - try: - for key in keys: - server.expect(b"DELETED") -- except socket.error as msg: -+ except OSError as msg: - if isinstance(msg, tuple): - msg = msg[1] - server.mark_dead(msg) -@@ -568,7 +560,7 @@ class Client(threading.local): - return 1 - self.debuglog('%s expected %s, got: %r' - % (cmd, b' or '.join(expected), line)) -- except socket.error as msg: -+ except OSError as msg: - if isinstance(msg, tuple): - msg = msg[1] - server.mark_dead(msg) -@@ -642,7 +634,7 @@ class Client(threading.local): - if line is None or line.strip() == b'NOT_FOUND': - return None - return int(line) -- except socket.error as msg: -+ except OSError as msg: - if isinstance(msg, tuple): - msg = msg[1] - server.mark_dead(msg) -@@ -789,11 +781,10 @@ class Client(threading.local): - serverhash, key = orig_key - - key = self._encode_key(key) -- if not isinstance(key, six.binary_type): -+ if not isinstance(key, bytes): - # set_multi supports int / long keys. - key = str(key) -- if six.PY3: -- key = key.encode('utf8') -+ key = key.encode('utf8') - bytes_orig_key = key - - # Gotta pre-mangle key before hashing to a -@@ -804,11 +795,10 @@ class Client(threading.local): - orig_key = orig_key[1] - else: - key = self._encode_key(orig_key) -- if not isinstance(key, six.binary_type): -+ if not isinstance(key, bytes): - # set_multi supports int / long keys. - key = str(key) -- if six.PY3: -- key = key.encode('utf8') -+ key = key.encode('utf8') - bytes_orig_key = key - server, key = self._get_server(key_prefix + key) - -@@ -893,13 +883,13 @@ class Client(threading.local): - self._statlog('set_multi') - - server_keys, prefixed_to_orig_key = self._map_and_prefix_keys( -- six.iterkeys(mapping), key_prefix) -+ mapping.keys(), key_prefix) - - # send out all requests on each server before reading anything - dead_servers = [] - notstored = [] # original keys. - -- for server in six.iterkeys(server_keys): -+ for server in server_keys.keys(): - bigcmd = [] - write = bigcmd.append - try: -@@ -917,7 +907,7 @@ class Client(threading.local): - else: - notstored.append(prefixed_to_orig_key[key]) - server.send_cmds(b''.join(bigcmd)) -- except socket.error as msg: -+ except OSError as msg: - if isinstance(msg, tuple): - msg = msg[1] - server.mark_dead(msg) -@@ -935,7 +925,7 @@ class Client(threading.local): - if not server_keys: - return list(mapping.keys()) - -- for server, keys in six.iteritems(server_keys): -+ for server, keys in server_keys.items(): - try: - for key in keys: - if server.readline() == b'STORED': -@@ -943,7 +933,7 @@ class Client(threading.local): - else: - # un-mangle. - notstored.append(prefixed_to_orig_key[key]) -- except (_Error, socket.error) as msg: -+ except (_Error, OSError) as msg: - if isinstance(msg, tuple): - msg = msg[1] - server.mark_dead(msg) -@@ -960,23 +950,15 @@ class Client(threading.local): - # subclasses of native types (such as markup-safe strings) are pickled - # and restored as instances of the correct class. - val_type = type(val) -- if val_type == six.binary_type: -+ if val_type == bytes: - pass -- elif val_type == six.text_type: -+ elif val_type == str: - flags |= Client._FLAG_TEXT - val = val.encode('utf-8') - elif val_type == int: - flags |= Client._FLAG_INTEGER - val = '%d' % val -- if six.PY3: -- val = val.encode('ascii') -- # force no attempt to compress this silly string. -- min_compress_len = 0 -- elif six.PY2 and isinstance(val, long): # noqa: F821 -- flags |= Client._FLAG_LONG -- val = str(val) -- if six.PY3: -- val = val.encode('ascii') -+ val = val.encode('ascii') - # force no attempt to compress this silly string. - min_compress_len = 0 - else: -@@ -1042,7 +1024,7 @@ class Client(threading.local): - if noreply: - return True - return server.expect(b"STORED", raise_exception=True) == b"STORED" -- except socket.error as msg: -+ except OSError as msg: - if isinstance(msg, tuple): - msg = msg[1] - server.mark_dead(msg) -@@ -1055,7 +1037,7 @@ class Client(threading.local): - try: - if server._get_socket(): - return _unsafe_set() -- except (_ConnectionDeadError, socket.error) as msg: -+ except (_ConnectionDeadError, OSError) as msg: - server.mark_dead(msg) - return 0 - -@@ -1071,7 +1053,7 @@ class Client(threading.local): - self._statlog(cmd) - - try: -- cmd_bytes = cmd.encode('utf-8') if six.PY3 else cmd -+ cmd_bytes = cmd.encode('utf-8') - fullcmd = b''.join((cmd_bytes, b' ', key)) - server.send_cmd(fullcmd) - rkey = flags = rlen = cas_id = None -@@ -1093,7 +1075,7 @@ class Client(threading.local): - value = self._recv_value(server, flags, rlen) - finally: - server.expect(b"END", raise_exception=True) -- except (_Error, socket.error) as msg: -+ except (_Error, OSError) as msg: - if isinstance(msg, tuple): - msg = msg[1] - server.mark_dead(msg) -@@ -1109,7 +1091,7 @@ class Client(threading.local): - if server.connect(): - return _unsafe_get() - return None -- except (_ConnectionDeadError, socket.error) as msg: -+ except (_ConnectionDeadError, OSError) as msg: - server.mark_dead(msg) - return None - -@@ -1189,11 +1171,11 @@ class Client(threading.local): - - # send out all requests on each server before reading anything - dead_servers = [] -- for server in six.iterkeys(server_keys): -+ for server in server_keys.keys(): - try: - fullcmd = b"get " + b" ".join(server_keys[server]) - server.send_cmd(fullcmd) -- except socket.error as msg: -+ except OSError as msg: - if isinstance(msg, tuple): - msg = msg[1] - server.mark_dead(msg) -@@ -1204,7 +1186,7 @@ class Client(threading.local): - del server_keys[server] - - retvals = {} -- for server in six.iterkeys(server_keys): -+ for server in server_keys.keys(): - try: - line = server.readline() - while line and line != b'END': -@@ -1215,7 +1197,7 @@ class Client(threading.local): - # un-prefix returned key. - retvals[prefixed_to_orig_key[rkey]] = val - line = server.readline() -- except (_Error, socket.error) as msg: -+ except (_Error, OSError) as msg: - if isinstance(msg, tuple): - msg = msg[1] - server.mark_dead(msg) -@@ -1264,10 +1246,7 @@ class Client(threading.local): - elif flags & Client._FLAG_INTEGER: - val = int(buf) - elif flags & Client._FLAG_LONG: -- if six.PY3: -- val = int(buf) -- else: -- val = long(buf) # noqa: F821 -+ val = int(buf) - elif flags & Client._FLAG_PICKLE: - try: - file = BytesIO(buf) -@@ -1300,14 +1279,14 @@ class Client(threading.local): - key = key[1] - if key is None: - raise Client.MemcachedKeyNoneError("Key is None") -- if key is '': -- if key_extra_len is 0: -+ if key == '': -+ if key_extra_len == 0: - raise Client.MemcachedKeyNoneError("Key is empty") - - # key is empty but there is some other component to key - return - -- if not isinstance(key, six.binary_type): -+ if not isinstance(key, bytes): - raise Client.MemcachedKeyTypeError("Key must be a binary string") - - if (self.server_max_key_length != 0 and -@@ -1320,7 +1299,7 @@ class Client(threading.local): - "Control/space characters not allowed (key=%r)" % key) - - --class _Host(object): -+class _Host: - - def __init__(self, host, debug=0, dead_retry=_DEAD_RETRY, - socket_timeout=_SOCKET_TIMEOUT, flush_on_reconnect=0): -@@ -1383,7 +1362,7 @@ class _Host(object): - return 0 - - def mark_dead(self, reason): -- self.debuglog("MemCache: %s: %s. Marking dead." % (self, reason)) -+ self.debuglog("MemCache: {}: {}. Marking dead.".format(self, reason)) - self.deaduntil = time.time() + self.dead_retry - if self.flush_on_reconnect: - self.flush_on_next_connect = 1 -@@ -1402,7 +1381,7 @@ class _Host(object): - except socket.timeout as msg: - self.mark_dead("connect: %s" % msg) - return None -- except socket.error as msg: -+ except OSError as msg: - if isinstance(msg, tuple): - msg = msg[1] - self.mark_dead("connect: %s" % msg) -@@ -1420,13 +1399,13 @@ class _Host(object): - self.socket = None - - def send_cmd(self, cmd): -- if isinstance(cmd, six.text_type): -+ if isinstance(cmd, str): - cmd = cmd.encode('utf8') - self.socket.sendall(cmd + b'\r\n') - - def send_cmds(self, cmds): - """cmds already has trailing \r\n's applied.""" -- if isinstance(cmds, six.text_type): -+ if isinstance(cmds, str): - cmds = cmds.encode('utf8') - self.socket.sendall(cmds) - -@@ -1462,11 +1441,8 @@ class _Host(object): - def expect(self, text, raise_exception=False): - line = self.readline(raise_exception) - if self.debug and line != text: -- if six.PY3: -- text = text.decode('utf8') -- log_line = line.decode('utf8', 'replace') -- else: -- log_line = line -+ text = text.decode('utf8') -+ log_line = line.decode('utf8', 'replace') - self.debuglog("while expecting %r, got unexpected response %r" - % (text, log_line)) - return line -@@ -1497,7 +1473,7 @@ class _Host(object): - elif self.family == socket.AF_INET6: - return "inet6:[%s]:%d%s" % (self.address[0], self.address[1], d) - else: -- return "unix:%s%s" % (self.address, d) -+ return "unix:{}{}".format(self.address, d) - - - def _doctest(): -@@ -1508,7 +1484,7 @@ def _doctest(): - globs = {"mc": mc} - results = doctest.testmod(memcache, globs=globs) - mc.disconnect_all() -- print("Doctests: %s" % (results,)) -+ print("Doctests: {}".format(results)) - if results.failed: - sys.exit(1) - -Index: python-memcached-1.59/requirements.txt -=================================================================== ---- python-memcached-1.59.orig/requirements.txt -+++ python-memcached-1.59/requirements.txt -@@ -1 +0,0 @@ --six>=1.4.0 -Index: python-memcached-1.59/tests/utils.py -=================================================================== ---- python-memcached-1.59.orig/tests/utils.py -+++ python-memcached-1.59/tests/utils.py -@@ -1,7 +1,7 @@ - from contextlib import contextmanager - import sys - --from six import StringIO -+from io import StringIO - - - @contextmanager diff --git a/python-python-memcached.changes b/python-python-memcached.changes index 6f409be..706f444 100644 --- a/python-python-memcached.changes +++ b/python-python-memcached.changes @@ -1,3 +1,35 @@ +------------------------------------------------------------------- +Thu Feb 1 21:18:55 UTC 2024 - Dirk Müller + +- update to 1.62: + * delete() return value now is 1 for "DELETED" and 0 for + "NOT_FOUND" or server error. (Nick Pope PR #190) +- update to 1.60: + * Allow to use a datetime.timedelta parameter for Client.set + * Fix cmemcahe_hash 0 values being translated to 1 + * Fix tuple key support in multi methods + * Add support for default value in get + * test_memcache.py: try import unittest.mock + * Use == as suggested by Python 3.8 (PR from @za) + * Decoding in slab funcs, replacing "1" with "True" in while. + * Tell PyPI to parse README as markdown (PR from @MartinThoma) + * test_memcache.py: try import unittest.mock + * Removed Python 2.7 from setup.cfg, adding 3.8-3.12 + * Add support for default value in get() + * Fix tuple key support in multi methods (regression in 1.55). + * Removing six.PY2/3 conditionals + * Removing "time" from delete and making expiry mandatory in + touch. (port of @erankor's PR in #30 ) + * Added quit() method. This method sends the 'quit' command to + the servers and then closes the connections, reducing the + number of TIME_WAIT sockets hanging around the OS. + * Allow to use a datetime.timedelta parameter for Client.set + * Allow keys to be encoded before use. + * Removing historic python 2to3 code and deprecated + socket.error (for OSError). + * Updating to the latest PSF license +- drop python-python-memcached-no-six.patch (upstream) + ------------------------------------------------------------------- Thu Jun 1 09:27:51 UTC 2023 - pgajdos@suse.com @@ -151,11 +183,11 @@ Fri Apr 1 11:23:28 UTC 2011 - oliver.bengs@opensuse.org - added %{py_requires} - make use of --record-rpm from setuptools -------------------------------------------------------------------- +------------------------------------------------------------------- Sat Feb 26 14.13.54 UTC 2011 - stian@viskjer.net - python-memcached 1.47 - * Bug #680359: useOldServerHashFunction() is broken. It now + * Bug #680359: useOldServerHashFunction() is broken. It now correctly switches back to the old memcache hash function. - python-memcached 1.46 @@ -184,7 +216,7 @@ Sat Feb 26 14.13.54 UTC 2011 - stian@viskjer.net * Removing Evan's e-mail address at his request, changing authorship to Sean. -------------------------------------------------------------------- +------------------------------------------------------------------- Fri Nov 26 23.00.00 UTC 2010 - stian@viskjer.net - python-memcached 1.45 diff --git a/python-python-memcached.spec b/python-python-memcached.spec index 8c71731..8456576 100644 --- a/python-python-memcached.spec +++ b/python-python-memcached.spec @@ -1,7 +1,7 @@ # # spec file for package python-python-memcached # -# Copyright (c) 2023 SUSE LLC +# Copyright (c) 2024 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -16,29 +16,25 @@ # -%define oldpython python +%{?sle15_python_module_pythons} Name: python-python-memcached -Version: 1.59 +Version: 1.62 Release: 0 Summary: Pure python memcached client License: Python-2.0 Group: Development/Languages/Python URL: https://github.com/linsomniac/python-memcached Source: https://github.com/linsomniac/python-memcached/archive/%{version}.tar.gz -# https://github.com/linsomniac/python-memcached/pull/186 -Patch0: python-python-memcached-no-six.patch +BuildRequires: %{python_module pip} BuildRequires: %{python_module pytest} BuildRequires: %{python_module setuptools} +BuildRequires: %{python_module wheel} BuildRequires: fdupes BuildRequires: memcached BuildRequires: python-rpm-macros BuildRequires: util-linux Requires: memcached BuildArch: noarch -%ifpython2 -Provides: %{oldpython}-memcached = %{version} -Obsoletes: %{oldpython}-memcached < %{version} -%endif %python_subpackages %description @@ -55,15 +51,13 @@ for more information. sed -i \ -e 's:#!%{_bindir}/env python::' \ memcache.py -sed -i 's/import mock/import unittest.mock as mock/' tests/test_memcache.py -# gh#linsomniac/python-memcached#185 sed -i -e '/__version__/s/[0-9.]\+/%{version}/' memcache.py %build -%python_build +%pyproject_wheel %install -%python_install +%pyproject_install %python_expand %fdupes %{buildroot}%{$python_sitelib} %check @@ -76,6 +70,6 @@ kill -9 $(cat $PWD/memcached.pid) %doc README.md %{python_sitelib}/memcache.py %pycache_only %{python_sitelib}/__pycache__/memcache.*.pyc -%{python_sitelib}/python_memcached-%{version}*-info +%{python_sitelib}/python_memcached-%{version}.dist-info %changelog