Hello community,

here is the log from the commit of package python-pylibmc for openSUSE:Factory 
checked in at 2019-03-14 14:55:35
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-pylibmc (Old)
 and      /work/SRC/openSUSE:Factory/.python-pylibmc.new.28833 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-pylibmc"

Thu Mar 14 14:55:35 2019 rev:6 rq:684213 version:1.6.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-pylibmc/python-pylibmc.changes    
2017-09-05 15:19:33.456656110 +0200
+++ /work/SRC/openSUSE:Factory/.python-pylibmc.new.28833/python-pylibmc.changes 
2019-03-14 14:55:36.947758249 +0100
@@ -1,0 +2,9 @@
+Tue Mar 12 05:07:50 UTC 2019 - John Vandenberg <jay...@gmail.com>
+
+- Remove bcond test
+- Activate test suite
+- Use %license
+- Update URL to GitHub repository
+- Update to v1.6.0
+
+-------------------------------------------------------------------

Old:
----
  pylibmc-1.5.2.tar.gz

New:
----
  pylibmc-1.6.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-pylibmc.spec ++++++
--- /var/tmp/diff_new_pack.9SljKH/_old  2019-03-14 14:55:37.599758146 +0100
+++ /var/tmp/diff_new_pack.9SljKH/_new  2019-03-14 14:55:37.603758145 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package python-pylibmc
 #
-# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -12,29 +12,27 @@
 # license that conforms to the Open Source Definition (Version 1.9)
 # published by the Open Source Initiative.
 
-# Please submit bugfixes or comments via http://bugs.opensuse.org/
+# Please submit bugfixes or comments via https://bugs.opensuse.org/
 #
 
 
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
-%bcond_with     test
 Name:           python-pylibmc
-Version:        1.5.2
+Version:        1.6.0
 Release:        0
 Summary:        memcached client for Python
 License:        BSD-3-Clause
 Group:          Development/Languages/Python
-Url:            http://sendapatch.se/projects/pylibmc/
+URL:            https://github.com/lericson/pylibmc
 Source:         
https://files.pythonhosted.org/packages/source/p/pylibmc/pylibmc-%{version}.tar.gz
 BuildRequires:  %{python_module devel}
+BuildRequires:  %{python_module nose}
 BuildRequires:  %{python_module setuptools}
 BuildRequires:  fdupes
 BuildRequires:  libmemcached-devel
+BuildRequires:  memcached
 BuildRequires:  python-rpm-macros
 BuildRequires:  zlib-devel
-%if %{with test}
-BuildRequires:  %{python_module nose}
-%endif
 %python_subpackages
 
 %description
@@ -56,17 +54,18 @@
 %python_install
 %python_expand %fdupes %{buildroot}%{$python_sitearch}
 
-%if %{with test}
 %check
+%{_sbindir}/memcached &
+pid=$!
 export NOSE_IGNORE_CONFIG_FILES=1
 %{python_expand export PYTHONPATH=%{buildroot}%{$python_sitearch}
 nosetests-%{$python_bin_suffix} tests
 }
-%endif
+kill $pid
 
 %files %{python_files}
