Add specialized exception classes.

Useful when you need to catch certain errors like when a key isn't found
during an increment/decrement operation.
This commit is contained in:
lericson 2009-11-05 19:09:09 +01:00
parent 529adbe6bb
commit 1c83ad0de2
3 changed files with 79 additions and 3 deletions

View File

@ -890,8 +890,18 @@ static PyObject *PylibMC_ErrFromMemcached(PylibMC_Client *self, const char *what
PyErr_Format(PyExc_RuntimeError, "error == 0? %s:%d", PyErr_Format(PyExc_RuntimeError, "error == 0? %s:%d",
__FILE__, __LINE__); __FILE__, __LINE__);
} else { } else {
PyErr_Format(PylibMCExc_MemcachedError, "error %d from %s: %s", PylibMC_McErr *err;
error, what, memcached_strerror(self->mc, error)); 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, "error %d from %s: %s", error, what,
memcached_strerror(self->mc, error));
} }
return NULL; return NULL;
} }
@ -976,6 +986,7 @@ static PyMethodDef PylibMC_functions[] = {
PyMODINIT_FUNC init_pylibmc(void) { PyMODINIT_FUNC init_pylibmc(void) {
PyObject *module; PyObject *module;
PylibMC_Behavior *b; PylibMC_Behavior *b;
PylibMC_McErr *err;
char name[128]; char name[128];
if (PyType_Ready(&PylibMC_ClientType) < 0) { if (PyType_Ready(&PylibMC_ClientType) < 0) {
@ -1006,12 +1017,20 @@ Oh, and: plankton.\n");
return; return;
} }
PyModule_AddStringConstant(module, "__version__", PYLIBMC_VERSION);
PylibMCExc_MemcachedError = PyErr_NewException( PylibMCExc_MemcachedError = PyErr_NewException(
"_pylibmc.MemcachedError", NULL, NULL); "_pylibmc.MemcachedError", NULL, NULL);
PyModule_AddObject(module, "MemcachedError", PyModule_AddObject(module, "MemcachedError",
(PyObject *)PylibMCExc_MemcachedError); (PyObject *)PylibMCExc_MemcachedError);
PyModule_AddStringConstant(module, "__version__", PYLIBMC_VERSION); for (err = PylibMCExc_mc_errs; err->name != NULL; err++) {
char excnam[64];
strncpy(excnam, "_pylibmc.", 64);
strncat(excnam, err->name, 64);
err->exc = PyErr_NewException(excnam, PylibMCExc_MemcachedError, NULL);
PyModule_AddObject(module, err->name, (PyObject *)err->exc);
}
Py_INCREF(&PylibMC_ClientType); Py_INCREF(&PylibMC_ClientType);
PyModule_AddObject(module, "client", (PyObject *)&PylibMC_ClientType); PyModule_AddObject(module, "client", (PyObject *)&PylibMC_ClientType);

View File

@ -68,6 +68,53 @@ typedef memcached_return (*_PylibMC_SetCommand)(memcached_st *, const char *,
/* {{{ Exceptions */ /* {{{ Exceptions */
static PyObject *PylibMCExc_MemcachedError; static PyObject *PylibMCExc_MemcachedError;
/* Mapping of memcached_return value -> Python exception object. */
typedef struct {
memcached_return rc;
char *name;
PyObject *exc;
} PylibMC_McErr;
static PylibMC_McErr PylibMCExc_mc_errs[] = {
{ MEMCACHED_FAILURE, "Failure", NULL },
{ MEMCACHED_HOST_LOOKUP_FAILURE, "HostLookupError", NULL },
{ MEMCACHED_CONNECTION_FAILURE, "ConnectionError", NULL },
{ MEMCACHED_CONNECTION_BIND_FAILURE, "ConnectionBindError", NULL },
{ MEMCACHED_WRITE_FAILURE, "WriteError", NULL },
{ MEMCACHED_READ_FAILURE, "ReadError", NULL },
{ MEMCACHED_UNKNOWN_READ_FAILURE, "UnknownReadFailure", NULL },
{ MEMCACHED_PROTOCOL_ERROR, "ProtocolError", NULL },
{ MEMCACHED_CLIENT_ERROR, "ClientError", NULL },
{ MEMCACHED_SERVER_ERROR, "ServerError", NULL },
{ MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE, "SocketCreateError", NULL },
{ MEMCACHED_DATA_EXISTS, "DataExists", NULL },
{ MEMCACHED_DATA_DOES_NOT_EXIST, "DataDoesNotExist", NULL },
//{ MEMCACHED_NOTSTORED, "NotStored", NULL },
//{ MEMCACHED_STORED, "Stored", NULL },
{ MEMCACHED_NOTFOUND, "NotFound", NULL },
{ MEMCACHED_MEMORY_ALLOCATION_FAILURE, "AllocationError", NULL },
//{ MEMCACHED_PARTIAL_READ, "PartialRead", NULL },
{ MEMCACHED_SOME_ERRORS, "SomeErrors", NULL },
{ MEMCACHED_NO_SERVERS, "NoServers", NULL },
//{ MEMCACHED_END, "", NULL },
//{ MEMCACHED_DELETED, "", NULL },
//{ MEMCACHED_VALUE, "", NULL },
//{ MEMCACHED_STAT, "", NULL },
//{ MEMCACHED_ITEM, "", NULL },
//{ MEMCACHED_ERRNO, "", NULL },
{ MEMCACHED_FAIL_UNIX_SOCKET, "UnixSocketError", NULL },
{ MEMCACHED_NOT_SUPPORTED, "NotSupportedError", NULL },
{ MEMCACHED_FETCH_NOTFINISHED, "FetchNotFinished", NULL },
//{ MEMCACHED_TIMEOUT, "TimeoutError", NULL },
//{ MEMCACHED_BUFFERED, "Buffer, NULL },
{ MEMCACHED_BAD_KEY_PROVIDED, "BadKeyProvided", NULL },
{ MEMCACHED_INVALID_HOST_PROTOCOL, "InvalidHostProtocolError", NULL },
//{ MEMCACHED_SERVER_MARKED_DEAD,
{ MEMCACHED_UNKNOWN_STAT_KEY, "UnknownStatKey", NULL },
{ MEMCACHED_E2BIG, "TooBigError", NULL },
{ 0, NULL, NULL }
};
/* }}} */ /* }}} */
/* {{{ Behavior statics */ /* {{{ Behavior statics */

View File

@ -147,6 +147,16 @@ True
True True
>>> del c2 >>> del c2
Per-error exceptions
>>> c.incr("test")
Traceback (most recent call last):
...
NotFound: error 16 from memcached_increment: NOT FOUND
>>> c.incr(chr(0))
Traceback (most recent call last):
...
ProtocolError: error 8 from memcached_increment: PROTOCOL ERROR
Behaviors. Behaviors.
>>> c.set_behaviors({"tcp_nodelay": True, "hash": 6}) >>> c.set_behaviors({"tcp_nodelay": True, "hash": 6})
>>> list(sorted((k, v) for (k, v) in c.get_behaviors().items() >>> list(sorted((k, v) for (k, v) in c.get_behaviors().items()