diff -Nru pylibmc-1.2.2/PKG-INFO pylibmc-1.2.3/PKG-INFO --- pylibmc-1.2.2/PKG-INFO 2011-10-28 13:59:07.000000000 +0000 +++ pylibmc-1.2.3/PKG-INFO 2012-04-26 16:05:31.000000000 +0000 @@ -1,6 +1,6 @@ Metadata-Version: 1.0 Name: pylibmc -Version: 1.2.2 +Version: 1.2.3 Summary: Quick and small memcached client for Python Home-page: http://sendapatch.se/projects/pylibmc/ Author: Ludvig Ericson diff -Nru pylibmc-1.2.2/_pylibmcmodule.c pylibmc-1.2.3/_pylibmcmodule.c --- pylibmc-1.2.2/_pylibmcmodule.c 2011-10-28 13:49:27.000000000 +0000 +++ pylibmc-1.2.3/_pylibmcmodule.c 2012-04-26 16:05:21.000000000 +0000 @@ -127,7 +127,11 @@ #endif } - memcached_behavior_set(self->mc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, bin); + rc = memcached_behavior_set(self->mc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, bin); + if (rc != MEMCACHED_SUCCESS) { + PyErr_SetString(PyExc_RuntimeError, "binary protocol behavior set failed"); + goto error; + } while ((c_srv = PyIter_Next(srvs_it)) != NULL) { unsigned char stype; @@ -159,8 +163,11 @@ } else { set_stype = stype; if (stype == PYLIBMC_SERVER_UDP) { - memcached_behavior_set(self->mc, - MEMCACHED_BEHAVIOR_USE_UDP, 1); + rc = memcached_behavior_set(self->mc, MEMCACHED_BEHAVIOR_USE_UDP, 1); + if (rc != MEMCACHED_SUCCESS) { + PyErr_SetString(PyExc_RuntimeError, "udp behavior set failed"); + goto it_error; + } } } @@ -471,7 +478,7 @@ static PyObject *PylibMC_Client_gets(PylibMC_Client *self, PyObject *arg) { const char* keys[2]; size_t keylengths[2]; - memcached_result_st *res, *res0; + memcached_result_st *res = NULL; memcached_return rc; PyObject* ret = NULL; @@ -494,12 +501,8 @@ Py_BEGIN_ALLOW_THREADS; rc = memcached_mget(self->mc, keys, keylengths, 1); - if (rc == MEMCACHED_SUCCESS) { - res0 = memcached_result_create(self->mc, NULL); - /* this will be NULL if the key wasn't found, or - memcached_result_st if it was */ - res = memcached_fetch_result(self->mc, res0, &rc); - } + if (rc == MEMCACHED_SUCCESS) + res = memcached_fetch_result(self->mc, res, &rc); Py_END_ALLOW_THREADS; @@ -509,8 +512,7 @@ memcached_result_cas(res)); /* we have to fetch the last result from the mget cursor */ - res = memcached_fetch_result(self->mc, res0, &rc); - if (res || rc != MEMCACHED_END) { + if (NULL != memcached_fetch_result(self->mc, NULL, &rc)) { memcached_quit(self->mc); Py_DECREF(ret); ret = NULL; @@ -523,10 +525,8 @@ ret = PylibMC_ErrFromMemcached(self, "memcached_gets", rc); } - /* deallocate any indirect buffers, even though the struct itself - is on our stack */ - if (res0 != NULL) { - memcached_result_free(res0); + if (res != NULL) { + memcached_result_free(res); } return ret; @@ -886,7 +886,7 @@ pylibmc_mset *mset = &msets[pos]; char *value = mset->value; - size_t value_len = mset->value_len; + size_t value_len = (size_t)mset->value_len; uint32_t flags = mset->flags; #ifdef USE_ZLIB @@ -998,30 +998,26 @@ } static PyObject *PylibMC_Client_delete(PylibMC_Client *self, PyObject *args) { - PyObject *retval; char *key; - Py_ssize_t key_sz; + Py_ssize_t key_len = 0; memcached_return rc; - retval = NULL; - if (PyArg_ParseTuple(args, "s#:delete", &key, &key_sz) - && _PylibMC_CheckKeyStringAndSize(key, key_sz)) { + if (PyArg_ParseTuple(args, "s#:delete", &key, &key_len) + && _PylibMC_CheckKeyStringAndSize(key, key_len)) { Py_BEGIN_ALLOW_THREADS; - rc = memcached_delete(self->mc, key, key_sz, 0); + rc = memcached_delete(self->mc, key, key_len, 0); Py_END_ALLOW_THREADS; switch (rc) { case MEMCACHED_SUCCESS: Py_RETURN_TRUE; - break; case MEMCACHED_FAILURE: case MEMCACHED_NOTFOUND: case MEMCACHED_NO_KEY_PROVIDED: case MEMCACHED_BAD_KEY_PROVIDED: Py_RETURN_FALSE; - break; default: return PylibMC_ErrFromMemcachedWithKey(self, "memcached_delete", - rc, key, key_sz); + rc, key, key_len); } } @@ -1033,15 +1029,25 @@ _PylibMC_IncrCommand incr_func, PyObject *args) { char *key; - Py_ssize_t key_len; - unsigned int delta = 1; + Py_ssize_t key_len = 0; + int delta = 1; - if (!PyArg_ParseTuple(args, "s#|I", &key, &key_len, &delta)) { + if (!PyArg_ParseTuple(args, "s#|i", &key, &key_len, &delta)) { return NULL; } else if (!_PylibMC_CheckKeyStringAndSize(key, key_len)) { return NULL; } + if (delta < 0L) { + PyErr_SetString(PyExc_ValueError, "delta must be positive"); + return NULL; + } + + if ((unsigned int)delta != delta) { + PyErr_Format(PyExc_OverflowError, "%d", delta); + return NULL; + } + pylibmc_incr incr = { key, key_len, incr_func, delta, 0 }; @@ -1060,132 +1066,95 @@ static PyObject *_PylibMC_IncrMulti(PylibMC_Client *self, _PylibMC_IncrCommand incr_func, PyObject *args, PyObject *kwds) { - /** - * Takes an iterable of keys and a single delta (that defaults to 1) - * to be applied to all keys. Consider the return value and exception - * behaviour to be undocumented, for now it returns None and throws an - * exception on an error incrementing any key - */ - + PyObject *key = NULL; PyObject *keys = NULL; + PyObject *keys_tmp = NULL; PyObject *key_prefix = NULL; - PyObject *prefixed_keys = NULL; PyObject *retval = NULL; PyObject *iterator = NULL; unsigned int delta = 1; + size_t nkeys = 0, i = 0; static char *kws[] = { "keys", "key_prefix", "delta", NULL }; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|SI", kws, - &keys, &key_prefix, &delta)) { + &keys, &key_prefix, &delta)) return NULL; - } - size_t nkeys = (size_t)PySequence_Size(keys); - if(nkeys == -1) + nkeys = (size_t)PySequence_Size(keys); + if (nkeys == -1) return NULL; - if(key_prefix == NULL || PyString_Size(key_prefix) < 1) { - /* if it's 0-length, we can safely pretend it doesn't exist */ - key_prefix = NULL; - } - if(key_prefix != NULL) { - if(!_PylibMC_CheckKey(key_prefix)) { + if (key_prefix != NULL) { + if (!_PylibMC_CheckKey(key_prefix)) return NULL; - } - prefixed_keys = PyList_New(nkeys); - if(prefixed_keys == NULL) { - return NULL; - } + if (PyString_Size(key_prefix) == 0) + key_prefix = NULL; } - pylibmc_incr* incrs = PyMem_New(pylibmc_incr, nkeys); - if(incrs == NULL) { + keys_tmp = PyList_New(nkeys); + if (keys_tmp == NULL) + return NULL; + + pylibmc_incr *incrs = PyMem_New(pylibmc_incr, nkeys); + if (incrs == NULL) goto cleanup; - } iterator = PyObject_GetIter(keys); - if(iterator == NULL) { + if (iterator == NULL) goto cleanup; - } - PyObject *key = NULL; - size_t idx = 0; + /* Build pylibmc_incr structs, prefixed as appropriate. */ + for (i = 0; (key = PyIter_Next(iterator)) != NULL; i++) { + pylibmc_incr *incr = incrs + i; - /** - * Build our list of keys, prefixed as appropriate, and turn that - * into a list of pylibmc_incr objects that can be incred in one - * go. We're not going to own references to the prefixed keys: so - * that we can free them all at once, we'll give ownership to a list - * of them (prefixed_keys) which we'll DECR once at the end - */ - - while((key = PyIter_Next(iterator)) != NULL) { - if(!_PylibMC_CheckKey(key)) goto loopcleanup; - - if(key_prefix != NULL) { - PyObject* newkey = NULL; - - newkey = PyString_FromFormat("%s%s", - PyString_AS_STRING(key_prefix), - PyString_AS_STRING(key)); - - if(!_PylibMC_CheckKey(newkey)) { - Py_XDECREF(newkey); - goto loopcleanup; - } - - /* steals our reference */ - if(PyList_SetItem(prefixed_keys, idx, newkey) == -1) { - /* it wasn't stolen before the error */ - Py_DECREF(newkey); - goto loopcleanup; - } + if (!_PylibMC_CheckKey(key)) + goto loopcleanup; - /* the list stole our reference to it, and we're going to rely - on that list to maintain it while we release the GIL, but - since we DECREF the key in loopcleanup we need to INCREF it - here */ + /* prefix `key` with `key_prefix` */ + if (key_prefix != NULL) { + PyObject* newkey = PyString_FromFormat("%s%s", + PyString_AS_STRING(key_prefix), + PyString_AS_STRING(key)); Py_DECREF(key); - Py_INCREF(newkey); key = newkey; } - if(PyString_AsStringAndSize(key, &incrs[idx].key, - &incrs[idx].key_len) == -1) + Py_INCREF(key); + if (PyList_SetItem(keys_tmp, i, key) == -1) goto loopcleanup; - incrs[idx].delta = delta; - incrs[idx].incr_func = incr_func; + /* Populate pylibmc_incr */ + if (PyString_AsStringAndSize(key, &incr->key, &incr->key_len) == -1) + goto loopcleanup; + incr->delta = delta; + incr->incr_func = incr_func; /* After incring we have no way of knowing whether the real result is 0 * or if the incr wasn't successful (or if noreply is set), but since * we're not actually returning the result that's okay for now */ - incrs[idx].result = 0; + incr->result = 0; loopcleanup: Py_DECREF(key); - - if(PyErr_Occurred()) - break; - - idx++; + if (PyErr_Occurred()) + goto cleanup; } /* end each key */ - /* iteration error */ - if (PyErr_Occurred()) goto cleanup; - _PylibMC_IncrDecr(self, incrs, nkeys); - /* if that failed, there's an exception on the stack */ - if(PyErr_Occurred()) goto cleanup; - - retval = Py_None; - Py_INCREF(retval); + if (!PyErr_Occurred()) { + retval = Py_None; + Py_INCREF(retval); + } else { + Py_XDECREF(retval); + retval = NULL; + } cleanup: - PyMem_Free(incrs); - Py_XDECREF(prefixed_keys); + if (incrs != NULL) + PyMem_Free(incrs); + Py_DECREF(keys_tmp); Py_XDECREF(iterator); return retval; @@ -1206,34 +1175,42 @@ static bool _PylibMC_IncrDecr(PylibMC_Client *self, pylibmc_incr *incrs, size_t nkeys) { - bool error = false; memcached_return rc = MEMCACHED_SUCCESS; _PylibMC_IncrCommand f = NULL; - size_t i; + size_t i, notfound = 0, errors = 0; Py_BEGIN_ALLOW_THREADS; - for (i = 0; i < nkeys && !error; i++) { + for (i = 0; i < nkeys; i++) { pylibmc_incr *incr = &incrs[i]; uint64_t result = 0; f = incr->incr_func; rc = f(self->mc, incr->key, incr->key_len, incr->delta, &result); + /* TODO Signal errors through `incr` */ if (rc == MEMCACHED_SUCCESS) { incr->result = result; + } else if (rc == MEMCACHED_NOTFOUND) { + notfound++; } else { - error = true; + errors++; } } Py_END_ALLOW_THREADS; - if (error) { - char *fname = (f == memcached_decrement) ? "memcached_decrement" - : "memcached_increment"; - PylibMC_ErrFromMemcached(self, fname, rc); - return false; - } else { - return true; + if (errors + notfound) { + PyObject *exc = PylibMCExc_MemcachedError; + + if (errors == 0) + exc = _exc_by_rc(MEMCACHED_NOTFOUND); + else if (errors == 1) + exc = _exc_by_rc(rc); + + PyErr_Format(exc, "%d keys %s", + (int)(notfound + errors), + errors ? "failed" : "not found"); } + + return 0 == (errors + notfound); } /* }}} */ @@ -1363,8 +1340,10 @@ key_lens[i] = (size_t)(key_len + prefix_len); /* Skip empty keys */ - if (!key_lens[i]) + if (!key_lens[i]) { + Py_DECREF(ckey); continue; + } /* determine rkey, the prefixed ckey */ if (prefix != NULL) { @@ -1372,6 +1351,7 @@ PyString_Concat(&rkey, ckey); if (rkey == NULL) goto earlybird; + Py_DECREF(rkey); rkey = PyString_FromFormat("%s%s", prefix, PyString_AS_STRING(ckey)); } else { @@ -1420,9 +1400,7 @@ res = results + i; - /* Explicitly construct a key string object so that NUL-bytes and the - * likes can be contained within the keys (this is possible in the - * binary protocol.) */ + /* Long-winded, but this way we can handle NUL-bytes in keys. */ key_obj = PyString_FromStringAndSize(memcached_result_key_value(res) + prefix_len, memcached_result_key_length(res) - prefix_len); if (key_obj == NULL) @@ -1443,8 +1421,9 @@ continue; unpack_error: - Py_DECREF(retval); - break; + Py_DECREF(retval); + retval = NULL; + break; } earlybird: @@ -1790,11 +1769,6 @@ context.servers = NULL; /* DEPRECATED */ context.index = 0; - /* TODO Remove BC for 0.38 */ -#ifndef LIBMEMCACHED_VERSION_HEX -# define LIBMEMCACHED_VERSION_HEX 0x0 -#endif - #if LIBMEMCACHED_VERSION_HEX >= 0x00038000 memcached_server_function callbacks[] = { (memcached_server_function)_PylibMC_AddServerCallback @@ -1876,26 +1850,21 @@ } /* }}} */ +static PyObject *_exc_by_rc(memcached_return rc) { + PylibMC_McErr *err; + for (err = PylibMCExc_mc_errs; err->name != NULL; err++) + if (err->rc == rc) + return err->exc; + return (PyObject *)PylibMCExc_MemcachedError; +} + static char *_get_lead(memcached_st *mc, char *buf, int n, const char *what, memcached_return error, const char *key, Py_ssize_t len) { - int sz = snprintf(buf, n, "error %d from %s", error, what); + int sz = snprintf(buf, n, "error %d from %.32s", error, what); - /* - * Need to protect from libmemcached versions as their - * memcached_server_instance_st are called (memcached_server_st *). - */ -#if LIBMEMCACHED_VERSION_HEX >= 0x00038000 - if (key != NULL) { - memcached_return rc = MEMCACHED_FAILURE; - memcached_server_instance_st svr = NULL; - - svr = memcached_server_by_key(mc, key, len, &rc); - if (svr && rc == MEMCACHED_SUCCESS) { - sz += snprintf(buf + sz, n - sz, " on %s:%d", - svr->hostname, svr->port); - } + if (key != NULL && len) { + sz += snprintf(buf+sz, n-sz, "(%.32s)", key); } -#endif return buf; } @@ -1907,17 +1876,12 @@ } else if (error == MEMCACHED_SUCCESS) { PyErr_Format(PyExc_RuntimeError, "error == MEMCACHED_SUCCESS"); } else { - PylibMC_McErr *err; - PyObject *exc = (PyObject *)PylibMCExc_MemcachedError; - - for (err = PylibMCExc_mc_errs; err->name != NULL; err++) { - if (err->rc == error) { - exc = err->exc; - break; - } - } - - PyErr_Format(exc, "%s: %s", lead, memcached_strerror(mc, error)); + PyObject *exc = _exc_by_rc(error); +#if LIBMEMCACHED_VERSION_HEX >= 0x00049000 + PyErr_Format(exc, "%s: %.200s", lead, memcached_last_error_message(mc)); +#else + PyErr_Format(exc, "%s: %.200s", lead, memcached_strerror(mc, error)); +#endif } } @@ -2060,7 +2024,7 @@ uint8_t maj, min; char *ver, *dot, *tmp; - ver = dot = strndup(LIBMEMCACHED_VERSION_STRING, 8); + ver = dot = strdup(LIBMEMCACHED_VERSION_STRING); while ((tmp = strrchr(ver, '.')) != NULL) { dot = tmp; *dot = 0; diff -Nru pylibmc-1.2.2/_pylibmcmodule.h pylibmc-1.2.3/_pylibmcmodule.h --- pylibmc-1.2.2/_pylibmcmodule.h 2011-09-07 23:27:08.000000000 +0000 +++ pylibmc-1.2.3/_pylibmcmodule.h 2012-04-26 16:05:21.000000000 +0000 @@ -41,6 +41,10 @@ #include #include +#ifndef LIBMEMCACHED_VERSION_HEX +# define LIBMEMCACHED_VERSION_HEX 0x0 +#endif + #include "pylibmc-version.h" /* Py_ssize_t appeared in Python 2.5. */ @@ -73,18 +77,20 @@ typedef memcached_return (*_PylibMC_IncrCommand)(memcached_st *, const char *, size_t, unsigned int, uint64_t*); +static PyObject *_exc_by_rc(memcached_return); + typedef struct { char *key; Py_ssize_t key_len; - char* value; + char *value; Py_ssize_t value_len; time_t time; uint32_t flags; /* the objects that must be freed after the mset is executed */ - PyObject* key_obj; - PyObject* prefixed_key_obj; - PyObject* value_obj; + PyObject *key_obj; + PyObject *prefixed_key_obj; + PyObject *value_obj; /* the success of executing the mset afterwards */ int success; @@ -151,7 +157,10 @@ //{ MEMCACHED_BUFFERED, "Buffer, NULL }, { MEMCACHED_BAD_KEY_PROVIDED, "BadKeyProvided", NULL }, { MEMCACHED_INVALID_HOST_PROTOCOL, "InvalidHostProtocolError", NULL }, - //{ MEMCACHED_SERVER_MARKED_DEAD, + { MEMCACHED_SERVER_MARKED_DEAD, "ServerDead", NULL }, +#ifdef MEMCACHED_SERVER_TEMPORARILY_DISABLED + { MEMCACHED_SERVER_TEMPORARILY_DISABLED, "ServerDown", NULL }, +#endif { MEMCACHED_UNKNOWN_STAT_KEY, "UnknownStatKey", NULL }, //{ MEMCACHED_E2BIG, "TooBigError", NULL }, { 0, NULL, NULL } @@ -180,6 +189,7 @@ { MEMCACHED_BEHAVIOR_RCV_TIMEOUT, "receive_timeout" }, { MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS, "num_replicas" }, { MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS, "auto_eject" }, + { MEMCACHED_BEHAVIOR_RETRY_TIMEOUT, "retry_timeout" }, #if LIBMEMCACHED_VERSION_HEX >= 0x00049000 { MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS, "remove_failed" }, #endif @@ -193,7 +203,6 @@ { MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY, "_hash_with_prefix_key" }, { MEMCACHED_BEHAVIOR_NOREPLY, "_noreply" }, { MEMCACHED_BEHAVIOR_SORT_HOSTS, "_sort_hosts" }, - { MEMCACHED_BEHAVIOR_RETRY_TIMEOUT, "_retry_timeout" }, { MEMCACHED_BEHAVIOR_POLL_TIMEOUT, "_poll_timeout" }, { MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE, "_socket_send_size" }, { MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE, "_socket_recv_size" }, @@ -265,23 +274,23 @@ static PyObject *_PylibMC_Pickle(PyObject *); static int _PylibMC_CheckKey(PyObject *); static int _PylibMC_CheckKeyStringAndSize(char *, Py_ssize_t); -static int _PylibMC_SerializeValue(PyObject* key_obj, - PyObject* key_prefix, - PyObject* value_obj, +static int _PylibMC_SerializeValue(PyObject *key_obj, + PyObject *key_prefix, + PyObject *value_obj, time_t time, - pylibmc_mset* serialized); + pylibmc_mset *serialized); static void _PylibMC_FreeMset(pylibmc_mset*); static PyObject *_PylibMC_RunSetCommandSingle(PylibMC_Client *self, _PylibMC_SetCommand f, char *fname, PyObject *args, PyObject *kwds); -static PyObject *_PylibMC_RunSetCommandMulti(PylibMC_Client* self, +static PyObject *_PylibMC_RunSetCommandMulti(PylibMC_Client *self, _PylibMC_SetCommand f, char *fname, PyObject *args, PyObject *kwds); -static bool _PylibMC_RunSetCommand(PylibMC_Client* self, +static bool _PylibMC_RunSetCommand(PylibMC_Client *self, _PylibMC_SetCommand f, char *fname, - pylibmc_mset* msets, size_t nkeys, + pylibmc_mset *msets, size_t nkeys, size_t min_compress); -static int _PylibMC_Deflate(char* value, size_t value_len, - char** result, size_t *result_len); -static bool _PylibMC_IncrDecr(PylibMC_Client*, pylibmc_incr*, size_t); +static int _PylibMC_Deflate(char *value, size_t value_len, + char **result, size_t *result_len); +static bool _PylibMC_IncrDecr(PylibMC_Client *, pylibmc_incr *, size_t); /* }}} */ diff -Nru pylibmc-1.2.2/debian/changelog pylibmc-1.2.3/debian/changelog --- pylibmc-1.2.2/debian/changelog 2012-05-23 06:11:43.000000000 +0000 +++ pylibmc-1.2.3/debian/changelog 2013-07-02 23:04:10.000000000 +0000 @@ -1,8 +1,17 @@ -pylibmc (1.2.2-1build1) quantal; urgency=low +pylibmc (1.2.3-1) unstable; urgency=low - * Rebuild for memcached transition + [ Jakub Wilk ] + * Use canonical URIs for Vcs-* fields. - -- Bhavani Shankar Wed, 23 May 2012 11:41:05 +0530 + [ Carl Chenet ] + * New upstream release + - debian/control + - bump Standards-Version to 3.9.4.0 + - bump python minimum version to 2.6 + - debian/compat + - bump to 9 + + -- Carl Chenet Wed, 19 Jun 2013 23:31:07 +0200 pylibmc (1.2.2-1) unstable; urgency=low diff -Nru pylibmc-1.2.2/debian/compat pylibmc-1.2.3/debian/compat --- pylibmc-1.2.2/debian/compat 2011-02-15 20:52:56.000000000 +0000 +++ pylibmc-1.2.3/debian/compat 2013-06-27 17:39:44.000000000 +0000 @@ -1 +1 @@ -7 +9 diff -Nru pylibmc-1.2.2/debian/control pylibmc-1.2.3/debian/control --- pylibmc-1.2.2/debian/control 2011-12-07 18:56:53.000000000 +0000 +++ pylibmc-1.2.3/debian/control 2013-06-27 17:45:26.000000000 +0000 @@ -1,14 +1,14 @@ Source: pylibmc Section: python Priority: optional -X-Python-Version: >= 2.5 +X-Python-Version: >= 2.6 Maintainer: Debian Python Modules Team Uploaders: Carl Chenet -Build-Depends: debhelper (>= 7.0.50~), python (>= 2.5), python-all-dev, python-all-dbg, libmemcached-dev, zlib1g-dev -Standards-Version: 3.9.2.0 +Build-Depends: debhelper (>= 9.0), python-all-dev (>= 2.6.6-3), python-all-dbg (>= 2.6.6-3), libmemcached-dev, zlib1g-dev +Standards-Version: 3.9.4.0 Homepage: http://pypi.python.org/pypi/pylibmc/ -Vcs-Svn: svn://svn.debian.org/python-modules/packages/pylibmc/trunk -Vcs-Browser: http://svn.debian.org/viewsvn/python-modules/packages/pylibmc/trunk/ +Vcs-Svn: svn://anonscm.debian.org/python-modules/packages/pylibmc/trunk/ +Vcs-Browser: http://anonscm.debian.org/viewvc/python-modules/packages/pylibmc/trunk/ Package: python-pylibmc Architecture: any diff -Nru pylibmc-1.2.2/docs/_themes/sap/static/main.css_t pylibmc-1.2.3/docs/_themes/sap/static/main.css_t --- pylibmc-1.2.2/docs/_themes/sap/static/main.css_t 2011-07-24 14:24:21.000000000 +0000 +++ pylibmc-1.2.3/docs/_themes/sap/static/main.css_t 2012-01-08 08:06:54.000000000 +0000 @@ -16,7 +16,7 @@ body { font-family: {{ theme_bodyfont }}; font-size: 100%; - background-color: {{ theme_bgcolor }}; + background: {{ theme_bgcolor }} url('http://sendapatch.se/bg.png'); color: #000; margin: 0; padding: 0; diff -Nru pylibmc-1.2.2/docs/_themes/sap/theme.conf pylibmc-1.2.3/docs/_themes/sap/theme.conf --- pylibmc-1.2.2/docs/_themes/sap/theme.conf 2011-07-24 14:24:33.000000000 +0000 +++ pylibmc-1.2.3/docs/_themes/sap/theme.conf 2012-01-08 08:06:54.000000000 +0000 @@ -10,7 +10,7 @@ externalrefs = false nosidebar = true -bgcolor = #f5f5f5 +bgcolor = #fefefe contentbgcolor = #efefef contentboxcolor = #c0c0c0 footertextcolor = #2e2e2e diff -Nru pylibmc-1.2.2/docs/behaviors.rst pylibmc-1.2.3/docs/behaviors.rst --- pylibmc-1.2.2/docs/behaviors.rst 2011-07-24 14:20:15.000000000 +0000 +++ pylibmc-1.2.3/docs/behaviors.rst 2012-04-26 16:05:21.000000000 +0000 @@ -213,8 +213,27 @@ Failover -------- +Most people desire the classical "I don't really care" type of failover +support: if a server goes down, just use another one. This, sadly, is not an +option with libmemcached for the time being. + When libmemcached introduced a behavior called ``remove_failed``, two other behaviors were deprecated in its stead called ``auto_eject`` and ``failure_limit`` -- this new behavior is a combination of the latter two. When enabled, the numeric value is the number of times a server may fail before it is ejected, and when not, no ejection occurs. + +"Ejection" simply means *libmemcached will stop using that server without +trying any others.* + +So, if you configure the behaviors ``remove_failed=4`` and ``retry_timeout=10`` +and one of your four servers go down for some reason, then the first request to +that server will trigger whatever actual error occurred (connection reset, read +error, etc), then the subsequent requests to that server within 10 seconds will +all raise ``ServerDown``, then again an actual request is made and the cycle +repeats until four consequent errors have occurred, at which point +``ServerDead`` will be raised immediately. + +In other words, ``ServerDown`` means that if the server comes back up, it goes +into rotation; ``ServerDead`` means that this key is unusable until the client +is reset. diff -Nru pylibmc-1.2.2/docs/coders.rst pylibmc-1.2.3/docs/coders.rst --- pylibmc-1.2.2/docs/coders.rst 2011-07-22 11:00:25.000000000 +0000 +++ pylibmc-1.2.3/docs/coders.rst 2012-04-04 12:45:30.000000000 +0000 @@ -6,3 +6,5 @@ * Ruda Moura * Noah Silas * Johan Bergström +* Andrew McFague +* James Brown diff -Nru pylibmc-1.2.2/docs/index.rst pylibmc-1.2.3/docs/index.rst --- pylibmc-1.2.2/docs/index.rst 2011-07-25 07:37:25.000000000 +0000 +++ pylibmc-1.2.3/docs/index.rst 2012-01-08 08:07:00.000000000 +0000 @@ -29,6 +29,10 @@ ... behaviors={"tcp_nodelay": True, ... "ketama": True}) +.. hint:: In earlier versions ``behaviors`` was no keyword + argument, only an attribute. To safe-guard version compatibility use + ``mc.behaviors = {...}`` + Basic memcached operations can be accomplished with the mapping interface:: >>> mc["some_key"] = "Some value" @@ -49,8 +53,6 @@ True >>> mc.delete("another_key") True - >>> mc.set("key", "1") # str or int is fine - True Automatic pickling of complex Python types:: @@ -67,6 +69,8 @@ Atomic memcached-side increments and decrements:: + >>> mc.set("key", "1") # str or int is fine + True >>> mc.incr("key") 2L >>> mc.decr("key") diff -Nru pylibmc-1.2.2/pylibmc/client.py pylibmc-1.2.3/pylibmc/client.py --- pylibmc-1.2.2/pylibmc/client.py 2011-08-22 15:22:51.000000000 +0000 +++ pylibmc-1.2.3/pylibmc/client.py 2012-04-26 16:05:21.000000000 +0000 @@ -148,13 +148,18 @@ (where it most surely will error out.) This also happens for `distribution`. + + Translates old underscored behavior names to new ones for API leniency. """ + behaviors = behaviors.copy() + if "_retry_timeout" in behaviors: + behaviors.setdefault("retry_timeout", behaviors.pop("_retry_timeout")) + unknown = set(behaviors).difference(_all_behaviors_set) if unknown: names = ", ".join(map(str, sorted(unknown))) raise ValueError("unknown behavior names: %s" % (names,)) - behaviors = behaviors.copy() if behaviors.get("hash") is not None: behaviors["hash"] = hashers[behaviors["hash"]] if behaviors.get("ketama_hash") in hashers: diff -Nru pylibmc-1.2.2/pylibmc-version.h pylibmc-1.2.3/pylibmc-version.h --- pylibmc-1.2.2/pylibmc-version.h 2011-10-28 13:58:40.000000000 +0000 +++ pylibmc-1.2.3/pylibmc-version.h 2012-04-26 16:05:21.000000000 +0000 @@ -1 +1 @@ -#define PYLIBMC_VERSION "1.2.2" +#define PYLIBMC_VERSION "1.2.3" diff -Nru pylibmc-1.2.2/tests/test_client.py pylibmc-1.2.3/tests/test_client.py --- pylibmc-1.2.2/tests/test_client.py 2011-08-22 16:16:41.000000000 +0000 +++ pylibmc-1.2.3/tests/test_client.py 2012-01-08 08:07:50.000000000 +0000 @@ -1,12 +1,22 @@ import pylibmc from pylibmc.test import make_test_client from tests import PylibmcTestCase -from nose.tools import eq_ +from nose.tools import eq_, ok_ class ClientTests(PylibmcTestCase): def test_zerokey(self): bc = make_test_client(binary=True) k = "\x00\x01" - assert bc.set(k, "test") + ok_(bc.set(k, "test")) rk = bc.get_multi([k]).keys()[0] eq_(k, rk) + + def test_cas(self): + k = "testkey" + mc = make_test_client(binary=False, behaviors={"cas": True}) + ok_(mc.set(k, 0)) + while True: + rv, cas = mc.gets(k) + ok_(mc.cas(k, rv + 1, cas)) + if rv == 10: + break