-%defattr(-,root,root,-)
-%doc LICENSE README.rst
+%license LICENSE
+%doc README.rst
 %{python_sitearch}/*
 
 %changelog

++++++ pylibmc-1.5.2.tar.gz -> pylibmc-1.6.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pylibmc-1.5.2/PKG-INFO new/pylibmc-1.6.0/PKG-INFO
--- old/pylibmc-1.5.2/PKG-INFO  2017-03-06 14:13:31.000000000 +0100
+++ new/pylibmc-1.6.0/PKG-INFO  2018-11-09 19:05:45.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: pylibmc
-Version: 1.5.2
+Version: 1.6.0
 Summary: Quick and small memcached client for Python
 Home-page: http://sendapatch.se/projects/pylibmc/
 Author: Ludvig Ericson
@@ -15,6 +15,22 @@
         .. image:: https://travis-ci.org/lericson/pylibmc.png?branch=master
            :target: https://travis-ci.org/lericson/pylibmc
         
+        New in version 1.6.0
+        ====================
+        
+        Though no major feature overhauls have taken place, this release is 
partially
+        incompatible with 1.5.0. This stems from the fact that 
python-memcached is now
+        using a flag that pylibmc has been using for some years. 
python-memcached uses
+        it for a different purpose, and an incompatible one. We deemed that it 
would be
+        better to support this interoperability. The change also means that 
Unicode
+        strings are now stored as UTF-8 rather than pickled, which may or may 
not
+        result in a slight performance improvement for this type of data.
+        
+        We have also introduced a `pickle_protocol` behavior to enable seamless
+        interoperability between Python 2.x and 3.x. Also, this release 
introduces a
+        ManyLinux wheel, making installation a breeze on ManyLinux systems 
(which I
+        suppose is many linuxes.)
+        
         New in version 1.5.0
         ====================
         
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pylibmc-1.5.2/README.rst new/pylibmc-1.6.0/README.rst
--- old/pylibmc-1.5.2/README.rst        2016-03-21 19:38:38.000000000 +0100
+++ new/pylibmc-1.6.0/README.rst        2018-11-09 18:49:56.000000000 +0100
@@ -7,6 +7,22 @@
 .. image:: https://travis-ci.org/lericson/pylibmc.png?branch=master
    :target: https://travis-ci.org/lericson/pylibmc
 
+New in version 1.6.0
+====================
+
+Though no major feature overhauls have taken place, this release is partially
+incompatible with 1.5.0. This stems from the fact that python-memcached is now
+using a flag that pylibmc has been using for some years. python-memcached uses
+it for a different purpose, and an incompatible one. We deemed that it would be
+better to support this interoperability. The change also means that Unicode
+strings are now stored as UTF-8 rather than pickled, which may or may not
+result in a slight performance improvement for this type of data.
+
+We have also introduced a `pickle_protocol` behavior to enable seamless
+interoperability between Python 2.x and 3.x. Also, this release introduces a
+ManyLinux wheel, making installation a breeze on ManyLinux systems (which I
+suppose is many linuxes.)
+
 New in version 1.5.0
 ====================
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pylibmc-1.5.2/docs/behaviors.rst 
new/pylibmc-1.6.0/docs/behaviors.rst
--- old/pylibmc-1.5.2/docs/behaviors.rst        2015-09-28 18:38:56.000000000 
+0200
+++ new/pylibmc-1.6.0/docs/behaviors.rst        2018-11-09 18:42:08.000000000 
+0100
@@ -250,3 +250,18 @@
           ``auto_eject``; these still exist, but their interaction with the
           state machine is unclear, and should be avoided. ``remove_failed``
           acts as a combination of the two.
+
+Non-libmemcached Behaviors
+--------------------------
+
+It wouldn't make sense to have multiple avenues of configuration, and so
+whenever possible, pylibmc tries to co-opt the behaviors dictionary for
+configuration of strictly pylibmc-level things. These are described below.
+
+.. _pickle_protocol:
+
+``"pickle_protocol"``
+   Specifies the default pickling protocol. This is by default set to -1, which
+   means the pickle module will use the latest protocol it understands. This is
+   an issue for interoperability, and so for example to work between Python 2
+   and 3, set this explicitly to 2 or whatever you prefer.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pylibmc-1.5.2/docs/install.rst 
new/pylibmc-1.6.0/docs/install.rst
--- old/pylibmc-1.5.2/docs/install.rst  2016-06-13 16:18:53.000000000 +0200
+++ new/pylibmc-1.6.0/docs/install.rst  2018-11-09 18:42:08.000000000 +0100
@@ -5,8 +5,8 @@
 Requirements
 ============
 
-* Python 2.5, Python 3.2 or later
-* libmemcached 0.32 or later (last test with 1.0.18)
+* Python 2.6-2.7, or Python 3.3-3.6
+* libmemcached 1.0.8 or later (latest tested is 1.0.18)
 * zlib (required for compression support)
 * libsasl2 (required for authentication support)
 
@@ -28,7 +28,11 @@
 From PyPI
 ---------
 
-Since ``pip`` doesn't support passing arguments to the setup script,
-you can also define environment variables::
+Using ``pip`` you can pass install options as follows::
 
-    LIBMEMCACHED=/opt/local pip install pylibmc
+    pip install pylibmc --install-option="--with-libmemcached=/usr/local/"
+
+Using Homebrew (MacOSX) you can install from PyPI via::
+
+    brew install libmemcached
+    pip install pylibmc 
--install-option="--with-libmemcached=/usr/local/Cellar/libmemcached"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pylibmc-1.5.2/docs/reference.rst 
new/pylibmc-1.6.0/docs/reference.rst
--- old/pylibmc-1.5.2/docs/reference.rst        2016-08-09 18:06:26.000000000 
+0200
+++ new/pylibmc-1.6.0/docs/reference.rst        2018-11-09 18:42:08.000000000 
+0100
@@ -180,13 +180,13 @@
 
    .. method:: touch(key, time) -> touched
 
-      Touch a given *key* and increase it's expiry time by *time* seconds.
+      Touch a given *key* and set its expiry time to *time* seconds.
 
       :param key: Key to touch
       :param time: Number of seconds until the key expires.
 
       Returns ``True`` if the key was successfully touched. ``False``
-      if the key did not exist.
+      if the key did not exist (so touching is not possible.)
 
    .. Utilities
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pylibmc-1.5.2/setup.py new/pylibmc-1.6.0/setup.py
--- old/pylibmc-1.5.2/setup.py  2016-08-09 18:06:26.000000000 +0200
+++ new/pylibmc-1.6.0/setup.py  2018-11-09 18:42:08.000000000 +0100
@@ -76,14 +76,14 @@
 # strict aliasing rules. Let's skip this flag for now.
 cflags = ["-fno-strict-aliasing", "-std=c99"]
 
-## Extension definitions
+# Extension definitions
 
 pylibmc_ext = Extension("_pylibmc", ["src/_pylibmcmodule.c"],
                         libraries=libs, include_dirs=incdirs,
                         library_dirs=libdirs, define_macros=defs,
                         extra_compile_args=cflags)
 
-# Hidden secret: if environment variable GEN_SETUP is set, generate Setup file.
+# Hidden secret: generate Setup file for statically compiling the extension.
 if cmd == "gen-setup":
     line = " ".join((
         pylibmc_ext.name,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pylibmc-1.5.2/src/_pylibmcmodule.c 
new/pylibmc-1.6.0/src/_pylibmcmodule.c
--- old/pylibmc-1.5.2/src/_pylibmcmodule.c      2017-02-25 17:39:03.000000000 
+0100
+++ new/pylibmc-1.6.0/src/_pylibmcmodule.c      2018-11-09 18:42:08.000000000 
+0100
@@ -216,6 +216,8 @@
     }
     self->native_deserialization = (uint8_t) native_deserialization;
 
+    self->pickle_protocol = -1;
+
     while ((c_srv = PyIter_Next(srvs_it)) != NULL) {
         unsigned char stype;
         char *hostname;
@@ -352,9 +354,8 @@
         goto error;
     }
 
-    if(strm.total_out >= value_len) {
-      /* if we didn't actually save anything, don't bother storing it
-         compressed */
+    if ((Py_ssize_t)strm.total_out >= value_len) {
+      /* if no data was saved, don't use compression */
       goto error;
     }
 
