[Python-modules-commits] [pylibmc] 11/18: Import pylibmc_1.5.2.orig.tar.gz
Michael Fladischer
fladi at moszumanska.debian.org
Mon Jul 24 13:23:57 UTC 2017
This is an automated email from the git hooks/post-receive script.
fladi pushed a commit to branch master
in repository pylibmc.
commit 01fa087f70b0369acfe51309e5579c75072f0964
Author: Michael Fladischer <FladischerMichael at fladi.at>
Date: Mon Jul 24 13:40:11 2017 +0200
Import pylibmc_1.5.2.orig.tar.gz
---
MANIFEST.in | 2 +-
PKG-INFO | 3 +-
docs/failover.svg | 130 +++++++++++++++++++++++++++++++++++++
docs/install.rst | 2 +-
docs/reference.rst | 18 ++----
setup.py | 1 +
src/_pylibmcmodule.c | 152 +++++++++++++++++++-------------------------
src/_pylibmcmodule.h | 25 ++++----
src/pylibmc-version.h | 2 +-
src/pylibmc/__init__.py | 11 +---
src/pylibmc/client.py | 8 ++-
tests/test_client.py | 17 +++++
tests/test_refcounts.py | 19 ++++++
tests/test_serialization.py | 3 +-
14 files changed, 267 insertions(+), 126 deletions(-)
diff --git a/MANIFEST.in b/MANIFEST.in
index 79a1587..c293df1 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -3,6 +3,6 @@ include src/_pylibmcmodule.c src/_pylibmcmodule.h src/pylibmc-version.h
recursive-include pylibmc *.py
recursive-include tests *.py
-include docs/Makefile docs/make.bat docs/conf.py
+include docs/Makefile docs/make.bat docs/conf.py docs/*.svg
recursive-include docs *.rst
recursive-include docs/_themes *
diff --git a/PKG-INFO b/PKG-INFO
index 9f33970..c292a68 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: pylibmc
-Version: 1.5.1
+Version: 1.5.2
Summary: Quick and small memcached client for Python
Home-page: http://sendapatch.se/projects/pylibmc/
Author: Ludvig Ericson
@@ -79,3 +79,4 @@ Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.2
Classifier: Programming Language :: Python :: 3.3
Classifier: Programming Language :: Python :: 3.4
+Classifier: Programming Language :: Python :: 3.5
diff --git a/docs/failover.svg b/docs/failover.svg
new file mode 100644
index 0000000..dd497ce
--- /dev/null
+++ b/docs/failover.svg
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<!-- Generated by graphviz version 2.26.3 (20100126.1600)
+ -->
+<!-- Title: G Pages: 1 -->
+<svg width="541pt" height="680pt"
+ viewBox="0.00 0.00 541.00 680.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<g id="graph1" class="graph" transform="scale(1 1) rotate(0) translate(4 676)">
+<title>G</title>
+<!-- init -->
+<g id="node1" class="node"><title>init</title>
+<ellipse fill="lightgray" stroke="black" cx="453" cy="-654" rx="59.0322" ry="18"/>
+<text text-anchor="middle" x="453" y="-649.4" font-family="Times Roman,serif" font-size="14.00">new client</text>
+</g>
+<!-- initconnect -->
+<g id="node2" class="node"><title>initconnect</title>
+<ellipse fill="white" stroke="black" cx="453" cy="-566" rx="69.7653" ry="18"/>
+<text text-anchor="middle" x="453" y="-561.4" font-family="Times Roman,serif" font-size="14.00">first connect</text>
+</g>
+<!-- init->initconnect -->
+<g id="edge2" class="edge"><title>init->initconnect</title>
+<path fill="none" stroke="black" d="M453,-635.766C453,-623.849 453,-608.038 453,-594.482"/>
+<polygon fill="black" stroke="black" points="456.5,-594.21 453,-584.21 449.5,-594.21 456.5,-594.21"/>
+<text text-anchor="middle" x="488.5" y="-605.4" font-family="Times Roman,serif" font-size="14.00">on get/set</text>
+</g>
+<!-- connerr -->
+<g id="node3" class="node"><title>connerr</title>
+<ellipse fill="white" stroke="red" cx="360" cy="-492" rx="88.048" ry="18"/>
+<text text-anchor="middle" x="360" y="-487.4" font-family="Times Roman,serif" font-size="14.00">connection error</text>
+</g>
+<!-- initconnect->connerr -->
+<g id="edge4" class="edge"><title>initconnect->connerr</title>
+<path fill="none" stroke="black" d="M431.43,-548.837C419.166,-539.078 403.617,-526.706 390.159,-515.998"/>
+<polygon fill="black" stroke="black" points="392.103,-513.072 382.099,-509.584 387.745,-518.549 392.103,-513.072"/>
+</g>
+<!-- connected -->
+<g id="node9" class="node"><title>connected</title>
+<ellipse fill="white" stroke="black" cx="455" cy="-171" rx="59.8749" ry="18"/>
+<text text-anchor="middle" x="455" y="-166.4" font-family="Times Roman,serif" font-size="14.00">connected</text>
+</g>
+<!-- initconnect->connected -->
+<g id="edge8" class="edge"><title>initconnect->connected</title>
+<path fill="none" stroke="black" d="M469.039,-548.271C480.167,-534.104 493,-513.176 493,-492 493,-492 493,-492 493,-281 493,-252.317 488.711,-244.989 479,-218 476.582,-211.281 473.412,-204.297 470.172,-197.832"/>
+<polygon fill="black" stroke="black" points="473.194,-196.058 465.454,-188.823 466.993,-199.305 473.194,-196.058"/>
+</g>
+<!-- timeout -->
+<g id="node4" class="node"><title>timeout</title>
+<ellipse fill="white" stroke="red" cx="307" cy="-407" rx="99.201" ry="28.2843"/>
+<text text-anchor="middle" x="307" y="-410.4" font-family="Times Roman,serif" font-size="14.00">server has</text>
+<text text-anchor="middle" x="307" y="-394.4" font-family="Times Roman,serif" font-size="14.00">temporarily failed</text>
+</g>
+<!-- connerr->timeout -->
+<g id="edge6" class="edge"><title>connerr->timeout</title>
+<path fill="none" stroke="black" d="M348.76,-473.974C343.3,-465.217 336.529,-454.358 330.04,-443.95"/>
+<polygon fill="black" stroke="black" points="332.951,-442.004 324.69,-435.37 327.011,-445.708 332.951,-442.004"/>
+</g>
+<!-- server_dead -->
+<g id="node5" class="node"><title>server_dead</title>
+<ellipse fill="white" stroke="red" cx="178" cy="-281" rx="77.0746" ry="28.2843"/>
+<text text-anchor="middle" x="178" y="-284.4" font-family="Times Roman,serif" font-size="14.00">server is</text>
+<text text-anchor="middle" x="178" y="-268.4" font-family="Times Roman,serif" font-size="14.00">marked dead</text>
+</g>
+<!-- timeout->server_dead -->
+<g id="edge12" class="edge"><title>timeout->server_dead</title>
+<path fill="none" stroke="black" d="M224.479,-391.059C192.955,-383.15 162.314,-372.581 153,-360 143.872,-347.67 146.687,-331.904 153.079,-317.704"/>
+<polygon fill="black" stroke="black" points="156.271,-319.148 157.706,-308.651 150.038,-315.962 156.271,-319.148"/>
+<text text-anchor="middle" x="225.5" y="-347.4" font-family="Times Roman,serif" font-size="14.00">after remove_failed</text>
+<text text-anchor="middle" x="225.5" y="-331.4" font-family="Times Roman,serif" font-size="14.00">connection attempts</text>
+</g>
+<!-- new -->
+<g id="node8" class="node"><title>new</title>
+<ellipse fill="white" stroke="black" cx="349" cy="-281" rx="30.1869" ry="18"/>
+<text text-anchor="middle" x="349" y="-276.4" font-family="Times Roman,serif" font-size="14.00">new</text>
+</g>
+<!-- timeout->new -->
+<g id="edge16" class="edge"><title>timeout->new</title>
+<path fill="none" stroke="black" d="M302.681,-378.321C301.505,-362.919 301.929,-343.888 308,-328 311.52,-318.789 317.723,-310.184 324.256,-302.919"/>
+<polygon fill="black" stroke="black" points="326.909,-305.211 331.362,-295.597 321.886,-300.336 326.909,-305.211"/>
+<text text-anchor="middle" x="374.5" y="-347.4" font-family="Times Roman,serif" font-size="14.00">after retry_timeout</text>
+<text text-anchor="middle" x="374.5" y="-331.4" font-family="Times Roman,serif" font-size="14.00">(or dead_timeout)</text>
+</g>
+<!-- removed -->
+<g id="node6" class="node"><title>removed</title>
+<ellipse fill="white" stroke="red" cx="185" cy="-171" rx="89.8026" ry="28.2843"/>
+<text text-anchor="middle" x="185" y="-174.4" font-family="Times Roman,serif" font-size="14.00">server removed</text>
+<text text-anchor="middle" x="185" y="-158.4" font-family="Times Roman,serif" font-size="14.00">from rotation</text>
+</g>
+<!-- server_dead->removed -->
+<g id="edge14" class="edge"><title>server_dead->removed</title>
+<path fill="none" stroke="black" d="M179.821,-252.386C180.641,-239.501 181.622,-224.085 182.509,-210.152"/>
+<polygon fill="black" stroke="black" points="186.022,-210.055 183.164,-199.853 179.036,-209.61 186.022,-210.055"/>
+</g>
+<!-- added -->
+<g id="node7" class="node"><title>added</title>
+<ellipse fill="white" stroke="black" cx="104" cy="-29" rx="103.945" ry="28.2843"/>
+<text text-anchor="middle" x="104" y="-32.4" font-family="Times Roman,serif" font-size="14.00">server added back</text>
+<text text-anchor="middle" x="104" y="-16.4" font-family="Times Roman,serif" font-size="14.00">into rotation</text>
+</g>
+<!-- removed->added -->
+<g id="edge18" class="edge"><title>removed->added</title>
+<path fill="none" stroke="black" d="M168.997,-142.945C156.487,-121.014 138.982,-90.3265 125.29,-66.3226"/>
+<polygon fill="black" stroke="black" points="128.242,-64.4344 120.247,-57.4824 122.162,-67.9028 128.242,-64.4344"/>
+<text text-anchor="middle" x="226.5" y="-111.4" font-family="Times Roman,serif" font-size="14.00">after dead_timeout,</text>
+<text text-anchor="middle" x="226.5" y="-95.4" font-family="Times Roman,serif" font-size="14.00">make a single</text>
+<text text-anchor="middle" x="226.5" y="-79.4" font-family="Times Roman,serif" font-size="14.00">connection attempt</text>
+</g>
+<!-- added->timeout -->
+<g id="edge20" class="edge"><title>added->timeout</title>
+<path fill="none" stroke="black" d="M94.5567,-57.75C78.9475,-110.526 53.1425,-225.217 92,-310 112.627,-355.006 161.724,-379.137 207.799,-392.072"/>
+<polygon fill="black" stroke="black" points="207.011,-395.484 217.574,-394.666 208.806,-388.718 207.011,-395.484"/>
+</g>
+<!-- new->connected -->
+<g id="edge10" class="edge"><title>new->connected</title>
+<path fill="none" stroke="black" d="M351.392,-262.988C353.993,-249.358 359.311,-230.853 370,-218 379.899,-206.096 393.631,-196.686 407.173,-189.511"/>
+<polygon fill="black" stroke="black" points="409.067,-192.478 416.468,-184.898 405.955,-186.208 409.067,-192.478"/>
+<text text-anchor="middle" x="405.5" y="-221.4" font-family="Times Roman,serif" font-size="14.00">on get/set</text>
+</g>
+<!-- connected->timeout -->
+<g id="edge24" class="edge"><title>connected->timeout</title>
+<path fill="none" stroke="black" d="M459.578,-189.122C467.654,-225.641 480.117,-308.937 441,-360 433.982,-369.162 414.174,-377.908 391.87,-385.318"/>
+<polygon fill="black" stroke="black" points="390.65,-382.034 382.189,-388.41 392.78,-388.702 390.65,-382.034"/>
+</g>
+<!-- connected->connected -->
+<g id="edge22" class="edge"><title>connected->connected</title>
+<path fill="none" stroke="black" d="M504.887,-181.119C520.602,-180.965 533,-177.592 533,-171 533,-165.902 525.584,-162.729 514.952,-161.481"/>
+<polygon fill="black" stroke="black" points="515.078,-157.983 504.887,-160.881 514.661,-164.97 515.078,-157.983"/>
+</g>
+</g>
+</svg>
diff --git a/docs/install.rst b/docs/install.rst
index 887aa4a..cab21a2 100644
--- a/docs/install.rst
+++ b/docs/install.rst
@@ -5,7 +5,7 @@
Requirements
============
-* Python 2.5 or later (Python 3 not supported yet)
+* Python 2.5, Python 3.2 or later
* libmemcached 0.32 or later (last test with 1.0.18)
* zlib (required for compression support)
* libsasl2 (required for authentication support)
diff --git a/docs/reference.rst b/docs/reference.rst
index f223b3e..e2553ef 100644
--- a/docs/reference.rst
+++ b/docs/reference.rst
@@ -35,9 +35,10 @@
.. Reading
- .. method:: get(key) -> value
+ .. method:: get(key[, default]) -> value
- Get *key* if it exists, otherwise ``None``.
+ Get *key* if it exists, otherwise *default*. If *default* is not given,
+ it defaults to ``None``.
.. method:: get_multi(keys[, key_prefix=None]) -> values
@@ -160,29 +161,20 @@
.. Deleting
- .. method:: delete(key[, time=0]) -> deleted
+ .. method:: delete(key) -> deleted
Delete *key* if it exists.
- If *time* is non-zero, this is equivalent of setting an expiry time for a
- key, i.e., the key will cease to exist after that many seconds.
-
Returns ``True`` if the key was deleted, ``False`` otherwise (as is the case if
it wasn't set in the first place.)
- .. note:: Some versions of libmemcached are unable to set *time* for a
- delete. This is true of versions up until at least 0.38.
-
- .. method:: delete_multi(keys[, time=0, key_prefix=None]) -> deleted
+ .. method:: delete_multi(keys[, key_prefix=None]) -> deleted
Delete each of key in the sequence *keys*.
:param keys: Sequence of keys to delete
- :param time: Number of seconds until the keys are deleted
:param key_prefix: Prefix for the keys to delete
- If *time* is zero, the keys are deleted immediately.
-
Returns ``True`` if all keys were successfully deleted, ``False``
otherwise (as is the case if it wasn't set in the first place.)
diff --git a/setup.py b/setup.py
index 7de01aa..f6a5180 100644
--- a/setup.py
+++ b/setup.py
@@ -121,5 +121,6 @@ setup(
'Programming Language :: Python :: 3.2',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
+ 'Programming Language :: Python :: 3.5',
],
)
diff --git a/src/_pylibmcmodule.c b/src/_pylibmcmodule.c
index 1372144..1ce5a6a 100644
--- a/src/_pylibmcmodule.c
+++ b/src/_pylibmcmodule.c
@@ -304,8 +304,8 @@ error:
/* {{{ Compression helpers */
#ifdef USE_ZLIB
-static int _PylibMC_Deflate(char *value, size_t value_len,
- char **result, size_t *result_len,
+static int _PylibMC_Deflate(char *value, Py_ssize_t value_len,
+ char **result, Py_ssize_t *result_len,
int compress_level) {
/* FIXME Failures are entirely silent. */
int rc;
@@ -373,8 +373,8 @@ error:
return 0;
}
-static int _PylibMC_Inflate(char *value, size_t size,
- char** result, size_t* result_size,
+static int _PylibMC_Inflate(char *value, Py_ssize_t size,
+ char** result, Py_ssize_t* result_size,
char** failure_reason) {
/*
@@ -542,7 +542,7 @@ static void _PylibMC_cleanup_str_key_mapping(PyObject *key_str_map) {
/* }}} */
static PyObject *_PylibMC_parse_memcached_value(PylibMC_Client *self,
- char *value, size_t size, uint32_t flags) {
+ char *value, Py_ssize_t size, uint32_t flags) {
PyObject *retval = NULL;
#if USE_ZLIB
@@ -552,7 +552,7 @@ static PyObject *_PylibMC_parse_memcached_value(PylibMC_Client *self,
if (flags & PYLIBMC_FLAG_ZLIB) {
int rc;
char* inflated_buf = NULL;
- size_t inflated_size = 0;
+ Py_ssize_t inflated_size = 0;
char* failure_reason = NULL;
if(size >= ZLIB_GIL_RELEASE) {
@@ -618,7 +618,7 @@ static PyObject *_PylibMC_parse_memcached_value(PylibMC_Client *self,
}
/** Helper because PyLong_FromString requires a null-terminated string. */
-static PyObject *_PyLong_FromStringAndSize(char *value, size_t size, char **pend, int base) {
+static PyObject *_PyLong_FromStringAndSize(char *value, Py_ssize_t size, char **pend, int base) {
PyObject *retval;
char *tmp;
if ((tmp = malloc(size+1)) == NULL) {
@@ -637,7 +637,7 @@ static PyObject *_PyLong_FromStringAndSize(char *value, size_t size, char **pend
the value to be deserialized is a byte array `value_str` of length
`value_size`.
*/
-static PyObject *_PylibMC_deserialize_native(PylibMC_Client *self, PyObject *value, char *value_str, size_t value_size, uint32_t flags) {
+static PyObject *_PylibMC_deserialize_native(PylibMC_Client *self, PyObject *value, char *value_str, Py_ssize_t value_size, uint32_t flags) {
assert(value || value_str);
PyObject *retval = NULL;
@@ -707,47 +707,54 @@ static int _PylibMC_cache_miss_simulated(PyObject *r) {
return 0;
}
-static PyObject *PylibMC_Client_get(PylibMC_Client *self, PyObject *arg) {
+static PyObject *PylibMC_Client_get(PylibMC_Client *self, PyObject *args) {
char *mc_val;
size_t val_size;
uint32_t flags;
memcached_return error;
+ PyObject *key;
+ /* if a default argument was in fact passed, it's still a borrowed reference
+ at this point, so borrow a reference to Py_None as well for parity. */
+ PyObject *default_value = Py_None;
- if (!_key_normalized_obj(&arg)) {
+ if (!PyArg_UnpackTuple(args, "get", 1, 2, &key, &default_value)) {
+ return NULL;
+ }
+
+ if (!_key_normalized_obj(&key)) {
return NULL;
- } else if (!PySequence_Length(arg) ) {
- Py_RETURN_NONE;
+ } else if (!PySequence_Length(key) ) {
+ Py_INCREF(default_value);
+ return default_value;
}
Py_BEGIN_ALLOW_THREADS;
mc_val = memcached_get(self->mc,
- PyBytes_AS_STRING(arg), PyBytes_GET_SIZE(arg),
+ PyBytes_AS_STRING(key), PyBytes_GET_SIZE(key),
&val_size, &flags, &error);
Py_END_ALLOW_THREADS;
- Py_DECREF(arg);
+ Py_DECREF(key);
if (mc_val != NULL) {
PyObject *r = _PylibMC_parse_memcached_value(self, mc_val, val_size, flags);
free(mc_val);
if (_PylibMC_cache_miss_simulated(r)) {
- /* Since python-memcache returns None when the key doesn't exist,
- * so shall we. */
- Py_RETURN_NONE;
+ 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) {
- /* Since python-memcache returns None when the key doesn't exist,
- * so shall we. */
- Py_RETURN_NONE;
+ Py_INCREF(default_value);
+ return default_value;
}
return PylibMC_ErrFromMemcachedWithKey(self, "memcached_get", error,
- PyBytes_AS_STRING(arg),
- PyBytes_GET_SIZE(arg));
+ PyBytes_AS_STRING(key),
+ PyBytes_GET_SIZE(key));
}
static PyObject *PylibMC_Client_gets(PylibMC_Client *self, PyObject *arg) {
@@ -829,7 +836,7 @@ static PyObject *PylibMC_Client_hash(PylibMC_Client *self, PyObject *args, PyObj
return NULL;
}
- h = memcached_generate_hash(self->mc, key, (size_t)key_len);
+ h = memcached_generate_hash(self->mc, key, (Py_ssize_t)key_len);
return PyLong_FromLong((long)h);
}
@@ -922,11 +929,11 @@ static PyObject *_PylibMC_RunSetCommandMulti(PylibMC_Client *self,
unsigned int min_compress = 0;
int compress_level = -1;
PyObject *failed = NULL;
- size_t idx = 0;
+ Py_ssize_t idx = 0;
PyObject *curr_key, *curr_value;
PyObject *key_str_map = NULL;
Py_ssize_t i;
- size_t nkeys;
+ Py_ssize_t nkeys;
pylibmc_mset* serialized = NULL;
bool allsuccess;
@@ -955,7 +962,7 @@ static PyObject *_PylibMC_RunSetCommandMulti(PylibMC_Client *self,
}
#endif
- nkeys = (size_t)PyDict_Size(keys);
+ nkeys = (Py_ssize_t)PyDict_Size(keys);
key_str_map = _PylibMC_map_str_keys(keys, NULL, NULL);
if (key_str_map == NULL) {
@@ -1294,8 +1301,8 @@ static PyObject *PylibMC_Client_serialize(PylibMC_Client *self, PyObject *value_
/* {{{ Set commands (set, replace, add, prepend, append) */
static bool _PylibMC_RunSetCommand(PylibMC_Client* self,
_PylibMC_SetCommand f, char *fname,
- pylibmc_mset* msets, size_t nkeys,
- size_t min_compress,
+ pylibmc_mset* msets, Py_ssize_t nkeys,
+ Py_ssize_t min_compress,
int compress_level) {
memcached_st *mc = self->mc;
memcached_return rc = MEMCACHED_SUCCESS;
@@ -1309,12 +1316,12 @@ static bool _PylibMC_RunSetCommand(PylibMC_Client* self,
pylibmc_mset *mset = &msets[i];
char *value = mset->value;
- size_t value_len = (size_t)mset->value_len;
+ Py_ssize_t value_len = (Py_ssize_t)mset->value_len;
uint32_t flags = mset->flags;
#ifdef USE_ZLIB
char *compressed_value = NULL;
- size_t compressed_len = 0;
+ Py_ssize_t compressed_len = 0;
if (compress_level && min_compress && value_len >= min_compress) {
_PylibMC_Deflate(value, value_len,
@@ -1501,11 +1508,6 @@ static PyObject *_PylibMC_IncrSingle(PylibMC_Client *self,
return NULL;
}
- if ((unsigned int)delta != delta) {
- PyErr_Format(PyExc_OverflowError, "%d", delta);
- return NULL;
- }
-
incr.key = key;
incr.key_len = key_len;
incr.incr_func = incr_func;
@@ -1535,7 +1537,7 @@ static PyObject *_PylibMC_IncrMulti(PylibMC_Client *self,
PyObject *retval = NULL;
PyObject *iterator = NULL;
unsigned int delta = 1;
- size_t nkeys = 0, i = 0;
+ Py_ssize_t nkeys = 0, i = 0;
pylibmc_incr *incrs;
static char *kws[] = { "keys", "key_prefix", "delta", NULL };
@@ -1545,7 +1547,7 @@ static PyObject *_PylibMC_IncrMulti(PylibMC_Client *self,
&key_prefix_len, &delta))
return NULL;
- nkeys = (size_t)PySequence_Size(keys);
+ nkeys = (Py_ssize_t)PySequence_Size(keys);
if (nkeys == -1)
return NULL;
@@ -1638,10 +1640,10 @@ static PyObject *PylibMC_Client_incr_multi(PylibMC_Client *self, PyObject *args,
}
static bool _PylibMC_IncrDecr(PylibMC_Client *self,
- pylibmc_incr *incrs, size_t nkeys) {
+ pylibmc_incr *incrs, Py_ssize_t nkeys) {
memcached_return rc = MEMCACHED_SUCCESS;
_PylibMC_IncrCommand f = NULL;
- size_t i, notfound = 0, errors = 0;
+ Py_ssize_t i, notfound = 0, errors = 0;
Py_BEGIN_ALLOW_THREADS;
for (i = 0; i < nkeys; i++) {
@@ -1757,7 +1759,7 @@ static PyObject *PylibMC_Client_get_multi(
PyObject *temp_key_obj;
size_t *key_lens;
Py_ssize_t nkeys = 0, orig_nkeys = 0;
- size_t nresults = 0;
+ Py_ssize_t nresults = 0;
memcached_return rc;
pylibmc_mget_req req;
@@ -1773,8 +1775,8 @@ static PyObject *PylibMC_Client_get_multi(
/* Populate keys and key_lens. */
keys = PyMem_New(char *, orig_nkeys);
key_lens = PyMem_New(size_t, (size_t) orig_nkeys);
- key_objs = PyMem_New(PyObject *, (size_t) orig_nkeys);
- orig_key_objs = PyMem_New(PyObject *, (size_t) orig_nkeys);
+ key_objs = PyMem_New(PyObject *, (Py_ssize_t) orig_nkeys);
+ orig_key_objs = PyMem_New(PyObject *, (Py_ssize_t) orig_nkeys);
if (!keys || !key_lens || !key_objs || !orig_key_objs) {
PyErr_NoMemory();
goto memory_cleanup;
@@ -1795,7 +1797,7 @@ static PyObject *PylibMC_Client_get_multi(
PyObject *ckey = orig_key_objs[i];
char *key;
Py_ssize_t key_len;
- size_t final_key_len;
+ Py_ssize_t final_key_len;
PyObject *rkey;
if (PyErr_Occurred() || !_key_normalized_obj(&ckey)) {
@@ -1807,7 +1809,7 @@ static PyObject *PylibMC_Client_get_multi(
PyBytes_AsStringAndSize(ckey, &key, &key_len);
- final_key_len = (size_t)(key_len + prefix_len);
+ final_key_len = (Py_ssize_t)(key_len + prefix_len);
/* Skip empty keys */
if (!final_key_len) {
@@ -2067,10 +2069,8 @@ static PyObject *PylibMC_Client_delete_multi(PylibMC_Client *self,
const char *prefix_raw = NULL;
Py_ssize_t prefix_len;
PyObject *prefix = NULL;
- PyObject *time = NULL;
PyObject *delete;
PyObject *keys;
- PyObject *call_args;
PyObject *retval;
static char *kws[] = { "keys", "key_prefix", NULL };
@@ -2080,48 +2080,25 @@ static PyObject *PylibMC_Client_delete_multi(PylibMC_Client *self,
return NULL;
/**
- * Because of how DoMulti works, we have to prohibit the use of mappings
- * here. Otherwise, the values of the mapping will be the second argument
- * to the delete function; the time argument will then become a third
- * argument, which delete doesn't take.
- *
- * So a mapping to DoMulti would produce calls like:
- * DoMulti({"a": 1, "b": 2}, time=3)
- * delete("a", 1, 3)
- * delete("b", 2, 3)
- */
-#if PY_MAJOR_VERSION >= 3
- /*
- * This isn't optimal, but PyMapping_Check returns 1 for
- * tuples, lists and other sequences in Python 3. According to
- * http://bugs.python.org/issue5945 PyMapping_Check has never
- * been particularly reliable, so hopefully it's enough to
- * check for dict objects (and subclasses) specifically.
+ * Prohibit use of mappings, otherwise DoMulti interprets the values of
+ * such mappings as the 2nd argument to the delete function, e.g.
+ * DoMulti({"a": 1, "b": 2}) calls delete("a", 1) and delete("b", 2), which
+ * is nonsense.
*/
if (PyDict_Check(keys)) {
-#else
- if (PyMapping_Check(keys)) {
-#endif
PyErr_SetString(PyExc_TypeError,
"keys must be a sequence, not a mapping");
return NULL;
}
- if (prefix_raw != NULL) {
+ if (prefix_raw != NULL)
prefix = PyBytes_FromStringAndSize(prefix_raw, prefix_len);
- }
if ((delete = PyObject_GetAttrString((PyObject *)self, "delete")) == NULL)
return NULL;
- if (time == NULL) {
- retval = _PylibMC_DoMulti(keys, delete, prefix, NULL);
- } else {
- if ((call_args = PyTuple_Pack(1, time)) == NULL)
- goto error;
- retval = _PylibMC_DoMulti(keys, delete, prefix, call_args);
- Py_DECREF(call_args);
- }
+ retval = _PylibMC_DoMulti(keys, delete, prefix, NULL);
+
Py_DECREF(delete);
Py_XDECREF(prefix);
@@ -2135,12 +2112,9 @@ static PyObject *PylibMC_Client_delete_multi(PylibMC_Client *self,
Py_DECREF(retval);
retval = Py_False;
}
- Py_INCREF(retval);
+ Py_INCREF(retval);
return retval;
-error:
- Py_XDECREF(delete);
- return NULL;
}
static PyObject *PylibMC_Client_get_behaviors(PylibMC_Client *self) {
@@ -2438,10 +2412,18 @@ static void _set_error(memcached_st *mc, memcached_return error, char *lead) {
lead, strerror(errno));
} else if (error == MEMCACHED_SUCCESS) {
PyErr_Format(PyExc_RuntimeError, "error == MEMCACHED_SUCCESS");
+#if LIBMEMCACHED_VERSION_HEX >= 0x01000002
+ } else if (error == MEMCACHED_E2BIG) {
+ PyErr_SetNone(_exc_by_rc(error));
+#endif
} else {
PyObject *exc = _exc_by_rc(error);
#if LIBMEMCACHED_VERSION_HEX >= 0x00049000
- PyErr_Format(exc, "%s: %.200s", lead, memcached_last_error_message(mc));
+ if (memcached_last_error(mc) != MEMCACHED_SUCCESS) {
+ PyErr_Format(exc, "%s: %.200s", lead, memcached_last_error_message(mc));
+ } else {
+ PyErr_SetString(exc, lead);
+ }
#else
PyErr_Format(exc, "%s: %.200s", lead, memcached_strerror(mc, error));
#endif
@@ -2489,7 +2471,7 @@ static PyObject *_PylibMC_GetPickles(const char *attname) {
return pickle_attr;
}
-static PyObject *_PylibMC_Unpickle(const char *buff, size_t size) {
+static PyObject *_PylibMC_Unpickle(const char *buff, Py_ssize_t size) {
#if PY_MAJOR_VERSION >= 3
return PyObject_CallFunction(_PylibMC_pickle_loads, "y#", buff, size);
#else
@@ -2502,7 +2484,7 @@ static PyObject *_PylibMC_Unpickle_Bytes(PyObject *val) {
}
static PyObject *_PylibMC_Pickle(PyObject *val) {
- return PyObject_CallFunctionObjArgs(_PylibMC_pickle_dumps, val, NULL);
+ return PyObject_CallFunction(_PylibMC_pickle_dumps, "Oi", val, -1);
}
/* }}} */
@@ -2660,7 +2642,7 @@ static void _make_excs(PyObject *module) {
"pylibmc.Error", NULL, NULL);
PylibMCExc_CacheMiss = PyErr_NewException(
- "_pylibmc.CacheMiss", PylibMCExc_Error, NULL);
+ "pylibmc.CacheMiss", PylibMCExc_Error, NULL);
exc_objs = PyList_New(0);
PyList_Append(exc_objs,
@@ -2670,7 +2652,7 @@ static void _make_excs(PyObject *module) {
for (err = PylibMCExc_mc_errs; err->name != NULL; err++) {
char excnam[64];
- snprintf(excnam, 64, "_pylibmc.%s", err->name);
+ snprintf(excnam, 64, "pylibmc.%s", err->name);
err->exc = PyErr_NewException(excnam, PylibMCExc_Error, NULL);
PyObject_SetAttrString(err->exc, "retcode", PyLong_FromLong(err->rc));
PyModule_AddObject(module, err->name, (PyObject *)err->exc);
diff --git a/src/_pylibmcmodule.h b/src/_pylibmcmodule.h
index b3847ab..3aa3dcc 100644
--- a/src/_pylibmcmodule.h
+++ b/src/_pylibmcmodule.h
@@ -105,10 +105,10 @@ typedef struct {
typedef struct {
char **keys;
- size_t nkeys;
+ Py_ssize_t nkeys;
size_t *key_lens;
memcached_result_st **results;
- size_t *nresults;
+ Py_ssize_t *nresults;
char **err_func;
PyObject *transform;
} pylibmc_mget_req;
@@ -177,6 +177,7 @@ static PylibMC_McErr PylibMCExc_mc_errs[] = {
{ MEMCACHED_SERVER_MARKED_DEAD, "ServerDead", NULL },
#if LIBMEMCACHED_VERSION_HEX >= 0x01000002
{ MEMCACHED_SERVER_TEMPORARILY_DISABLED, "ServerDown", NULL },
+ { MEMCACHED_E2BIG, "TooBig", NULL },
#endif
{ MEMCACHED_UNKNOWN_STAT_KEY, "UnknownStatKey", NULL },
//{ MEMCACHED_E2BIG, "TooBigError", NULL },
@@ -314,14 +315,14 @@ static PyObject *PylibMC_ErrFromMemcachedWithKey(PylibMC_Client *, const char *,
memcached_return, const char *, Py_ssize_t);
static PyObject *PylibMC_ErrFromMemcached(PylibMC_Client *, const char *,
memcached_return);
-static PyObject *_PylibMC_Unpickle(const char *, size_t);
+static PyObject *_PylibMC_Unpickle(const char *, Py_ssize_t);
static PyObject *_PylibMC_Unpickle_Bytes(PyObject *);
static PyObject *_PylibMC_Pickle(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 *);
static int _PylibMC_serialize_native(PylibMC_Client *, PyObject *, PyObject **, uint32_t *);
-static PyObject *_PylibMC_deserialize_native(PylibMC_Client *, PyObject *, char *, size_t, uint32_t);
+static PyObject *_PylibMC_deserialize_native(PylibMC_Client *, PyObject *, char *, Py_ssize_t, uint32_t);
static int _PylibMC_SerializeValue(PylibMC_Client *self,
PyObject *key_obj,
PyObject *key_prefix,
@@ -335,16 +336,16 @@ static PyObject *_PylibMC_RunSetCommandMulti(PylibMC_Client *self,
_PylibMC_SetCommand f, char *fname, PyObject *args, PyObject *kwds);
static bool _PylibMC_RunSetCommand(PylibMC_Client *self,
_PylibMC_SetCommand f, char *fname,
- pylibmc_mset *msets, size_t nkeys,
- size_t min_compress,
+ pylibmc_mset *msets, Py_ssize_t nkeys,
+ Py_ssize_t min_compress,
int compress_level);
-static int _PylibMC_Deflate(char *value, size_t value_len,
- char **result, size_t *result_len,
+static int _PylibMC_Deflate(char *value, Py_ssize_t value_len,
+ char **result, Py_ssize_t *result_len,
int compress_level);
-static int _PylibMC_Inflate(char *value, size_t size,
- char** result, size_t* result_size,
+static int _PylibMC_Inflate(char *value, Py_ssize_t size,
+ char** result, Py_ssize_t* result_size,
char** failure_reason);
-static bool _PylibMC_IncrDecr(PylibMC_Client *, pylibmc_incr *, size_t);
+static bool _PylibMC_IncrDecr(PylibMC_Client *, pylibmc_incr *, Py_ssize_t);
/* }}} */
@@ -356,7 +357,7 @@ static PyMethodDef PylibMC_ClientType_methods[] = {
{"deserialize", (PyCFunction)PylibMC_Client_deserialize, METH_VARARGS,
"Deserialize a bytestring and flag field retrieved from memcached. "
"Raise pylibmc.CacheMiss to simulate a cache miss."},
- {"get", (PyCFunction)PylibMC_Client_get, METH_O,
+ {"get", (PyCFunction)PylibMC_Client_get, METH_VARARGS,
"Retrieve a key from a memcached."},
{"gets", (PyCFunction)PylibMC_Client_gets, METH_O,
"Retrieve a key and cas_id from a memcached."},
diff --git a/src/pylibmc-version.h b/src/pylibmc-version.h
index 932ac03..4a4a5aa 100644
--- a/src/pylibmc-version.h
+++ b/src/pylibmc-version.h
@@ -1 +1 @@
-#define PYLIBMC_VERSION "1.5.1"
+#define PYLIBMC_VERSION "1.5.2"
diff --git a/src/pylibmc/__init__.py b/src/pylibmc/__init__.py
index 286f551..b4f51ba 100644
--- a/src/pylibmc/__init__.py
+++ b/src/pylibmc/__init__.py
@@ -69,17 +69,12 @@ See http://sendapatch.se/projects/pylibmc/
"""
import _pylibmc
+from _pylibmc import *
+from _pylibmc import __version__
from .consts import hashers, distributions
from .client import Client
from .pools import ClientPool, ThreadMappedPool
-libmemcached_version = _pylibmc.libmemcached_version
-support_compression = _pylibmc.support_compression
-support_sasl = _pylibmc.support_sasl
-Error = _pylibmc.Error
-
-__version__ = _pylibmc.__version__
-
def build_info():
return ("pylibmc %s for libmemcached %s (compression=%s, sasl=%s)"
% (__version__,
@@ -88,4 +83,4 @@ def build_info():
support_sasl))
__all__ = ["hashers", "distributions", "Client",
- "ClientPool", "ThreadMappedPool"]
+ "ClientPool", "ThreadMappedPool"] + dir(_pylibmc)
diff --git a/src/pylibmc/client.py b/src/pylibmc/client.py
index c93016a..e2da11e 100644
--- a/src/pylibmc/client.py
+++ b/src/pylibmc/client.py
@@ -12,6 +12,8 @@ server_type_map = {"tcp": _pylibmc.server_type_tcp,
"udp": _pylibmc.server_type_udp,
"unix": _pylibmc.server_type_unix}
+_MISS_SENTINEL = object()
+
def _split_spec_type(spec):
if spec.startswith("/"):
return ("unix", spec)
@@ -153,8 +155,8 @@ class Client(_pylibmc.client):
# {{{ Mapping interface
def __getitem__(self, key):
- value = self.get(key)
- if value is None:
+ value = self.get(key, _MISS_SENTINEL)
+ if value is _MISS_SENTINEL:
raise KeyError(key)
else:
return value
@@ -168,7 +170,7 @@ class Client(_pylibmc.client):
raise KeyError(key)
def __contains__(self, key):
- return self.get(key) is not None
+ return self.get(key, _MISS_SENTINEL) is not _MISS_SENTINEL
# }}}
# {{{ Behaviors
diff --git a/tests/test_client.py b/tests/test_client.py
index 3a61fea..6636f40 100644
--- a/tests/test_client.py
+++ b/tests/test_client.py
@@ -94,3 +94,20 @@ class ClientTests(PylibmcTestCase):
mc = make_test_client(binary=True)
ok_(mc.set(k, 0))
ok_(mc.get(k_enc) == 0)
+
+ def test_get_with_default(self):
+ mc = make_test_client(binary=True)
+ key = 'get-api-test'
+ mc.delete(key)
+ eq_(mc.get(key), None)
+ default = object()
+ assert mc.get(key, default) is default
+
+ def test_none_values(self):
+ mc = make_test_client(binary=True)
+ mc.set('none-test', None)
+ self.assertEqual(mc.get('none-test'), None)
+ self.assertEqual(mc.get('none-test', 'default'), None)
+ # formerly, this would raise a KeyError, which was incorrect
+ self.assertEqual(mc['none-test'], None)
+ assert 'none-test' in mc
diff --git a/tests/test_refcounts.py b/tests/test_refcounts.py
index 92a5ac6..699bbd7 100644
--- a/tests/test_refcounts.py
+++ b/tests/test_refcounts.py
@@ -47,6 +47,25 @@ class RefcountTests(PylibmcTestCase):
def test_get_singleton(self):
self._test_get(b"refcountest3", False)
+ def test_get_with_default(self):
+ bc = make_test_client(binary=True)
+ key = b'refcountest4'
+ val = 'some_value'
+ default = object()
+ refcountables = [key, val, default]
+ initial_refcounts = get_refcounts(refcountables)
+ bc.set(key, val)
+ eq_(get_refcounts(refcountables), initial_refcounts)
+ assert bc.get(key) == val
+ eq_(get_refcounts(refcountables), initial_refcounts)
+ assert bc.get(key, default) == val
+ eq_(get_refcounts(refcountables), initial_refcounts)
+ bc.delete(key)
+ assert bc.get(key) is None
+ eq_(get_refcounts(refcountables), initial_refcounts)
+ assert bc.get(key, default) is default
+ eq_(get_refcounts(refcountables), initial_refcounts)
+
def test_get_multi(self):
bc = make_test_client(binary=True)
keys = ["first", "second", "", b""]
diff --git a/tests/test_serialization.py b/tests/test_serialization.py
index 4a1f8c7..61f2e57 100644
--- a/tests/test_serialization.py
+++ b/tests/test_serialization.py
@@ -53,7 +53,8 @@ class SerializationMethodTests(PylibmcTestCase):
(b'asdf', (b'asdf', 0)),
(b'\xb5\xb1\xbf\xed\xa9\xc2{8', (b'\xb5\xb1\xbf\xed\xa9\xc2{8', 0)),
# objects
- (datetime.date(2015, 12, 28), (pickle.dumps(datetime.date(2015, 12, 28)), 1)),
+ (datetime.date(2015, 12, 28), (pickle.dumps(datetime.date(2015, 12, 28),
+ protocol=-1), 1)),
]
c = make_test_client(binary=True)
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/pylibmc.git
More information about the Python-modules-commits
mailing list