diff options
-rw-r--r-- | .gitmodules | 6 | ||||
-rw-r--r-- | MANIFEST.in | 2 | ||||
-rw-r--r-- | Makefile | 13 | ||||
-rw-r--r-- | Modules/_librabbitmq/connection.c | 122 | ||||
-rw-r--r-- | Modules/_librabbitmq/connection.h | 56 | ||||
-rw-r--r-- | benchmark.py | 58 | ||||
-rw-r--r-- | funtests/config.py | 2 | ||||
-rw-r--r-- | funtests/setup.py | 1 | ||||
-rw-r--r-- | librabbitmq/__init__.py | 7 | ||||
-rw-r--r-- | librabbitmq/tests/test_functional.py | 9 | ||||
m--------- | rabbitmq-c | 0 | ||||
m--------- | rabbitmq-codegen | 0 | ||||
-rw-r--r-- | requirements/README.rst | 13 | ||||
-rw-r--r-- | requirements/default.txt | 1 | ||||
-rw-r--r-- | requirements/test.txt | 2 | ||||
-rw-r--r-- | setup.py | 44 |
16 files changed, 189 insertions, 147 deletions
diff --git a/.gitmodules b/.gitmodules index ebc8053..53784ba 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,4 @@ -[submodule "rabbitmq-codegen"] - path = rabbitmq-codegen - url = https://github.com/rabbitmq/rabbitmq-codegen.git [submodule "rabbitmq-c"] path = rabbitmq-c - url = https://github.com/ask/rabbitmq-c.git + url = https://github.com/alanxz/rabbitmq-c.git + branch = v0.8.0 diff --git a/MANIFEST.in b/MANIFEST.in index 4287ace..971ccec 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -9,8 +9,6 @@ include setup.cfg recursive-include librabbitmq * recursive-include Modules * recursive-include tests * -recursive-include clib * -recursive-include rabbitmq-codegen * prune *.pyc prune *.o prune *.la @@ -1,8 +1,6 @@ # Building RABBIT_DIR=rabbitmq-c -CODEGEN_DIR=rabbitmq-codegen -RABBIT_TARGET=clib -RABBIT_DIST=rabbitmq-c-0.5.3 +RABBIT_DIST=librabbitmq # Distribuition tools PYTHON=python @@ -10,13 +8,11 @@ PYTHON=python all: build add-submodules: - -git submodule add https://github.com/ask/rabbitmq-c.git - -git submodule add https://github.com/rabbitmq/rabbitmq-codegen + -git submodule add -b v0.8.0 https://github.com/alanxz/rabbitmq-c.git submodules: git submodule init git submodule update - (cd $(RABBIT_DIR); rm -rf codegen; ln -sf ../$(CODEGEN_DIR) ./codegen) rabbitmq-c: submodules (cd $(RABBIT_DIR); test -f configure || autoreconf -i) @@ -25,11 +21,9 @@ rabbitmq-c: submodules rabbitmq-clean: -(cd $(RABBIT_DIR) && make clean) - -(cd $(RABBIT_TARGET) && make clean) rabbitmq-distclean: -(cd $(RABBIT_DIR) && make distclean) - -(cd $(RABBIT_TARGET) && make distclean) clean-build: -rm -rf build @@ -57,8 +51,7 @@ distclean: pyclean rabbitmq-distclean removepyc $(RABBIT_TARGET): (test -f config.h || cd $(RABBIT_DIR); ./configure --disable-tools --disable-docs) - (cd $(RABBIT_DIR); make distdir) - mv "$(RABBIT_DIR)/$(RABBIT_DIST)" "$(RABBIT_TARGET)" + (cd $(RABBIT_DIR); make) dist: rabbitmq-c $(RABBIT_TARGET) diff --git a/Modules/_librabbitmq/connection.c b/Modules/_librabbitmq/connection.c index 10b0ddf..54f2427 100644 --- a/Modules/_librabbitmq/connection.c +++ b/Modules/_librabbitmq/connection.c @@ -15,6 +15,9 @@ #define PYRABBITMQ_CONNECTION_ERROR 0x10 #define PYRABBITMQ_CHANNEL_ERROR 0x20 +#define PYRABBITMQ_MODULE_NAME "_librabbitmq" +#define PYRABBITMQ_MODULE_DESC "Hand-made wrapper for librabbitmq." + /* ------: Private Prototypes :------------------------------------------- */ PyMODINIT_FUNC init_librabbitmq(void); @@ -248,12 +251,12 @@ PyDict_ToAMQTable(amqp_connection_state_t conn, PyObject *src, amqp_pool_t *pool { PyObject *dkey = NULL; PyObject *dvalue = NULL; - PY_SIZE_TYPE size = 0; - PY_SIZE_TYPE pos = 0; + Py_ssize_t size = 0; + Py_ssize_t pos = 0; uint64_t clong_value = 0; double cdouble_value = 0.0; int is_unicode = 0; - amqp_table_t dst = AMQP_EMPTY_TABLE; + amqp_table_t dst = amqp_empty_table; size = PyDict_Size(src); @@ -261,7 +264,7 @@ PyDict_ToAMQTable(amqp_connection_state_t conn, PyObject *src, amqp_pool_t *pool dst.num_entries = 0; dst.entries = amqp_pool_alloc(pool, size * sizeof(amqp_table_entry_t)); while (PyDict_Next(src, &pos, &dkey, &dvalue)) { - + dkey = Maybe_Unicode(dkey); if (dvalue == Py_None) { /* None */ AMQTable_SetNilValue(&dst, PyString_AS_AMQBYTES(dkey)); @@ -315,7 +318,7 @@ PyDict_ToAMQTable(amqp_connection_state_t conn, PyObject *src, amqp_pool_t *pool else { /* String | Unicode */ is_unicode = PyUnicode_Check(dvalue); - if (is_unicode || PyString_Check(dvalue)) { + if (is_unicode || PyBytes_Check(dvalue)) { if (is_unicode) { if ((dvalue = PyUnicode_AsASCIIString(dvalue)) == NULL) goto error; @@ -329,7 +332,7 @@ PyDict_ToAMQTable(amqp_connection_state_t conn, PyObject *src, amqp_pool_t *pool /* unsupported type */ PyErr_Format(PyExc_ValueError, "Table member %s is of an unsupported type", - PyString_AS_STRING(dkey)); + PyBytes_AS_STRING(dkey)); goto error; } } @@ -337,18 +340,18 @@ PyDict_ToAMQTable(amqp_connection_state_t conn, PyObject *src, amqp_pool_t *pool return dst; error: assert(PyErr_Occurred()); - return AMQP_EMPTY_TABLE; + return amqp_empty_table; } static amqp_array_t PyIter_ToAMQArray(amqp_connection_state_t conn, PyObject *src, amqp_pool_t *pool) { - PY_SIZE_TYPE pos = 0; + Py_ssize_t pos = 0; uint64_t clong_value = 0; int is_unicode = 0; - amqp_array_t dst = AMQP_EMPTY_ARRAY; + amqp_array_t dst = amqp_empty_array; - PY_SIZE_TYPE size = PySequence_Size(src); + Py_ssize_t size = PySequence_Size(src); if (size == -1) return dst; PyObject *iterator = PyObject_GetIter(src); @@ -382,7 +385,7 @@ PyIter_ToAMQArray(amqp_connection_state_t conn, PyObject *src, amqp_pool_t *pool else { /* String | Unicode */ is_unicode = PyUnicode_Check(item); - if (is_unicode || PyString_Check(item)) { + if (is_unicode || PyBytes_Check(item)) { if (is_unicode) { if ((item = PyUnicode_AsASCIIString(item)) == NULL) goto item_error; @@ -393,8 +396,8 @@ PyIter_ToAMQArray(amqp_connection_state_t conn, PyObject *src, amqp_pool_t *pool else { /* unsupported type */ PyErr_Format(PyExc_ValueError, - "Array member at index %lu, %s, is of an unsupported type", - pos, PyObject_REPR(item)); + "Array member at index %lu, %R, is of an unsupported type", + pos, item); goto item_error; } } @@ -608,7 +611,7 @@ AMQArray_toPyList(amqp_array_t *array) { register PyObject *value = NULL; PyObject *list = NULL; - list = PyList_New((PY_SIZE_TYPE) array->num_entries); + list = PyList_New((Py_ssize_t) array->num_entries); if (array) { int i; @@ -681,7 +684,7 @@ PyDict_to_basic_properties(PyObject *p, amqp_pool_t *pool) { PyObject *value = NULL; - props->headers = AMQP_EMPTY_TABLE; + props->headers = amqp_empty_table; props->_flags = AMQP_BASIC_HEADERS_FLAG; if ((value = PyDict_GetItemString(p, "content_type")) != NULL) { @@ -951,7 +954,7 @@ PyRabbitMQ_ConnectionType_dealloc(PyRabbitMQ_Connection *self) Py_XDECREF(self->callbacks); Py_XDECREF(self->client_properties); Py_XDECREF(self->server_properties); - self->ob_type->tp_free(self); + Py_TYPE(self)->tp_free(self); } @@ -1236,7 +1239,7 @@ PyRabbitMQ_ApplyCallback(PyRabbitMQ_Connection *self, goto error; /* message = self.Message(channel, properties, delivery_info, body) */ - Message = PyString_FromString("Message"); + Message = BUILD_METHOD_NAME("Message"); message = PyObject_CallMethodObjArgs((PyObject *)self, Message, channelobj, propdict, delivery_info, view, NULL); if (!message) @@ -1305,8 +1308,8 @@ PyRabbitMQ_recv(PyRabbitMQ_Connection *self, PyObject *p, amqp_channel_t cur_channel = 0; amqp_basic_deliver_t *deliver; amqp_basic_properties_t *props; - PY_SIZE_TYPE body_target; - PY_SIZE_TYPE body_received; + Py_ssize_t body_target; + Py_ssize_t body_received; PyObject *channel = NULL; PyObject *consumer_tag = NULL; PyObject *delivery_info = NULL; @@ -1393,23 +1396,21 @@ PyRabbitMQ_recv(PyRabbitMQ_Connection *self, PyObject *p, body_received += frame.payload.body_fragment.len; if (!i) { if (body_received < body_target) { - payload = PyString_FromStringAndSize(NULL, - (PY_SIZE_TYPE)body_target); + payload = PyBytes_FromStringAndSize(NULL, + (Py_ssize_t)body_target); if (!payload) goto finally; - buf = PyString_AsString(payload); + buf = PyBytes_AsString(payload); if (!buf) goto finally; - view = PyBuffer_FromObject(payload, 0, - (PY_SIZE_TYPE)body_target); + view = PyMemoryView_FromObject(payload); } else { if (p) { payload = PySTRING_FROM_AMQBYTES( frame.payload.body_fragment); } else { - view = PyBuffer_FromMemory(bufp, - (PY_SIZE_TYPE)frame.payload.body_fragment.len); + view = buffer_toMemoryView(bufp, (Py_ssize_t)frame.payload.body_fragment.len); } break; } @@ -1424,7 +1425,7 @@ PyRabbitMQ_recv(PyRabbitMQ_Connection *self, PyObject *p, if (body_target) goto error; /* did not expect content, return empty string */ - payload = PyString_FromStringAndSize(NULL, 0); + payload = PyBytes_FromStringAndSize(NULL, 0); } PyDict_SetItemString(p, "properties", propdict); @@ -1468,7 +1469,7 @@ PyRabbitMQ_Connection_queue_bind(PyRabbitMQ_Connection *self, PyObject *routing_key = NULL; PyObject *arguments = NULL; - amqp_table_t bargs = AMQP_EMPTY_TABLE; + amqp_table_t bargs = amqp_empty_table; amqp_pool_t *channel_pool = NULL; amqp_rpc_reply_t reply; @@ -1523,7 +1524,7 @@ PyRabbitMQ_Connection_queue_unbind(PyRabbitMQ_Connection *self, PyObject *routing_key = NULL; PyObject *arguments = NULL; - amqp_table_t uargs = AMQP_EMPTY_TABLE; + amqp_table_t uargs = amqp_empty_table; amqp_pool_t *channel_pool = NULL; amqp_rpc_reply_t reply; @@ -1625,7 +1626,7 @@ PyRabbitMQ_Connection_queue_declare(PyRabbitMQ_Connection *self, amqp_queue_declare_ok_t *ok; amqp_rpc_reply_t reply; amqp_pool_t *channel_pool = NULL; - amqp_table_t qargs = AMQP_EMPTY_TABLE; + amqp_table_t qargs = amqp_empty_table; PyObject *ret = NULL; if (PyRabbitMQ_Not_Connected(self)) @@ -1661,8 +1662,7 @@ PyRabbitMQ_Connection_queue_declare(PyRabbitMQ_Connection *self, goto bail; if ((ret = PyTuple_New(3)) == NULL) goto bail; - PyTuple_SET_ITEM(ret, 0, PyString_FromStringAndSize(ok->queue.bytes, - (PY_SIZE_TYPE)ok->queue.len)); + PyTuple_SET_ITEM(ret, 0, PySTRING_FROM_AMQBYTES(ok->queue)); PyTuple_SET_ITEM(ret, 1, PyInt_FromLong((long)ok->message_count)); PyTuple_SET_ITEM(ret, 2, PyInt_FromLong((long)ok->consumer_count)); return ret; @@ -1725,7 +1725,7 @@ PyRabbitMQ_Connection_exchange_declare(PyRabbitMQ_Connection *self, * as it has been decided that it's not that useful after all. */ unsigned int auto_delete = 0; - amqp_table_t eargs = AMQP_EMPTY_TABLE; + amqp_table_t eargs = amqp_empty_table; amqp_pool_t *channel_pool = NULL; amqp_rpc_reply_t reply; @@ -1816,7 +1816,7 @@ PyRabbitMQ_Connection_basic_publish(PyRabbitMQ_Connection *self, unsigned int immediate = 0; char *body_buf = NULL; - PY_SIZE_TYPE body_size = 0; + Py_ssize_t body_size = 0; int ret = 0; amqp_basic_properties_t props; @@ -1827,7 +1827,7 @@ PyRabbitMQ_Connection_basic_publish(PyRabbitMQ_Connection *self, if (PyRabbitMQ_Not_Connected(self)) goto bail; - if (!PyArg_ParseTuple(args, "It#OOO|II", + if (!PyArg_ParseTuple(args, "Is#OOO|II", &channel, &body_buf, &body_size, &exchange, &routing_key, &propdict, &mandatory, &immediate)) goto bail; @@ -1874,7 +1874,7 @@ static PyObject* PyRabbitMQ_Connection_basic_ack(PyRabbitMQ_Connection *self, PyObject *args) { - PY_SIZE_TYPE delivery_tag = 0; + Py_ssize_t delivery_tag = 0; unsigned int channel = 0; unsigned int multiple = 0; int ret = 0; @@ -1907,7 +1907,7 @@ bail: static PyObject *PyRabbitMQ_Connection_basic_reject(PyRabbitMQ_Connection *self, PyObject *args) { - PY_SIZE_TYPE delivery_tag = 0; + Py_ssize_t delivery_tag = 0; unsigned int channel = 0; unsigned int multiple = 0; @@ -1991,7 +1991,7 @@ PyRabbitMQ_Connection_basic_consume(PyRabbitMQ_Connection *self, amqp_basic_consume_ok_t *ok; amqp_rpc_reply_t reply; amqp_pool_t *channel_pool = NULL; - amqp_table_t cargs = AMQP_EMPTY_TABLE; + amqp_table_t cargs = amqp_empty_table; if (PyRabbitMQ_Not_Connected(self)) goto bail; @@ -2038,7 +2038,7 @@ PyRabbitMQ_Connection_basic_qos(PyRabbitMQ_Connection *self, PyObject *args) { unsigned int channel = 0; - PY_SIZE_TYPE prefetch_size = 0; + Py_ssize_t prefetch_size = 0; unsigned int prefetch_count = 0; unsigned int _global = 0; @@ -2252,24 +2252,56 @@ static PyMethodDef PyRabbitMQ_functions[] = { {NULL, NULL, 0, NULL} }; -PyMODINIT_FUNC init_librabbitmq(void) +#if PY_MAJOR_VERSION >= 3 + static struct PyModuleDef PyRabbitMQ_moduledef = { + PyModuleDef_HEAD_INIT, + PYRABBITMQ_MODULE_NAME, /* m_name */ + PYRABBITMQ_MODULE_DESC, /* m_doc */ + -1, /* m_size */ + PyRabbitMQ_functions, /* m_methods */ + NULL, /* m_reload */ + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL, /* m_free */ + }; +#endif + +PYRABBITMQ_MOD_INIT(_librabbitmq) { PyObject *module, *socket_module; if (PyType_Ready(&PyRabbitMQ_ConnectionType) < 0) { + #if PY_MAJOR_VERSION >= 3 + return NULL; + #else return; + #endif } - module = Py_InitModule3("_librabbitmq", PyRabbitMQ_functions, - "Hand-made wrapper for librabbitmq."); +#if PY_MAJOR_VERSION >= 3 + module = PyModule_Create(&PyRabbitMQ_moduledef); +#else + module = Py_InitModule3(PYRABBITMQ_MODULE_NAME, PyRabbitMQ_functions, + PYRABBITMQ_MODULE_DESC); +#endif + if (module == NULL) { + #if PY_MAJOR_VERSION >= 3 + return NULL; + #else return; + #endif } /* Get socket.error */ socket_module = PyImport_ImportModule("socket"); - if (!socket_module) + if (!socket_module) { + #if PY_MAJOR_VERSION >= 3 + return NULL; + #else return; + #endif + } PyRabbitMQ_socket_timeout = PyObject_GetAttrString(socket_module, "timeout"); Py_XDECREF(socket_module); @@ -2291,5 +2323,9 @@ PyMODINIT_FUNC init_librabbitmq(void) "_librabbitmq.ChannelError", NULL, NULL); PyModule_AddObject(module, "ChannelError", (PyObject *)PyRabbitMQExc_ChannelError); +#if PY_MAJOR_VERSION >= 3 + return module; +#else return; +#endif } diff --git a/Modules/_librabbitmq/connection.h b/Modules/_librabbitmq/connection.h index 98de26c..273ae75 100644 --- a/Modules/_librabbitmq/connection.h +++ b/Modules/_librabbitmq/connection.h @@ -8,25 +8,29 @@ #include <amqp.h> #include <amqp_framing.h> -#if PY_VERSION_HEX < 0x02060000 && !defined(Py_SIZE) -# define Py_SIZE(ob) (((PyVarObject*)(ob))->ob_size) +#if PY_MAJOR_VERSION == 2 +# define TP_FLAGS (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_WEAKREFS) +#else +# define TP_FLAGS (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE) #endif -#if PY_VERSION_HEX >= 0x02060000 /* 2.6 and up */ -# define PY_SIZE_TYPE Py_ssize_t -# define PyLong_FROM_SSIZE_T PyLong_FromSsize_t -# define PyLong_AS_SSIZE_T PyLong_AsSsize_t -# else /* 2.5 and below */ -# define PY_SIZE_TYPE unsigned long -# define PyLong_FROM_SSIZE_T PyLong_FromUnsignedLong -# define PyLong_AS_SSIZE_T PyLong_AsUnsignedLong + +#if PY_MAJOR_VERSION >= 3 + #define PYRABBITMQ_MOD_INIT(name) PyMODINIT_FUNC PyInit_##name(void) +#else + #define PYRABBITMQ_MOD_INIT(name) PyMODINIT_FUNC init##name(void) #endif + #if PY_VERSION_HEX >= 0x03000000 /* 3.0 and up */ +# define BUILD_METHOD_NAME PyUnicode_FromString # define FROM_FORMAT PyUnicode_FromFormat # define PyInt_FromLong PyLong_FromLong +# define PyInt_AS_LONG PyLong_AsLong +# define PyInt_Check PyLong_Check # define PyInt_FromSsize_t PyLong_FromSsize_t # define PyString_INTERN_FROM_STRING PyString_FromString #else /* 2.x */ +# define BUILD_METHOD_NAME PyBytes_FromString # define FROM_FORMAT PyString_FromFormat # define PyString_INTERN_FROM_STRING PyString_InternFromString #endif @@ -49,6 +53,21 @@ # endif #endif + +_PYRMQ_INLINE PyObject* +buffer_toMemoryView(char *buf, Py_ssize_t buf_len) { + PyObject *view; +#if PY_MAJOR_VERSION == 2 + PyObject *pybuffer; + pybuffer = PyBuffer_FromMemory(buf, buf_len); + view = PyMemoryView_FromObject(pybuffer); + Py_XDECREF(pybuffer); +#else + view = PyMemoryView_FromMemory(buf, buf_len, PyBUF_READ); +#endif + return view; +} + #define PyDICT_SETNONE_DECREF(dict, key) \ do { \ PyDict_SetItem(dict, key, Py_None); \ @@ -68,8 +87,14 @@ Py_XDECREF(value); \ } while(0) -#define PySTRING_FROM_AMQBYTES(member) \ - PyString_FromStringAndSize(member.bytes, (PY_SIZE_TYPE)member.len); \ +#if PY_MAJOR_VERSION == 2 +# define PySTRING_FROM_AMQBYTES(member) \ + PyString_FromStringAndSize((member).bytes, (Py_ssize_t)(member).len) +#else +# define PySTRING_FROM_AMQBYTES(member) \ + PyUnicode_FromStringAndSize((member).bytes, (Py_ssize_t)(member).len) +#endif + #define AMQTable_TO_PYKEY(table, i) \ PySTRING_FROM_AMQBYTES(table->entries[i].key) @@ -83,7 +108,7 @@ _PYRMQ_INLINE PyObject* Maybe_Unicode(PyObject *); #if defined(__C99__) || defined(__GNUC__) # define PyString_AS_AMQBYTES(s) \ - (amqp_bytes_t){Py_SIZE(s), (void *)PyString_AS_STRING(s)} + (amqp_bytes_t){Py_SIZE(s), (void *)PyBytes_AS_STRING(s)} #else _PYRMQ_INLINE amqp_bytes_t PyString_AS_AMQBYTES(PyObject *); _PYRMQ_INLINE amqp_bytes_t @@ -91,7 +116,7 @@ PyString_AS_AMQBYTES(PyObject *s) { amqp_bytes_t ret; ret.len = Py_SIZE(s); - ret.bytes = (void *)PyString_AS_STRING(s); + ret.bytes = (void *)PyBytes_AS_STRING(s); /*{Py_SIZE(s), (void *)PyString_AS_STRING(s)};*/ return ret; } @@ -337,8 +362,7 @@ static PyTypeObject PyRabbitMQ_ConnectionType = { /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ 0, - /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | - Py_TPFLAGS_HAVE_WEAKREFS, + /* tp_flags */ TP_FLAGS, /* tp_doc */ PyRabbitMQ_ConnectionType_doc, /* tp_traverse */ 0, /* tp_clear */ 0, diff --git a/benchmark.py b/benchmark.py index 7f17813..6143682 100644 --- a/benchmark.py +++ b/benchmark.py @@ -1,20 +1,18 @@ import timeit -QS = ("amqplib.benchmark", "librabbit.benchmark") - - INIT_COMMON = """ connection = amqp.Connection(hostname="localhost", userid="guest", -password="guest", virtual_host="/") +password="guest", virtual_host="/", lazy=True) +connection.connect() channel = connection.channel() channel.exchange_declare(Q, "direct") channel.queue_declare(Q) channel.queue_bind(Q, Q, Q) """ -INIT_AMQPLIB = """ -from amqplib import client_0_8 as amqp -Q = "amqplib.benchmark" +INIT_AMQP = """ +import amqp +Q = "amqp.benchmark" %s """ % INIT_COMMON @@ -35,7 +33,7 @@ connection._basic_publish(1, "x" * %d, Q, Q, {}) """ CONSUME = """ -method = getattr(channel, "wait", None) or connection.drain_events +method = connection.drain_events def callback(m): channel.basic_ack(m.delivery_info["delivery_tag"]) channel.basic_consume(Q, callback=callback) @@ -45,31 +43,45 @@ for i in range(%(its)d): def bench_basic_publish(iterations=10000, bytes=256): - t_publish_amqplib = timeit.Timer(stmt=PUBLISH % bytes, - setup=INIT_AMQPLIB) + t_publish_amqp = timeit.Timer(stmt=PUBLISH % bytes, + setup=INIT_AMQP) t_publish_librabbit = timeit.Timer(stmt=PUBLISH_LIBRABBIT % bytes, setup=INIT_LIBRABBIT) - print("basic.publish: (%s byte messages)" % bytes) - print(" amqplib: %.2f usec/pass" % ( - iterations * t_publish_amqplib.timeit(number=iterations)/iterations)) - print(" librabbit: %.2f usec/pass" % ( - iterations * t_publish_librabbit.timeit(number=iterations)/iterations)) + print("basic.publish: (%s x %s bytes messages)" % (iterations, bytes)) + print(" amqp: %.2f sec/pass" % ( + iterations * t_publish_amqp.timeit(number=iterations)/iterations) + ) + print(" librabbit: %.2f sec/pass" % ( + iterations * t_publish_librabbit.timeit(number=iterations)/iterations) + ) -def bench_basic_consume(iterations=10000): +def bench_basic_consume(iterations=10000, bytes=None): context = {"its": (iterations/2)/10} - t_consume_amqplib = timeit.Timer(stmt=CONSUME % context, - setup=INIT_AMQPLIB) + t_consume_amqp = timeit.Timer(stmt=CONSUME % context, + setup=INIT_AMQP) t_consume_librabbit = timeit.Timer(stmt=CONSUME % context, setup=INIT_LIBRABBIT) print("basic.consume (%s msg/pass) " % context["its"]) - print(" amqplib: %.2f usec/pass" % ( - 10 * t_consume_amqplib.timeit(number=10)/10)) - print(" librabbit: %.2f usec/pass" % ( - 10 * t_consume_librabbit.timeit(number=10)/10)) + print(" amqp: %.2f sec/pass" % ( + t_consume_amqp.timeit(number=10)) + ) + print(" librabbit: %.2f sec/pass" % ( + t_consume_librabbit.timeit(number=10)) + ) + benchmarks = [bench_basic_publish, bench_basic_consume] if __name__ == "__main__": + import argparse + + parser = argparse.ArgumentParser(description='Runs benchmark against local RabbitMQ instance.') + parser.add_argument('--iters', metavar='N', type=int, default=100000, + help='Number of iterations') + parser.add_argument('--bytes', metavar='B', type=int, + default=256, help='Message size') + + args = parser.parse_args() for benchmark in benchmarks: - benchmark(100000) + benchmark(args.iters, bytes=args.bytes) diff --git a/funtests/config.py b/funtests/config.py index 8e3cec4..1b95423 100644 --- a/funtests/config.py +++ b/funtests/config.py @@ -7,7 +7,7 @@ BROKER_USER = os.environ.get('BROKER_USER', 'guest') BROKER_PASSWORD = os.environ.get('BROKER_PASSWORD', 'guest') from functools import partial -from unittest2 import TestCase +from unittest import TestCase from uuid import uuid4 diff --git a/funtests/setup.py b/funtests/setup.py index fa6f625..5116dd6 100644 --- a/funtests/setup.py +++ b/funtests/setup.py @@ -45,7 +45,6 @@ setup( build_requires=[ "nose", "nose-cover3", - "unittest2", "coverage>=3.0", ], classifiers=[ diff --git a/librabbitmq/__init__.py b/librabbitmq/__init__.py index c3c831c..974f1f6 100644 --- a/librabbitmq/__init__.py +++ b/librabbitmq/__init__.py @@ -1,6 +1,8 @@ from __future__ import absolute_import +import sys import itertools +from six.moves import xrange import _librabbitmq @@ -43,7 +45,10 @@ class Channel(object): def __init__(self, connection, channel_id): self.connection = connection self.channel_id = channel_id - self.next_consumer_tag = itertools.count(1).next + if sys.version_info.major == 2: + self.next_consumer_tag = itertools.count(1).next + else: + self.next_consumer_tag = itertools.count(1).__next__ self.no_ack_consumers = set() def __enter__(self): diff --git a/librabbitmq/tests/test_functional.py b/librabbitmq/tests/test_functional.py index 2dc9bd6..03d6276 100644 --- a/librabbitmq/tests/test_functional.py +++ b/librabbitmq/tests/test_functional.py @@ -1,8 +1,9 @@ from __future__ import absolute_import -from __future__ import with_statement + +from six.moves import xrange import socket -import unittest2 as unittest +import unittest from librabbitmq import Message, Connection, ConnectionError, ChannelError TEST_QUEUE = 'pyrabbit.testq' @@ -86,7 +87,7 @@ class test_Channel(unittest.TestCase): for i in xrange(100): self.connection.drain_events(timeout=0.2) - self.assertEquals(len(messages), 100) + self.assertEqual(len(messages), 100) def test_timeout(self): """Check that our ``drain_events`` call actually times out if @@ -110,7 +111,7 @@ class test_Channel(unittest.TestCase): with self.assertRaises(socket.timeout): self.connection.drain_events(timeout=0.1) - self.assertEquals(len(messages), 1) + self.assertEqual(len(messages), 1) def tearDown(self): if self.channel and self.connection.connected: diff --git a/rabbitmq-c b/rabbitmq-c -Subproject 185ce081e3efc846b476995b7da7297bb0eec82 +Subproject caad0ef1533783729c7644a226c989c79b4c497 diff --git a/rabbitmq-codegen b/rabbitmq-codegen deleted file mode 160000 -Subproject b25efdd3f88a2b37af8e6c928432cb7378e772a diff --git a/requirements/README.rst b/requirements/README.rst index 1175f71..ffe49f4 100644 --- a/requirements/README.rst +++ b/requirements/README.rst @@ -14,10 +14,6 @@ Index Requirements needed to run the full unittest suite. -* :file:`requirements/test3.txt` - - Requirements needed to run the full unittest suite on Python 3. - * :file:`requirements/test-ci.txt` Extra test requirements required by the CI suite (Tox). @@ -41,12 +37,3 @@ Running the tests $ pip install -U -r requirements/default.txt $ pip install -U -r requirements/test.txt - - -Running the tests on Python 3 ------------------------------ - -:: - - $ pip install -U -r requirements/default.txt - $ pip install -U -r requirements/test3.txt diff --git a/requirements/default.txt b/requirements/default.txt index 22439cb..6fa7e25 100644 --- a/requirements/default.txt +++ b/requirements/default.txt @@ -1 +1,2 @@ +six>=1.0.0 amqp>=1.4.6 diff --git a/requirements/test.txt b/requirements/test.txt index 70e6505..1f4031d 100644 --- a/requirements/test.txt +++ b/requirements/test.txt @@ -1,3 +1,3 @@ -unittest2>=0.4.0 nose mock +six @@ -5,9 +5,8 @@ from setuptools import setup, find_packages # --with-librabbitmq=<dir>: path to librabbitmq package if needed -LRMQDIST = lambda *x: os.path.join('clib', *x) +LRMQDIST = lambda *x: os.path.join('rabbitmq-c', *x) LRMQSRC = lambda *x: LRMQDIST('librabbitmq', *x) -SPECPATH = lambda *x: os.path.join('rabbitmq-codegen', *x) PYCP = lambda *x: os.path.join('Modules', '_librabbitmq', *x) @@ -17,25 +16,7 @@ def senv(*k__v, **kwargs): for k, v in k__v: prev = restore[k] = os.environ.get(k) os.environ[k] = (prev + sep if prev else '') + str(v) - return dict((k, v) for k, v in restore.iteritems() if v is not None) - - -def codegen(): - codegen = LRMQSRC('codegen.py') - spec = SPECPATH('amqp-rabbitmq-0.9.1.json') - sys.path.insert(0, SPECPATH()) - commands = [ - (sys.executable, codegen, 'header', spec, LRMQSRC('amqp_framing.h')), - (sys.executable, codegen, 'body', spec, LRMQSRC('amqp_framing.c')), - ] - restore = senv(('PYTHONPATH', SPECPATH()), sep=':') - try: - for command in commands: - print('- generating %r' % command[-1]) - print(' '.join(command)) - os.system(' '.join(command)) - finally: - os.environ.update(restore) + return dict((k, v) for k, v in restore.items() if v is not None) def create_builder(): @@ -81,7 +62,7 @@ def create_builder(): 'amqp_socket.c', 'amqp_table.c', 'amqp_tcp_socket.c', - 'amqp_timer.c', + 'amqp_time.c', 'amqp_url.c', ]) @@ -92,7 +73,7 @@ def create_builder(): librabbitmq_ext = Extension( '_librabbitmq', - sources=PyC_files + librabbit_files, + sources=list(PyC_files) + list(librabbit_files), libraries=libs, include_dirs=incdirs, library_dirs=libdirs, define_macros=defs, ) @@ -150,7 +131,6 @@ def create_builder(): restore = senv( ('CFLAGS', ' '.join(self.stdcflags)), ) - codegen() try: _build.run(self) finally: @@ -179,10 +159,9 @@ packages = [] goahead = False is_jython = sys.platform.startswith('java') is_pypy = hasattr(sys, 'pypy_version_info') -is_py3k = sys.version_info[0] == 3 is_win = platform.system() == 'Windows' is_linux = platform.system() == 'Linux' -if is_jython or is_pypy or is_py3k or is_win: +if is_jython or is_pypy or is_win: pass elif find_make(): try: @@ -216,6 +195,13 @@ if 'bdist_egg' in sys.argv and 'build' not in sys.argv: sys.argv[:_index] + ['build', 'bdist_egg'] + sys.argv[_index + 1:] ) +# 'test doesn't always call build for some reason +if 'test' in sys.argv and 'build' not in sys.argv: + _index = sys.argv.index('test') + sys.argv[:] = ( + sys.argv[:_index] + ['build', 'test'] + sys.argv[_index + 1:] + ) + setup( name='librabbitmq', version=version, @@ -231,6 +217,7 @@ setup( cmdclass=cmdclass, install_requires=[ 'amqp>=1.4.6', + 'six>=1.0.0', ], ext_modules=ext_modules, classifiers=[ @@ -238,9 +225,10 @@ setup( 'Operating System :: POSIX', 'Operating System :: Microsoft :: Windows', 'Programming Language :: C', - 'Programming Language :: Python :: 2.5', - 'Programming Language :: Python :: 2.6', 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: Implementation :: CPython', 'Intended Audience :: Developers', 'License :: OSI Approved :: Mozilla Public License 1.0 (MPL)', |