@@ -594,7 +595,7 @@
 #else
     if (flags & PYLIBMC_FLAG_ZLIB) {
         PyErr_SetString(PylibMCExc_Error,
-            "value for key compressed, unable to inflate");
+            "key is compressed but pylibmc is compiled without zlib support");
         return NULL;
     }
 #endif
@@ -645,20 +646,21 @@
 
     switch (dtype) {
         case PYLIBMC_FLAG_PICKLE:
-            retval = value ? _PylibMC_Unpickle_Bytes(value) : 
_PylibMC_Unpickle(value_str, value_size);
+            retval = value ? _PylibMC_Unpickle_Bytes(self, value) : 
_PylibMC_Unpickle(self, value_str, value_size);
             break;
         case PYLIBMC_FLAG_INTEGER:
         case PYLIBMC_FLAG_LONG:
-        case PYLIBMC_FLAG_BOOL:
             if (value) {
                 retval = PyLong_FromString(PyBytes_AS_STRING(value), NULL, 10);
             } else {
                 retval = _PyLong_FromStringAndSize(value_str, value_size, 
NULL, 10);;
             }
-            if (retval != NULL && dtype == PYLIBMC_FLAG_BOOL) {
-                PyObject *bool_retval = 
PyBool_FromLong(PyLong_AS_LONG(retval));
-                Py_DECREF(retval);
-                retval = bool_retval;
+            break;
+        case PYLIBMC_FLAG_TEXT:
+            if (value) {
+                retval = PyUnicode_FromEncodedObject(value, "utf-8", "strict");
+            } else {
+                retval = PyUnicode_FromStringAndSize(value_str, value_size);
             }
             break;
         case PYLIBMC_FLAG_NONE:
@@ -723,7 +725,7 @@
 
     if (!_key_normalized_obj(&key)) {
         return NULL;
-    } else if (!PySequence_Length(key) ) {
+    } else if (!PySequence_Length(key)) {
         Py_INCREF(default_value);
         return default_value;
     }
@@ -736,18 +738,23 @@
 
     Py_DECREF(key);
 
-    if (mc_val != NULL) {
+    if (error == MEMCACHED_SUCCESS) {
+        /* note that mc_val can and is NULL for zero-length values. */
         PyObject *r = _PylibMC_parse_memcached_value(self, mc_val, val_size, 
flags);
-        free(mc_val);
+
+        if (mc_val != NULL) {
+            free(mc_val);
+        }
+
         if (_PylibMC_cache_miss_simulated(r)) {
             Py_INCREF(default_value);
             return default_value;
         }
+
         return r;
-    } else if (error == MEMCACHED_SUCCESS) {
-        /* This happens for empty values, and so we fake an empty string. */
-        return PyBytes_FromStringAndSize("", 0);
-    } else if (error == MEMCACHED_NOTFOUND) {
+    }
+
+    if (error == MEMCACHED_NOTFOUND) {
         Py_INCREF(default_value);
         return default_value;
     }
@@ -1247,12 +1254,12 @@
         /* Make store_val an owned reference */
         store_val = value_obj;
         Py_INCREF(store_val);
+    } else if (PyUnicode_Check(value_obj)) {
+        store_flags = PYLIBMC_FLAG_TEXT;
+        store_val = PyUnicode_AsUTF8String(value_obj);
     } else if (PyBool_Check(value_obj)) {
-        store_flags |= PYLIBMC_FLAG_BOOL;
-        /* bool cannot be subclassed; there are only two singleton values,
-           Py_True and Py_False */
-        const char *value_str = (value_obj == Py_True) ? "1" : "0";
-        store_val = PyBytes_FromString(value_str);
+        store_flags |= PYLIBMC_FLAG_INTEGER;
+        store_val = PyBytes_FromStringAndSize(&"01"[value_obj == Py_True], 1);
 #if PY_MAJOR_VERSION >= 3
     } else if (PyLong_Check(value_obj)) {
         store_flags |= PYLIBMC_FLAG_LONG;
@@ -1275,7 +1282,7 @@
         /* we have no idea what it is, so we'll store it pickled */
         Py_INCREF(value_obj);
         store_flags |= PYLIBMC_FLAG_PICKLE;
-        store_val = _PylibMC_Pickle(value_obj);
+        store_val = _PylibMC_Pickle(self, value_obj);
         Py_DECREF(value_obj);
     }
 
@@ -2128,14 +2135,21 @@
         uint64_t bval;
         PyObject *x;
 
-        bval = memcached_behavior_get(self->mc, b->flag);
+        switch (b->flag) {
+        case PYLIBMC_BEHAVIOR_PICKLE_PROTOCOL:
+            bval = self->pickle_protocol;
+            break;
+        default:
+            bval = memcached_behavior_get(self->mc, b->flag);
+        }
+
         x = PyLong_FromLong((long)bval);
         if (x == NULL || PyDict_SetItemString(retval, b->name, x) == -1) {
             Py_XDECREF(x);
             goto error;
         }
-
         Py_DECREF(x);
+
     }
 
     return retval;
@@ -2148,7 +2162,7 @@
         PyObject *behaviors) {
     PylibMC_Behavior *b;
     PyObject *py_v;
-    uint64_t v;
+    long v;
     memcached_return r;
     char *key;
 
@@ -2163,16 +2177,23 @@
             goto error;
         }
 
-        v = (uint64_t)PyLong_AS_LONG(py_v);
+        v = PyLong_AsLong(py_v);
         Py_DECREF(py_v);
 
-        r = memcached_behavior_set(self->mc, b->flag, v);
-        if (r != MEMCACHED_SUCCESS) {
-            PyErr_Format(PylibMCExc_Error,
-                         "memcached_behavior_set returned %d for "
-                         "behavior '%.32s' = %u", r, b->name, (unsigned int)v);
-            goto error;
+        switch (b->flag) {
+        case PYLIBMC_BEHAVIOR_PICKLE_PROTOCOL:
+            self->pickle_protocol = v;
+            break;
+        default:
+            r = memcached_behavior_set(self->mc, b->flag, (uint64_t)v);
+            if (r != MEMCACHED_SUCCESS) {
+                PyErr_Format(PylibMCExc_Error,
+                             "memcached_behavior_set returned %d for "
+                             "behavior '%.32s' = %ld", r, b->name, v);
+                goto error;
+            }
         }
+
     }
 
     for (b = PylibMC_callbacks; b->name != NULL; b++) {
@@ -2383,6 +2404,7 @@
     Py_END_ALLOW_THREADS;
     clone->native_serialization = self->native_serialization;
     clone->native_deserialization = self->native_deserialization;
+    clone->pickle_protocol = self->pickle_protocol;
     return (PyObject *)clone;
 }
 /* }}} */
@@ -2471,7 +2493,7 @@
     return pickle_attr;
 }
 
-static PyObject *_PylibMC_Unpickle(const char *buff, Py_ssize_t size) {
+static PyObject *_PylibMC_Unpickle(PylibMC_Client *self, const char *buff, 
Py_ssize_t size) {
 #if PY_MAJOR_VERSION >= 3
         return PyObject_CallFunction(_PylibMC_pickle_loads, "y#", buff, size);
 #else
@@ -2479,12 +2501,12 @@
 #endif
 }
 
-static PyObject *_PylibMC_Unpickle_Bytes(PyObject *val) {
+static PyObject *_PylibMC_Unpickle_Bytes(PylibMC_Client *self, PyObject *val) {
     return PyObject_CallFunctionObjArgs(_PylibMC_pickle_loads, val, NULL);
 }
 
-static PyObject *_PylibMC_Pickle(PyObject *val) {
-    return PyObject_CallFunction(_PylibMC_pickle_dumps, "Oi", val, -1);
+static PyObject *_PylibMC_Pickle(PylibMC_Client *self, PyObject *val) {
+    return PyObject_CallFunction(_PylibMC_pickle_dumps, "Oi", val, 
self->pickle_protocol);
 }
 /* }}} */
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pylibmc-1.5.2/src/_pylibmcmodule.h 
new/pylibmc-1.6.0/src/_pylibmcmodule.h
--- old/pylibmc-1.5.2/src/_pylibmcmodule.h      2016-08-09 18:06:26.000000000 
+0200
+++ new/pylibmc-1.6.0/src/_pylibmcmodule.h      2018-11-09 18:42:08.000000000 
+0100
@@ -60,23 +60,29 @@
 /* {{{ Key flags from python-memcached
  * Some flags (like the compression one, ZLIB) are combined with others.
  */
-#define PYLIBMC_FLAG_NONE    0
-#define PYLIBMC_FLAG_PICKLE  (1 << 0)
-#define PYLIBMC_FLAG_INTEGER (1 << 1)
-#define PYLIBMC_FLAG_LONG    (1 << 2)
-/* Note: this is an addition! python-memcached doesn't handle bools. */
-#define PYLIBMC_FLAG_BOOL    (1 << 4)
-#define PYLIBMC_FLAG_TYPES   (PYLIBMC_FLAG_PICKLE | PYLIBMC_FLAG_INTEGER | \
-                              PYLIBMC_FLAG_LONG | PYLIBMC_FLAG_BOOL)
-/* Modifier flags */
-#define PYLIBMC_FLAG_ZLIB    (1 << 3)
+enum PylibMC_Flags {
+    PYLIBMC_FLAG_NONE    = 0,
+    PYLIBMC_FLAG_PICKLE  = (1 << 0),
+    PYLIBMC_FLAG_INTEGER = (1 << 1),
+    PYLIBMC_FLAG_LONG    = (1 << 2),
+    PYLIBMC_FLAG_ZLIB    = (1 << 3),
+    PYLIBMC_FLAG_TEXT    = (1 << 4),
+};
+
+#define PYLIBMC_FLAG_TYPES (PYLIBMC_FLAG_PICKLE | PYLIBMC_FLAG_INTEGER | \
+                            PYLIBMC_FLAG_LONG | PYLIBMC_FLAG_TEXT)
+/* }}} */
+
+/* Behaviors that only affects pylibmc (i.e. not memached_set_behavior etc) */
+enum PylibMC_Behaviors {
+    PYLIBMC_BEHAVIOR_PICKLE_PROTOCOL = 0xcafe0000,
+};
 
 /* Python 3 stuff */
 #ifndef PyVarObject_HEAD_INIT
 #define PyVarObject_HEAD_INIT(type, size)       \
     PyObject_HEAD_INIT(type) size,
 #endif
-/* }}} */
 
 typedef memcached_return (*_PylibMC_SetCommand)(memcached_st *, const char *,
         size_t, const char *, size_t, time_t, uint32_t);
@@ -228,6 +234,7 @@
 #if LIBMEMCACHED_VERSION_HEX >= 0x01000003
     { MEMCACHED_BEHAVIOR_DEAD_TIMEOUT, "dead_timeout" },
 #endif
+    { PYLIBMC_BEHAVIOR_PICKLE_PROTOCOL, "pickle_protocol" },
     { 0, NULL }
 };
 
@@ -278,6 +285,7 @@
     uint8_t sasl_set;
     uint8_t native_serialization;
     uint8_t native_deserialization;
+    int pickle_protocol;
 } PylibMC_Client;
 
 /* {{{ Prototypes */
@@ -315,9 +323,9 @@
         memcached_return, const char *, Py_ssize_t);
 static PyObject *PylibMC_ErrFromMemcached(PylibMC_Client *, const char *,
         memcached_return);
-static PyObject *_PylibMC_Unpickle(const char *, Py_ssize_t);
-static PyObject *_PylibMC_Unpickle_Bytes(PyObject *);
-static PyObject *_PylibMC_Pickle(PyObject *);
+static PyObject *_PylibMC_Unpickle(PylibMC_Client *, const char *, Py_ssize_t);
+static PyObject *_PylibMC_Unpickle_Bytes(PylibMC_Client *, PyObject *);
+static PyObject *_PylibMC_Pickle(PylibMC_Client *, PyObject *);
 static int _key_normalized_obj(PyObject **);
 static int _key_normalized_str(char **, Py_ssize_t *);
 static int _PylibMC_serialize_user(PylibMC_Client *, PyObject *, PyObject **, 
uint32_t *);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pylibmc-1.5.2/src/pylibmc/__main__.py 
new/pylibmc-1.6.0/src/pylibmc/__main__.py
--- old/pylibmc-1.5.2/src/pylibmc/__main__.py   2015-06-17 13:21:50.000000000 
+0200
+++ new/pylibmc-1.6.0/src/pylibmc/__main__.py   2018-11-09 18:42:08.000000000 
+0100
@@ -20,14 +20,14 @@
 def collect_servers():
     try:
         in_addr = raw_input("Address [127.0.0.1]: ")
-    except:
+    except NameError:
         in_addr = input("Address [127.0.0.1]: ")
     if in_addr:
         while in_addr:
             yield in_addr
             try:
                 in_addr = raw_input("Address [<stop>]: ")
-            except:
+            except NameError:
                 in_addr = input("Address [<stop>]: ")
     else:
         yield "127.0.0.1"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pylibmc-1.5.2/src/pylibmc/autoconf.py 
new/pylibmc-1.6.0/src/pylibmc/autoconf.py
--- old/pylibmc-1.5.2/src/pylibmc/autoconf.py   1970-01-01 01:00:00.000000000 
+0100
+++ new/pylibmc-1.6.0/src/pylibmc/autoconf.py   2018-11-09 18:42:08.000000000 
+0100
@@ -0,0 +1,62 @@
+"Autoconfiguration"
+
+from __future__ import unicode_literals
+import pylibmc
+
+class UnsupportedAutoconfMethod(Exception):
+    pass
+
+class NoAutoconfFound(Exception):
+    pass
+
+def _elasticache_config_get(address, key):
+    import socket
+    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
+    host, port = address.split(':')
+    port = int(port)
+    sock.connect((host, port))
+    sock.send(('config get %s\r\n' % (key,)).encode('ascii'))
+    state = 'wait-nl-header'
+    nbytes = 0
+    buff = b''
+    while True:
+        chunk = sock.recv(4096)
+        if not chunk:
+            raise RuntimeError('failed reading cluster config')
+        buff += chunk
+        if state.startswith('wait-nl-') and b'\r\n' not in buff:
+            continue
+        elif state == 'wait-nl-header':
+            line, buff = buff.split(b'\r\n', 1)
+            if line.lower() == b'error':
+                raise UnsupportedAutoconfMethod()
+            cmd, key, flags, nbytes = line.split()
+            flags, nbytes = int(flags), int(nbytes)
+            state = 'read-body'
+        elif state == 'ready-body':
+            if len(buff) < nbytes:
+                continue
+            config, buff = buff[:nbytes], buff[nbytes+2:]
+            state = 'wait-nl-end'
+        elif state == 'wait-nl-end':
+            break
+        else:
+            raise RuntimeError(state)
+    return config
+
+def _parse_elasticache_config(cfg):
+    ver, nodes = cfg.split(b'\n')
+    ver, nodes = int(ver), [n.decode('ascii').split('|') for n in 
nodes.split()]
+    # NOTE Should probably verify ver == 12, but why not try anyways
+    return ['%s:%s' % (addr or cname, port) for (cname, addr, port) in nodes]
+
+def elasticache(address='127.0.0.1:11211', config_key=b'cluster',
+                mc_key='AmazonElastiCache:cluster'):
+    try:
+        config = _elasticache_config_get(address, config_key)
+    except UnsupportedAutoconfMethod:
+        config = pylibmc.Client([address]).get(mc_key)
+        if config is None:
+            raise NoAutoconfFound
+    hosts = _parse_elasticache_config(config)
+    return pylibmc.Client(hosts)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pylibmc-1.5.2/src/pylibmc-version.h 
new/pylibmc-1.6.0/src/pylibmc-version.h
--- old/pylibmc-1.5.2/src/pylibmc-version.h     2017-03-06 14:10:05.000000000 
+0100
+++ new/pylibmc-1.6.0/src/pylibmc-version.h     2018-11-09 19:05:41.000000000 
+0100
@@ -1 +1 @@
-#define PYLIBMC_VERSION "1.5.2"
+#define PYLIBMC_VERSION "1.6.0"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pylibmc-1.5.2/tests/__init__.py 
new/pylibmc-1.6.0/tests/__init__.py
--- old/pylibmc-1.5.2/tests/__init__.py 2016-02-25 17:51:25.000000000 +0100
+++ new/pylibmc-1.6.0/tests/__init__.py 2018-11-09 18:42:08.000000000 +0100
@@ -23,14 +23,6 @@
         self.mc.disconnect_all()
         del self.mc
 
-def dump_infos():
-    if hasattr(_pylibmc, "__file__"):
-        print("Starting tests with _pylibmc at", _pylibmc.__file__)
-    else:
-        print("Starting tests with static _pylibmc:", _pylibmc)
-    print("Reported libmemcached version:", _pylibmc.libmemcached_version)
-    print("Reported pylibmc version:", _pylibmc.__version__)
-    print("Support compression:", _pylibmc.support_compression)
 
 def get_refcounts(refcountables):
     """Measure reference counts during testing.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pylibmc-1.5.2/tests/test_autoconf.py 
new/pylibmc-1.6.0/tests/test_autoconf.py
--- old/pylibmc-1.5.2/tests/test_autoconf.py    1970-01-01 01:00:00.000000000 
+0100
+++ new/pylibmc-1.6.0/tests/test_autoconf.py    2018-11-09 18:42:08.000000000 
+0100
@@ -0,0 +1,21 @@
+from pylibmc import autoconf
+from tests import PylibmcTestCase
+
+class AutoConfTests(PylibmcTestCase):
+    def test_no_autoconf(self):
+        self.mc.delete('AmazonElastiCache:cluster')
+        self.assertRaises(autoconf.NoAutoconfFound, autoconf.elasticache)
+
+    def test_autoconf(self):
+        addrtup = (self.memcached_host, self.memcached_port)
+        self.mc.set('AmazonElastiCache:cluster', ('12\nlocalhost|%s|%s' % 
addrtup).encode('ascii'))
+        mc = autoconf.elasticache(address=('%s:%s' % addrtup))
+        self.assert_(mc.set('a', 'b'))
+        self.assertEqual(mc.get('a'), 'b')
+
+    def test_autoconf_only_cname(self):
+        addrtup = (self.memcached_host, self.memcached_port)
+        self.mc.set('AmazonElastiCache:cluster', ('12\n%s||%s' % 
addrtup).encode('ascii'))
+        mc = autoconf.elasticache(address=('%s:%s' % addrtup))
+        self.assert_(mc.set('a', 'b'))
+        self.assertEqual(mc.get('a'), 'b')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pylibmc-1.5.2/tests/test_client.py 
new/pylibmc-1.6.0/tests/test_client.py
--- old/pylibmc-1.5.2/tests/test_client.py      2016-08-09 18:06:26.000000000 
+0200
+++ new/pylibmc-1.6.0/tests/test_client.py      2018-11-09 18:42:08.000000000 
+0100
@@ -43,9 +43,9 @@
         expected_behaviors = [
             'auto_eject', 'buffer_requests', 'cas', 'connect_timeout',
             'distribution', 'failure_limit', 'hash', 'ketama', 'ketama_hash',
-            'ketama_weighted', 'no_block', 'num_replicas', 'receive_timeout',
-            'retry_timeout', 'send_timeout', 'tcp_keepalive', 'tcp_nodelay',
-            'verify_keys']
+            'ketama_weighted', 'no_block', 'num_replicas', 'pickle_protocol',
+            'receive_timeout', 'retry_timeout', 'send_timeout',
+            'tcp_keepalive', 'tcp_nodelay', 'verify_keys']
 
         # Since some parts of pyblibmc's functionality depend on the
         # libmemcached version, programatically check for the expected values
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pylibmc-1.5.2/tests/test_serialization.py 
new/pylibmc-1.6.0/tests/test_serialization.py
--- old/pylibmc-1.5.2/tests/test_serialization.py       2016-08-18 
15:30:00.000000000 +0200
+++ new/pylibmc-1.6.0/tests/test_serialization.py       2018-11-09 
18:42:08.000000000 +0100
@@ -1,3 +1,5 @@
+# -*- coding: utf-8 -*-
+
 from __future__ import unicode_literals
 from __future__ import print_function
 
@@ -25,6 +27,8 @@
         # this happens under Python 3
         return val
 
+f_none = 0
+f_pickle, f_int, f_long, f_zlib, f_text = (1 << i for i in range(5))
 
 class SerializationMethodTests(PylibmcTestCase):
     """Coverage tests for serialize and deserialize."""
@@ -32,29 +36,33 @@
     def test_integers(self):
         c = make_test_client(binary=True)
         if sys.version_info[0] == 3:
-            eq_(c.serialize(1), (b'1', 4))
-            eq_(c.serialize(2**64), (b'18446744073709551616', 4))
+            eq_(c.serialize(1), (b'1', f_long))
+            eq_(c.serialize(2**64), (b'18446744073709551616', f_long))
         else:
-            eq_(c.serialize(1), (b'1', 2))
-            eq_(c.serialize(2**64), (b'18446744073709551616', 4))
+            eq_(c.serialize(1), (b'1', f_int))
+            eq_(c.serialize(2**64), (b'18446744073709551616', f_long))
 
-            eq_(c.deserialize(b'1', 2), 1)
+            eq_(c.deserialize(b'1', f_int), 1)
 
-        eq_(c.deserialize(b'18446744073709551616', 4), 2**64)
-        eq_(c.deserialize(b'1', 4), long_(1))
+        eq_(c.deserialize(b'18446744073709551616', f_long), 2**64)
+        eq_(c.deserialize(b'1', f_long), long_(1))
 
     def test_nonintegers(self):
         # tuples (python_value, (expected_bytestring, expected_flags))
         SERIALIZATION_TEST_VALUES = [
-            # booleans
-            (True, (b'1', 16)),
-            (False, (b'0', 16)),
+            # booleans are just ints
+            (True, (b'1', f_int)),
+            (False, (b'0', f_int)),
             # bytestrings
-            (b'asdf', (b'asdf', 0)),
-            (b'\xb5\xb1\xbf\xed\xa9\xc2{8', (b'\xb5\xb1\xbf\xed\xa9\xc2{8', 
0)),
+            (b'asdf', (b'asdf', f_none)),
+            (b'\xb5\xb1\xbf\xed\xa9\xc2{8', (b'\xb5\xb1\xbf\xed\xa9\xc2{8', 
f_none)),
+            (b'', (b'', f_none)),
+            # unicode objects
+            (u'åäö', (u'åäö'.encode('utf-8'), f_text)),
+            (u'', (b'', f_text)),
             # objects
             (datetime.date(2015, 12, 28), (pickle.dumps(datetime.date(2015, 
12, 28),
-                                                        protocol=-1), 1)),
+                                                        protocol=-1), 
f_pickle)),
         ]
 
         c = make_test_client(binary=True)


Reply via email to