diff --git a/.travis.yml b/.travis.yml index c1217d3..1cc1881 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,11 +1,9 @@ dist: xenial language: python python: - - 2.7 - - 3.4 - - 3.5 - 3.6 - 3.7 + - 3.8 services: - docker install: diff --git a/docker-compose.yml b/docker-compose.yml index 963b9f4..5661748 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,5 +1,5 @@ rabbitmq: - image: rabbitmq:3.7 + image: rabbitmq:3.8 ports: - 5672 - 15672 diff --git a/docs/api/exceptions.rst b/docs/api/exceptions.rst index c5c157b..215c4b9 100644 --- a/docs/api/exceptions.rst +++ b/docs/api/exceptions.rst @@ -28,7 +28,7 @@ rabbitpy contains two types of exceptions, exceptions that are specific to rabbi self._write_frame(frame_value) File "rabbitpy/base.py", line 311, in _write_frame raise exception - rabbitpy.exceptions.AMQPPreconditionFailed: + rabbitpy.exceptions.AMQPPreconditionFailed: In this example, the channel that was created on the second line was closed and RabbitMQ is raising the :class:`AMQPPreconditionFailed ` exception via RPC sent to your application using the AMQP Channel.Close method. diff --git a/rabbitpy/amqp.py b/rabbitpy/amqp.py index dde40e9..2265dc0 100644 --- a/rabbitpy/amqp.py +++ b/rabbitpy/amqp.py @@ -2,8 +2,7 @@ AMQP Adapter """ -from pamqp import specification as spec - +from pamqp import commands from rabbitpy import base from rabbitpy import message from rabbitpy import exceptions @@ -35,7 +34,7 @@ def basic_ack(self, delivery_tag=0, multiple=False): :param bool multiple: Acknowledge multiple messages """ - self._write_frame(spec.Basic.Ack(delivery_tag, multiple)) + self._write_frame(commands.Basic.Ack(delivery_tag, multiple)) def basic_consume(self, queue='', consumer_tag='', no_local=False, no_ack=False, exclusive=False, nowait=False, @@ -70,7 +69,7 @@ def basic_consume(self, queue='', consumer_tag='', no_local=False, consumer_tag = self.consumer_tag # pylint: disable=protected-access self.channel._consumers[consumer_tag] = (self, no_ack) - self._rpc(spec.Basic.Consume(0, queue, consumer_tag, no_local, no_ack, + self._rpc(commands.Basic.Consume(0, queue, consumer_tag, no_local, no_ack, exclusive, nowait, arguments)) self._consuming = True try: @@ -119,7 +118,7 @@ def basic_get(self, queue='', no_ack=False): :param bool no_ack: No acknowledgement needed """ - self._rpc(spec.Basic.Get(0, queue, no_ack)) + self._rpc(commands.Basic.Get(0, queue, no_ack)) def basic_nack(self, delivery_tag=0, multiple=False, requeue=True): """Reject one or more incoming messages. @@ -137,7 +136,7 @@ def basic_nack(self, delivery_tag=0, multiple=False, requeue=True): :param bool requeue: Requeue the message """ - self._write_frame(spec.Basic.Nack(delivery_tag, multiple, requeue)) + self._write_frame(commands.Basic.Nack(delivery_tag, multiple, requeue)) def basic_publish(self, exchange='', routing_key='', body='', properties=None, mandatory=False, immediate=False): @@ -178,7 +177,7 @@ def basic_qos(self, prefetch_size=0, prefetch_count=0, global_flag=False): :param bool global_flag: Apply to entire connection """ - self._rpc(spec.Basic.Qos(prefetch_size, prefetch_count, global_flag)) + self._rpc(commands.Basic.Qos(prefetch_size, prefetch_count, global_flag)) def basic_reject(self, delivery_tag=0, requeue=True): """Reject an incoming message @@ -192,7 +191,7 @@ def basic_reject(self, delivery_tag=0, requeue=True): :param bool requeue: Requeue the message """ - self._write_frame(spec.Basic.Reject(delivery_tag, requeue)) + self._write_frame(commands.Basic.Reject(delivery_tag, requeue)) def basic_recover(self, requeue=False): """Redeliver unacknowledged messages @@ -204,14 +203,14 @@ def basic_recover(self, requeue=False): :param bool requeue: Requeue the message """ - self._rpc(spec.Basic.Recover(requeue)) + self._rpc(commands.Basic.Recover(requeue)) def confirm_select(self): """This method sets the channel to use publisher acknowledgements. The client can only use this method on a non-transactional channel. """ - self._rpc(spec.Confirm.Select()) + self._rpc(commands.Confirm.Select()) def exchange_declare(self, exchange='', exchange_type='direct', passive=False, durable=False, auto_delete=False, @@ -232,7 +231,7 @@ def exchange_declare(self, exchange='', exchange_type='direct', :param dict arguments: Arguments for declaration """ - self._rpc(spec.Exchange.Declare(0, exchange, exchange_type, passive, + self._rpc(commands.Exchange.Declare(0, exchange, exchange_type, passive, durable, auto_delete, internal, nowait, arguments)) @@ -248,7 +247,7 @@ def exchange_delete(self, exchange='', if_unused=False, :param bool nowait: Do not send a reply method """ - self._rpc(spec.Exchange.Delete(0, exchange, if_unused, nowait)) + self._rpc(commands.Exchange.Delete(0, exchange, if_unused, nowait)) def exchange_bind(self, destination='', source='', routing_key='', nowait=False, arguments=None): @@ -263,7 +262,7 @@ def exchange_bind(self, destination='', source='', :param dict arguments: Optional arguments """ - self._rpc(spec.Exchange.Bind(0, destination, source, routing_key, + self._rpc(commands.Exchange.Bind(0, destination, source, routing_key, nowait, arguments)) def exchange_unbind(self, destination='', source='', @@ -279,7 +278,7 @@ def exchange_unbind(self, destination='', source='', :param dict arguments: Optional arguments """ - self._rpc(spec.Exchange.Unbind(0, destination, source, routing_key, + self._rpc(commands.Exchange.Unbind(0, destination, source, routing_key, nowait, arguments)) def queue_bind(self, queue='', exchange='', routing_key='', @@ -298,7 +297,7 @@ def queue_bind(self, queue='', exchange='', routing_key='', :param dict arguments: Arguments for binding """ - self._rpc(spec.Queue.Bind(0, queue, exchange, routing_key, nowait, + self._rpc(commands.Queue.Bind(0, queue, exchange, routing_key, nowait, arguments)) def queue_declare(self, queue='', passive=False, durable=False, @@ -319,7 +318,7 @@ def queue_declare(self, queue='', passive=False, durable=False, :param dict arguments: Arguments for declaration """ - self._rpc(spec.Queue.Declare(0, queue, passive, durable, exclusive, + self._rpc(commands.Queue.Declare(0, queue, passive, durable, exclusive, auto_delete, nowait, arguments)) def queue_delete(self, queue='', if_unused=False, if_empty=False, @@ -336,7 +335,7 @@ def queue_delete(self, queue='', if_unused=False, if_empty=False, :param bool nowait: Do not send a reply method """ - self._rpc(spec.Queue.Delete(0, queue, if_unused, if_empty, nowait)) + self._rpc(commands.Queue.Delete(0, queue, if_unused, if_empty, nowait)) def queue_purge(self, queue='', nowait=False): """Purge a queue @@ -348,7 +347,7 @@ def queue_purge(self, queue='', nowait=False): :param bool nowait: Do not send a reply method """ - self._rpc(spec.Queue.Purge(0, queue, nowait)) + self._rpc(commands.Queue.Purge(0, queue, nowait)) def queue_unbind(self, queue='', exchange='', routing_key='', arguments=None): @@ -362,7 +361,7 @@ def queue_unbind(self, queue='', exchange='', routing_key='', :param dict arguments: Arguments of binding """ - self._rpc(spec.Queue.Unbind(0, queue, exchange, routing_key, + self._rpc(commands.Queue.Unbind(0, queue, exchange, routing_key, arguments)) def tx_select(self): @@ -373,7 +372,7 @@ def tx_select(self): or Rollback methods. """ - self._rpc(spec.Tx.Select()) + self._rpc(commands.Tx.Select()) def tx_commit(self): """Commit the current transaction @@ -383,7 +382,7 @@ def tx_commit(self): immediately after a commit. """ - self._rpc(spec.Tx.Commit()) + self._rpc(commands.Tx.Commit()) def tx_rollback(self): """Abandon the current transaction @@ -395,4 +394,4 @@ def tx_rollback(self): recover call should be issued. """ - self._rpc(spec.Tx.Rollback()) + self._rpc(commands.Tx.Rollback()) diff --git a/rabbitpy/amqp_queue.py b/rabbitpy/amqp_queue.py index 6cc48a8..703869b 100644 --- a/rabbitpy/amqp_queue.py +++ b/rabbitpy/amqp_queue.py @@ -29,7 +29,7 @@ import logging import warnings -from pamqp import specification +from pamqp import commands from rabbitpy import base from rabbitpy import exceptions @@ -172,12 +172,12 @@ def bind(self, source, routing_key=None, arguments=None): """ if hasattr(source, 'name'): source = source.name - frame = specification.Queue.Bind(queue=self.name, + frame = commands.Queue.Bind(queue=self.name, exchange=source, routing_key=routing_key or '', arguments=arguments) response = self._rpc(frame) - return isinstance(response, specification.Queue.BindOk) + return isinstance(response, commands.Queue.BindOk) def consume(self, no_ack=False, prefetch=None, priority=None, consumer_tag=None): @@ -286,7 +286,7 @@ def delete(self, if_unused=False, if_empty=False): :param bool if_empty: Delete only if empty """ - self._rpc(specification.Queue.Delete(queue=self.name, + self._rpc(commands.Queue.Delete(queue=self.name, if_unused=if_unused, if_empty=if_empty)) @@ -305,7 +305,7 @@ def get(self, acknowledge=True): :rtype: :class:`~rabbitpy.Message` or None """ - self._write_frame(specification.Basic.Get(queue=self.name, + self._write_frame(commands.Basic.Get(queue=self.name, no_ack=not acknowledge)) return self.channel._get_message() # pylint: disable=protected-access @@ -332,7 +332,7 @@ def ha_declare(self, nodes=None): def purge(self): """Purge the queue of all of its messages.""" - self._rpc(specification.Queue.Purge()) + self._rpc(commands.Queue.Purge()) def stop_consuming(self): """Stop consuming messages. This is usually invoked if you want to @@ -361,7 +361,7 @@ def unbind(self, source, routing_key=None): if hasattr(source, 'name'): source = source.name routing_key = routing_key or self.name - self._rpc(specification.Queue.Unbind(queue=self.name, exchange=source, + self._rpc(commands.Queue.Unbind(queue=self.name, exchange=source, routing_key=routing_key)) def _consume(self, no_ack=False, prefetch=None, priority=None): @@ -381,12 +381,12 @@ def _consume(self, no_ack=False, prefetch=None, priority=None): self.consuming = True def _declare(self, passive=False): - """Return a specification.Queue.Declare class pre-composed for the rpc + """Return a commands.Queue.Declare class pre-composed for the rpc method since this can be called multiple times. :param bool passive: Passive declare to retrieve message count and consumer count information - :rtype: pamqp.specification.Queue.Declare + :rtype: pamqp.commands.Queue.Declare """ arguments = dict(self.arguments) @@ -406,7 +406,7 @@ def _declare(self, passive=False): 'exclusive=%s, auto_delete=%s, arguments=%r', self.name, self.durable, passive, self.exclusive, self.auto_delete, arguments) - return specification.Queue.Declare(queue=self.name, + return commands.Queue.Declare(queue=self.name, durable=self.durable, passive=passive, exclusive=self.exclusive, diff --git a/rabbitpy/base.py b/rabbitpy/base.py index cd1f18d..7881584 100644 --- a/rabbitpy/base.py +++ b/rabbitpy/base.py @@ -5,8 +5,8 @@ import logging import threading -from pamqp import specification - +from pamqp import base +from pamqp import commands from rabbitpy import exceptions from rabbitpy import utils from rabbitpy.utils import queue @@ -30,8 +30,8 @@ def __init__(self, channel): def _rpc(self, frame_value): """Execute the RPC command for the frame. - :param pamqp.specification.Frame frame_value: The frame to send - :rtype: pamqp.specification.Frame or pamqp.message.Message + :param pamqp.base.Frame frame_value: The frame to send + :rtype: pamqp.base.Frame or pamqp.message.Message """ LOGGER.debug('Issuing RPC to RabbitMQ: %r', frame_value) @@ -42,7 +42,7 @@ def _rpc(self, frame_value): def _write_frame(self, frame_value): """Write a frame to the channel's connection - :param pamqp.specification.Frame frame_value: The frame to send + :param pamqp.base.Frame frame_value: The frame to send """ self.channel.write_frame(frame_value) @@ -158,9 +158,11 @@ def state_description(self): class AMQPChannel(StatefulObject): """Base AMQP Channel Object""" - CLOSE_REQUEST_FRAME = specification.Channel.Close + CLOSE_REQUEST_FRAME = commands.Channel.Close DEFAULT_CLOSE_CODE = 200 DEFAULT_CLOSE_REASON = 'Normal Shutdown' + DEFAULT_CLOSE_CLASS_ID = 0 + DEFAULT_CLOSE_METHOD_ID = 0 REMOTE_CLOSED = 0x04 def __init__(self, exception_queue, write_trigger, connection, @@ -219,8 +221,8 @@ def rpc(self, frame_value): """Send a RPC command to the remote server. This should not be directly invoked. - :param pamqp.specification.Frame frame_value: The frame to send - :rtype: pamqp.specification.Frame or None + :param pamqp.base.Frame frame_value: The frame to send + :rtype: pamqp.base.Frame or None """ if self.closed: @@ -238,14 +240,14 @@ def wait_for_confirmation(self): :rtype: pamqp.frame.Frame """ - return self._wait_on_frame([specification.Basic.Ack, - specification.Basic.Nack]) + return self._wait_on_frame([commands.Basic.Ack, + commands.Basic.Nack]) def write_frame(self, frame): """Put the frame in the write queue for the IOWriter object to write to the socket when it can. This should not be directly invoked. - :param pamqp.specification.Frame frame: The frame to write + :param pamqp.base.Frame frame: The frame to write """ if self._can_write(): @@ -275,11 +277,13 @@ def write_frames(self, frames): def _build_close_frame(self): """Return the proper close frame for this object. - :rtype: pamqp.specification.Channel.Close + :rtype: pamqp.commands.Channel.Close """ return self.CLOSE_REQUEST_FRAME(self.DEFAULT_CLOSE_CODE, - self.DEFAULT_CLOSE_REASON) + self.DEFAULT_CLOSE_REASON, + self.DEFAULT_CLOSE_CLASS_ID, + self.DEFAULT_CLOSE_METHOD_ID) def _can_write(self): self._check_for_exceptions() @@ -323,7 +327,7 @@ def _check_for_rpc_request(self, value): RPC requests from RabbitMQ. """ - if isinstance(value, specification.Channel.Close): + if isinstance(value, commands.Channel.Close): LOGGER.debug('Channel closed') self._on_remote_close(value) @@ -368,7 +372,7 @@ def _on_remote_close(self, value): """Handle RabbitMQ remotely closing the channel :param value: The Channel.Close method frame - :type value: pamqp.spec.Channel.Close + :type value: pamqp.commands.Channel.Close :raises: exceptions.RemoteClosedChannelException :raises: exceptions.AMQPException @@ -386,7 +390,7 @@ def _on_remote_close(self, value): def _read_from_queue(self): """Check to see if a frame is in the queue and if so, return it - :rtype: amqp.specification.Frame or None + :rtype: amqp.base.Frame or None """ if self._can_write() and not self.closing and self.blocking_read: @@ -414,9 +418,9 @@ def _validate_frame_type(self, frame_value, frame_type): be an individual frame type or a list of frame types. :param frame_value: The frame to check - :type frame_value: pamqp.specification.Frame + :type frame_value: pamqp.base.Frame :param frame_type: The frame(s) to check against - :type frame_type: pamqp.specification.Frame or list + :type frame_type: pamqp.base.Frame or list :rtype: bool """ @@ -433,7 +437,7 @@ def _validate_frame_type(self, frame_value, frame_type): if result: return True return False - elif isinstance(frame_value, specification.Frame): + elif isinstance(frame_value, base.Frame): return frame_value.name == frame_type.name return False @@ -445,7 +449,7 @@ def _wait_on_frame(self, frame_type=None): call the method. :param frame_type: The name or list of names of the frame type(s) - :type frame_type: str|list|pamqp.specification.Frame + :type frame_type: str|list|pamqp.base.Frame :rtype: Frame """ diff --git a/rabbitpy/channel.py b/rabbitpy/channel.py index 9bc6174..d66dc18 100644 --- a/rabbitpy/channel.py +++ b/rabbitpy/channel.py @@ -7,9 +7,8 @@ """ import logging -from pamqp import specification as spec -from pamqp import PYTHON3 - +from pamqp import base +from pamqp import commands from rabbitpy import base from rabbitpy import exceptions from rabbitpy import message @@ -151,7 +150,7 @@ def enable_publisher_confirms(self): """ if not self._supports_publisher_confirms: raise exceptions.NotSupportedError('Confirm.Select') - self.rpc(spec.Confirm.Select()) + self.rpc(commands.Confirm.Select()) self._publisher_confirms = True @property @@ -178,7 +177,7 @@ def open(self): """ self._set_state(self.OPENING) self.write_frame(self._build_open_frame()) - self._wait_on_frame(spec.Channel.OpenOk) + self._wait_on_frame(commands.Channel.OpenOk) self._set_state(self.OPEN) LOGGER.debug('Channel #%i open', self._channel_id) @@ -191,7 +190,7 @@ def prefetch_count(self, value, all_channels=False): same connection """ - self.rpc(spec.Basic.Qos(prefetch_count=value, global_=all_channels)) + self.rpc(commands.Basic.Qos(prefetch_count=value, global_=all_channels)) def prefetch_size(self, value, all_channels=False): """Set a prefetch size in bytes for the channel (or all channels on the @@ -204,7 +203,7 @@ def prefetch_size(self, value, all_channels=False): """ if value is None: return - self.rpc(spec.Basic.Qos(prefetch_size=value, global_=all_channels)) + self.rpc(commands.Basic.Qos(prefetch_size=value, global_=all_channels)) @property def publisher_confirms(self): @@ -222,16 +221,16 @@ def recover(self, requeue=False): :param bool requeue: Requeue the message """ - self.rpc(spec.Basic.Recover(requeue=requeue)) + self.rpc(commands.Basic.Recover(requeue=requeue)) @staticmethod def _build_open_frame(): """Build and return a channel open frame - :rtype: pamqp.spec.Channel.Open + :rtype: pamqp.commands.Channel.Open """ - return spec.Channel.Open() + return commands.Channel.Open() def _cancel_consumer(self, obj, consumer_tag=None, nowait=False): """Cancel the consuming of a queue. @@ -253,25 +252,25 @@ def _on_ready_to_cancel(self, consumer_tag, nowait): if consumer_tag in self._consumers: del self._consumers[consumer_tag] if nowait: - self.write_frame(spec.Basic.Cancel(consumer_tag=consumer_tag, + self.write_frame(commands.Basic.Cancel(consumer_tag=consumer_tag, nowait=True)) return - self.rpc(spec.Basic.Cancel(consumer_tag=consumer_tag)) + self.rpc(commands.Basic.Cancel(consumer_tag=consumer_tag)) def _check_for_rpc_request(self, value): """Inspect a frame to see if it's a RPC request from RabbitMQ. - :param spec.Frame value: + :param base.Frame value: """ LOGGER.debug('Checking for RPC request: %r', value) super(Channel, self)._check_for_rpc_request(value) - if isinstance(value, spec.Basic.Return): + if isinstance(value, commands.Basic.Return): raise exceptions.MessageReturnedException(value.reply_code, value.reply_text, value.exchange, value.routing_key) - elif isinstance(value, spec.Basic.Cancel): + elif isinstance(value, commands.Basic.Cancel): self._waiting = False if value.consumer_tag in self._consumers: del self._consumers[value.consumer_tag] @@ -294,7 +293,7 @@ def _consume(self, obj, no_ack, priority=None): if not isinstance(priority, int): raise ValueError('Consumer priority must be an int') args['x-priority'] = priority - self.rpc(spec.Basic.Consume(queue=obj.name, + self.rpc(commands.Basic.Consume(queue=obj.name, consumer_tag=obj.consumer_tag, no_ack=no_ack, arguments=args)) @@ -310,7 +309,7 @@ def _consume_message(self): """ if not self._consumers: raise exceptions.NotConsumingError - frame_value = self._wait_on_frame([spec.Basic.Deliver]) + frame_value = self._wait_on_frame([commands.Basic.Deliver]) LOGGER.debug('Waited on frame, got %r', frame_value) if frame_value: return self._wait_for_content_frames(frame_value) @@ -322,7 +321,7 @@ def _create_message(self, method_frame, header_frame, body): created. :param method_frame: The method frame value - :type method_frame: pamqp.specification.Frame + :type method_frame: pamqp.base.Frame :param header_frame: Header frame value :type header_frame: pamqp.header.ContentHeader or None :param body: The message body @@ -345,7 +344,7 @@ def _get_from_read_queue(self): """Fetch a frame from the read queue and return it, otherwise return None - :rtype: pamqp.specification.Frame + :rtype: pamqp.base.Frame """ try: @@ -365,9 +364,9 @@ def _get_message(self): :rtype: rabbitpy.message.Message or None """ - frame_value = self._wait_on_frame([spec.Basic.GetOk, - spec.Basic.GetEmpty]) - if isinstance(frame_value, spec.Basic.GetEmpty): + frame_value = self._wait_on_frame([commands.Basic.GetOk, + commands.Basic.GetEmpty]) + if isinstance(frame_value, commands.Basic.GetEmpty): return None return self._wait_for_content_frames(frame_value) @@ -382,7 +381,7 @@ def _multi_nack(self, delivery_tag, requeue=True): raise exceptions.NotSupportedError('Basic.Nack') if self._is_debugging: LOGGER.debug('Sending Basic.Nack with requeue') - self.rpc(spec.Basic.Nack(delivery_tag=delivery_tag, + self.rpc(commands.Basic.Nack(delivery_tag=delivery_tag, multiple=True, requeue=requeue)) @@ -390,10 +389,10 @@ def _reject_inbound_message(self, method_frame): """Used internally to reject a message when it's been received during a state that it should not have been. - :param pamqp.specification.Basic.Deliver method_frame: The method frame + :param pamqp.commands.Basic.Deliver method_frame: The method frame """ - self.rpc(spec.Basic.Reject(delivery_tag=method_frame.delivery_tag, + self.rpc(commands.Basic.Reject(delivery_tag=method_frame.delivery_tag, requeue=True)) @property @@ -455,7 +454,7 @@ def _wait_for_content_frames(self, method_frame): if self.closing or self.closed: return None - consuming = isinstance(method_frame, spec.Basic.Deliver) + consuming = isinstance(method_frame, commands.Basic.Deliver) if consuming and not self._consumers: return None @@ -474,13 +473,7 @@ def _wait_for_content_frames(self, method_frame): error = False - # To retrieve the message body we must concatenate the binary content - # of several frames. The recommended idiom for this differs - # in py3 and py2. - if PYTHON3: - body_value = bytearray() - else: - body_chunks = [] + body_value = bytearray() body_length_received = 0 body_total_size = header_value.body_size @@ -502,12 +495,6 @@ def _wait_for_content_frames(self, method_frame): return body_length_received += len(body_part.value) - if PYTHON3: - body_value += body_part.value - else: - body_chunks.append(body_part.value) - - if not PYTHON3: - body_value = ''.join(body_chunks) + body_value += body_part.value return self._create_message(method_frame, header_value, body_value) diff --git a/rabbitpy/channel0.py b/rabbitpy/channel0.py index 2e475fe..4a4ab11 100644 --- a/rabbitpy/channel0.py +++ b/rabbitpy/channel0.py @@ -9,7 +9,8 @@ from pamqp import header from pamqp import heartbeat -from pamqp import specification +from pamqp import commands +from pamqp import constants from rabbitpy import __version__ from rabbitpy import base @@ -39,7 +40,11 @@ class Channel0(base.AMQPChannel): """ CHANNEL = 0 - CLOSE_REQUEST_FRAME = specification.Connection.Close + CLOSE_REQUEST_FRAME = commands.Connection.Close + DEFAULT_CLOSE_CODE = 200 + DEFAULT_CLOSE_REASON = 'Normal Shutdown' + DEFAULT_CLOSE_CLASS_ID = 0 + DEFAULT_CLOSE_METHOD_ID = 0 DEFAULT_LOCALE = 'en-US' def __init__(self, connection_args, events_obj, exception_queue, @@ -63,7 +68,10 @@ def close(self): """Close the connection via Channel0 communication.""" if self.open: self._set_state(self.CLOSING) - self.rpc(specification.Connection.Close()) + self.rpc(commands.Connection.Close(self.DEFAULT_CLOSE_CODE, + self.DEFAULT_CLOSE_REASON, + self.DEFAULT_CLOSE_CLASS_ID, + self.DEFAULT_CLOSE_METHOD_ID)) @property def heartbeat_interval(self): @@ -133,7 +141,7 @@ def on_frame(self, value): pass else: LOGGER.warning('Unexpected Channel0 Frame: %r', value) - raise specification.AMQPUnexpectedFrame(value) + raise exceptions.AMQPUnexpectedFrame(value) def send_heartbeat(self): """Send a heartbeat frame to the remote connection.""" @@ -147,15 +155,15 @@ def start(self): def _build_open_frame(self): """Build and return the Connection.Open frame. - :rtype: pamqp.specification.Connection.Open + :rtype: pamqp.commands.Connection.Open """ - return specification.Connection.Open(self._args['virtual_host']) + return commands.Connection.Open(self._args['virtual_host']) def _build_start_ok_frame(self): """Build and return the Connection.StartOk frame. - :rtype: pamqp.specification.Connection.StartOk + :rtype: pamqp.commands.Connection.StartOk """ properties = { @@ -168,17 +176,17 @@ def _build_start_ok_frame(self): 'publisher_confirms': True}, 'information': 'See https://rabbitpy.readthedocs.io', 'version': __version__} - return specification.Connection.StartOk(client_properties=properties, + return commands.Connection.StartOk(client_properties=properties, response=self._credentials, locale=self._get_locale()) def _build_tune_ok_frame(self): """Build and return the Connection.TuneOk frame. - :rtype: pamqp.specification.Connection.TuneOk + :rtype: pamqp.commands.Connection.TuneOk """ - return specification.Connection.TuneOk(self._max_channels, + return commands.Connection.TuneOk(self._max_channels, self._max_frame_size, self._heartbeat_interval) @@ -224,7 +232,7 @@ def _on_connection_start(self, frame_value): """Negotiate the Connection.Start process, writing out a Connection.StartOk frame when the Connection.Start frame is received. - :type frame_value: pamqp.specification.Connection.Start + :type frame_value: pamqp.commands.Connection.Start :raises: rabbitpy.exceptions.ConnectionException """ @@ -247,7 +255,7 @@ def _on_connection_tune(self, frame_value): Connection.Tune frame from RabbitMQ and sending the Connection.TuneOk frame. - :param specification.Connection.Tune frame_value: Tune frame + :param commands.Connection.Tune frame_value: Tune frame """ self._max_frame_size = self._negotiate(self._max_frame_size, @@ -271,16 +279,16 @@ def _on_connection_tune(self, frame_value): def _validate_connection_start(frame_value): """Validate the received Connection.Start frame - :param specification.Connection.Start frame_value: Frame to validate + :param commands.Connection.Start frame_value: Frame to validate :rtype: bool """ if (frame_value.version_major, frame_value.version_minor) != \ - (specification.VERSION[0], specification.VERSION[1]): + (constants.VERSION[0], constants.VERSION[1]): LOGGER.warning('AMQP version error (received %i.%i, expected %r)', frame_value.version_major, frame_value.version_minor, - specification.VERSION) + constants.VERSION) return False return True diff --git a/rabbitpy/connection.py b/rabbitpy/connection.py index c4f399d..f391c78 100644 --- a/rabbitpy/connection.py +++ b/rabbitpy/connection.py @@ -3,20 +3,14 @@ """ import logging -# pylint: disable=import-error -try: - from urllib import parse as urlparse -except ImportError: - import urlparse - -try: - import ssl -except ImportError: - ssl = None +from urllib import parse as urlparse + +import ssl import threading import time -from pamqp import specification as spec +from pamqp import base +from pamqp import constants from rabbitpy import base from rabbitpy import heartbeat @@ -357,7 +351,7 @@ def _create_message(self, channel_id, method_frame, header_frame, body): :param int channel_id: The channel id the message was sent on :param method_frame: The method frame value - :type method_frame: pamqp.specification.Frame + :type method_frame: pamqp.base.Frame :param header_frame: The header frame value :type header_frame: pamqp.header.ContentHeader :param str body: The message body @@ -398,7 +392,7 @@ def _normalize_expectations(channel_id, expectations): :param int channel_id: The channel to normalize for :param expectations: List of classes or class name or class obj - :type expectations: list or str or pamqp.specification.Frame + :type expectations: list or str or pamqp.base.Frame :rtype: list """ @@ -497,7 +491,7 @@ def _process_url(self, url): 'heartbeat': self._qargs_int('heartbeat', qargs, self.DEFAULT_HEARTBEAT_INTERVAL), 'frame_max': self._qargs_int('frame_max', qargs, - spec.FRAME_MAX_SIZE), + constants.FRAME_MAX_SIZE), 'channel_max': self._qargs_int('channel_max', qargs, self.DEFAULT_CHANNEL_MAX), 'locale': self._qargs_value('locale', qargs), diff --git a/rabbitpy/exchange.py b/rabbitpy/exchange.py index 5b0b3e6..e9515d1 100644 --- a/rabbitpy/exchange.py +++ b/rabbitpy/exchange.py @@ -9,7 +9,7 @@ """ import logging -from pamqp import specification +from pamqp import commands from rabbitpy import base @@ -52,7 +52,7 @@ def bind(self, source, routing_key=None): """ if hasattr(source, 'name'): source = source.name - self._rpc(specification.Exchange.Bind(destination=self.name, + self._rpc(commands.Exchange.Bind(destination=self.name, source=source, routing_key=routing_key)) @@ -63,7 +63,7 @@ def declare(self, passive=False): :param bool passive: Do not actually create the exchange """ - self._rpc(specification.Exchange.Declare(exchange=self.name, + self._rpc(commands.Exchange.Declare(exchange=self.name, exchange_type=self.type, durable=self.durable, passive=passive, @@ -76,7 +76,7 @@ def delete(self, if_unused=False): :param bool if_unused: Delete only if unused """ - self._rpc(specification.Exchange.Delete(exchange=self.name, + self._rpc(commands.Exchange.Delete(exchange=self.name, if_unused=if_unused)) def unbind(self, source, routing_key=None): @@ -90,7 +90,7 @@ def unbind(self, source, routing_key=None): """ if hasattr(source, 'name'): source = source.name - self._rpc(specification.Exchange.Unbind(destination=self.name, + self._rpc(commands.Exchange.Unbind(destination=self.name, source=source, routing_key=routing_key)) diff --git a/rabbitpy/include/site/python3.8/greenlet/greenlet.h b/rabbitpy/include/site/python3.8/greenlet/greenlet.h new file mode 100644 index 0000000..d68160b --- /dev/null +++ b/rabbitpy/include/site/python3.8/greenlet/greenlet.h @@ -0,0 +1,168 @@ +/* vim:set noet ts=8 sw=8 : */ + +/* Greenlet object interface */ + +#ifndef Py_GREENLETOBJECT_H +#define Py_GREENLETOBJECT_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define GREENLET_VERSION "0.4.17" + +#if PY_VERSION_HEX >= 0x030700A3 +# define GREENLET_USE_EXC_INFO +#endif + +#ifndef GREENLET_USE_CONTEXT_VARS +#ifdef Py_CONTEXT_H +#define GREENLET_USE_CONTEXT_VARS 1 +#else +#define GREENLET_USE_CONTEXT_VARS 0 +#endif +#endif + +typedef struct _greenlet { + PyObject_HEAD + char* stack_start; + char* stack_stop; + char* stack_copy; + intptr_t stack_saved; + struct _greenlet* stack_prev; + struct _greenlet* parent; + PyObject* run_info; + struct _frame* top_frame; + int recursion_depth; + PyObject* weakreflist; +#ifdef GREENLET_USE_EXC_INFO + _PyErr_StackItem* exc_info; + _PyErr_StackItem exc_state; +#else + PyObject* exc_type; + PyObject* exc_value; + PyObject* exc_traceback; +#endif + PyObject* dict; +#if GREENLET_USE_CONTEXT_VARS + PyObject* context; +#endif +} PyGreenlet; + +#define PyGreenlet_Check(op) PyObject_TypeCheck(op, &PyGreenlet_Type) +#define PyGreenlet_MAIN(op) (((PyGreenlet*)(op))->stack_stop == (char*) -1) +#define PyGreenlet_STARTED(op) (((PyGreenlet*)(op))->stack_stop != NULL) +#define PyGreenlet_ACTIVE(op) (((PyGreenlet*)(op))->stack_start != NULL) +#define PyGreenlet_GET_PARENT(op) (((PyGreenlet*)(op))->parent) + +#if (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION >= 7) || (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 1) || PY_MAJOR_VERSION > 3 +#define GREENLET_USE_PYCAPSULE +#endif + +/* C API functions */ + +/* Total number of symbols that are exported */ +#define PyGreenlet_API_pointers 8 + +#define PyGreenlet_Type_NUM 0 +#define PyExc_GreenletError_NUM 1 +#define PyExc_GreenletExit_NUM 2 + +#define PyGreenlet_New_NUM 3 +#define PyGreenlet_GetCurrent_NUM 4 +#define PyGreenlet_Throw_NUM 5 +#define PyGreenlet_Switch_NUM 6 +#define PyGreenlet_SetParent_NUM 7 + +#ifndef GREENLET_MODULE +/* This section is used by modules that uses the greenlet C API */ +static void **_PyGreenlet_API = NULL; + +#define PyGreenlet_Type (*(PyTypeObject *) _PyGreenlet_API[PyGreenlet_Type_NUM]) + +#define PyExc_GreenletError \ + ((PyObject *) _PyGreenlet_API[PyExc_GreenletError_NUM]) + +#define PyExc_GreenletExit \ + ((PyObject *) _PyGreenlet_API[PyExc_GreenletExit_NUM]) + +/* + * PyGreenlet_New(PyObject *args) + * + * greenlet.greenlet(run, parent=None) + */ +#define PyGreenlet_New \ + (* (PyGreenlet * (*)(PyObject *run, PyGreenlet *parent)) \ + _PyGreenlet_API[PyGreenlet_New_NUM]) + +/* + * PyGreenlet_GetCurrent(void) + * + * greenlet.getcurrent() + */ +#define PyGreenlet_GetCurrent \ + (* (PyGreenlet * (*)(void)) _PyGreenlet_API[PyGreenlet_GetCurrent_NUM]) + +/* + * PyGreenlet_Throw( + * PyGreenlet *greenlet, + * PyObject *typ, + * PyObject *val, + * PyObject *tb) + * + * g.throw(...) + */ +#define PyGreenlet_Throw \ + (* (PyObject * (*) \ + (PyGreenlet *self, PyObject *typ, PyObject *val, PyObject *tb)) \ + _PyGreenlet_API[PyGreenlet_Throw_NUM]) + +/* + * PyGreenlet_Switch(PyGreenlet *greenlet, PyObject *args) + * + * g.switch(*args, **kwargs) + */ +#define PyGreenlet_Switch \ + (* (PyObject * (*)(PyGreenlet *greenlet, PyObject *args, PyObject *kwargs)) \ + _PyGreenlet_API[PyGreenlet_Switch_NUM]) + +/* + * PyGreenlet_SetParent(PyObject *greenlet, PyObject *new_parent) + * + * g.parent = new_parent + */ +#define PyGreenlet_SetParent \ + (* (int (*)(PyGreenlet *greenlet, PyGreenlet *nparent)) \ + _PyGreenlet_API[PyGreenlet_SetParent_NUM]) + +/* Macro that imports greenlet and initializes C API */ +#ifdef GREENLET_USE_PYCAPSULE +#define PyGreenlet_Import() \ +{ \ + _PyGreenlet_API = (void**)PyCapsule_Import("greenlet._C_API", 0); \ +} +#else +#define PyGreenlet_Import() \ +{ \ + PyObject *module = PyImport_ImportModule("greenlet"); \ + if (module != NULL) { \ + PyObject *c_api_object = PyObject_GetAttrString( \ + module, "_C_API"); \ + if (c_api_object != NULL && PyCObject_Check(c_api_object)) { \ + _PyGreenlet_API = \ + (void **) PyCObject_AsVoidPtr(c_api_object); \ + Py_DECREF(c_api_object); \ + } \ + Py_DECREF(module); \ + } \ +} +#endif + +#endif /* GREENLET_MODULE */ + +#ifdef __cplusplus +} +#endif +#endif /* !Py_GREENLETOBJECT_H */ diff --git a/rabbitpy/io.py b/rabbitpy/io.py index 26d3e2c..bb02db7 100644 --- a/rabbitpy/io.py +++ b/rabbitpy/io.py @@ -13,7 +13,8 @@ from pamqp import frame from pamqp import exceptions as pamqp_exceptions -from pamqp import specification +from pamqp import base +from pamqp import constants from rabbitpy import base from rabbitpy import events @@ -21,8 +22,8 @@ LOGGER = logging.getLogger(__name__) -MAX_READ = specification.FRAME_MAX_SIZE -MAX_WRITE = specification.FRAME_MAX_SIZE +MAX_READ = constants.FRAME_MAX_SIZE +MAX_WRITE = constants.FRAME_MAX_SIZE # Timeout in seconds POLL_TIMEOUT = 1.0 @@ -320,7 +321,7 @@ class IO(threading.Thread, base.StatefulObject): """ CONTENT_METHODS = ['Basic.Deliver', 'Basic.GetOk'] - READ_BUFFER_SIZE = specification.FRAME_MAX_SIZE + READ_BUFFER_SIZE = constants.FRAME_MAX_SIZE SSL_KWARGS = { 'keyfile': 'keyfile', 'certfile': 'certfile', @@ -489,7 +490,7 @@ def _add_frame_to_read_queue(self, channel_id, frame_value): :param int channel_id: The channel id the frame was received on :param frame_value: The frame to add - :type frame_value: :class:`~pamqp.specification.Frame` + :type frame_value: :class:`~pamqp.base.Frame` """ # LOGGER.debug('Adding %s to channel %s', frame_value.name, channel_id) @@ -604,7 +605,7 @@ def _get_frame_from_str(value): """Get the pamqp frame from the string value. :param str value: The value to parse for an pamqp frame - :return (str, int, pamqp.specification.Frame): Remainder of value, + :return (str, int, pamqp.base.Frame): Remainder of value, channel id and frame value """ @@ -614,7 +615,7 @@ def _get_frame_from_str(value): byte_count, channel_id, frame_in = frame.unmarshal(value) except pamqp_exceptions.UnmarshalingException: return value, None, None - except specification.AMQPFrameError as error: + except exceptions.AMQPFrameError as error: LOGGER.error('Failed to demarshal: %r', error, exc_info=True) LOGGER.debug(value) return value, None, None @@ -623,7 +624,7 @@ def _get_frame_from_str(value): def _read_frame(self): """Read from the buffer and try and get the demarshaled frame. - :rtype (int, pamqp.specification.Frame): The channel and frame + :rtype (int, pamqp.base.Frame): The channel and frame """ self._buffer, chan_id, value = self._get_frame_from_str(self._buffer) @@ -635,7 +636,7 @@ def _remote_close_channel(self, channel_id, frame_value): :param int channel_id: The channel to remote close :param frame_value: The Channel.Close frame - :type frame_value: :class:`~pamqp.specification.Frame` + :type frame_value: :class:`~pamqp.base.Frame` """ self._channels[channel_id][0].on_remote_close(frame_value) diff --git a/rabbitpy/man/man1/nosetests.1 b/rabbitpy/man/man1/nosetests.1 new file mode 100644 index 0000000..5772845 --- /dev/null +++ b/rabbitpy/man/man1/nosetests.1 @@ -0,0 +1,581 @@ +.\" Man page generated from reStructuredText. +. +.TH "NOSETESTS" "1" "April 04, 2015" "1.3" "nose" +.SH NAME +nosetests \- Nicer testing for Python +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.SH NICER TESTING FOR PYTHON +.SS SYNOPSIS +.INDENT 0.0 +.INDENT 3.5 +nosetests [options] [names] +.UNINDENT +.UNINDENT +.SS DESCRIPTION +.sp +nose collects tests automatically from python source files, +directories and packages found in its working directory (which +defaults to the current working directory). Any python source file, +directory or package that matches the testMatch regular expression +(by default: \fI(?:^|[b_.\-])[Tt]est)\fP will be collected as a test (or +source for collection of tests). In addition, all other packages +found in the working directory will be examined for python source files +or directories that match testMatch. Package discovery descends all +the way down the tree, so package.tests and package.sub.tests and +package.sub.sub2.tests will all be collected. +.sp +Within a test directory or package, any python source file matching +testMatch will be examined for test cases. Within a test module, +functions and classes whose names match testMatch and TestCase +subclasses with any name will be loaded and executed as tests. Tests +may use the assert keyword or raise AssertionErrors to indicate test +failure. TestCase subclasses may do the same or use the various +TestCase methods available. +.sp +\fBIt is important to note that the default behavior of nose is to +not include tests from files which are executable.\fP To include +tests from such files, remove their executable bit or use +the \-\-exe flag (see \(aqOptions\(aq section below). +.SS Selecting Tests +.sp +To specify which tests to run, pass test names on the command line: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +nosetests only_test_this.py +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +Test names specified may be file or module names, and may optionally +indicate the test case to run by separating the module or file name +from the test case name with a colon. Filenames may be relative or +absolute. Examples: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +nosetests test.module +nosetests another.test:TestCase.test_method +nosetests a.test:TestCase +nosetests /path/to/test/file.py:test_function +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +You may also change the working directory where nose looks for tests +by using the \-w switch: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +nosetests \-w /path/to/tests +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +Note, however, that support for multiple \-w arguments is now deprecated +and will be removed in a future release. As of nose 0.10, you can get +the same behavior by specifying the target directories \fIwithout\fP +the \-w switch: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +nosetests /path/to/tests /another/path/to/tests +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +Further customization of test selection and loading is possible +through the use of plugins. +.sp +Test result output is identical to that of unittest, except for +the additional features (error classes, and plugin\-supplied +features such as output capture and assert introspection) detailed +in the options below. +.SS Configuration +.sp +In addition to passing command\-line options, you may also put +configuration options in your project\(aqs \fIsetup.cfg\fP file, or a .noserc +or nose.cfg file in your home directory. In any of these standard +ini\-style config files, you put your nosetests configuration in a +\fB[nosetests]\fP section. Options are the same as on the command line, +with the \-\- prefix removed. For options that are simple switches, you +must supply a value: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +[nosetests] +verbosity=3 +with\-doctest=1 +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +All configuration files that are found will be loaded and their +options combined. You can override the standard config file loading +with the \fB\-c\fP option. +.SS Using Plugins +.sp +There are numerous nose plugins available via easy_install and +elsewhere. To use a plugin, just install it. The plugin will add +command line options to nosetests. To verify that the plugin is installed, +run: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +nosetests \-\-plugins +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +You can add \-v or \-vv to that command to show more information +about each plugin. +.sp +If you are running nose.main() or nose.run() from a script, you +can specify a list of plugins to use by passing a list of plugins +with the plugins keyword argument. +.SS 0.9 plugins +.sp +nose 1.0 can use SOME plugins that were written for nose 0.9. The +default plugin manager inserts a compatibility wrapper around 0.9 +plugins that adapts the changed plugin api calls. However, plugins +that access nose internals are likely to fail, especially if they +attempt to access test case or test suite classes. For example, +plugins that try to determine if a test passed to startTest is an +individual test or a suite will fail, partly because suites are no +longer passed to startTest and partly because it\(aqs likely that the +plugin is trying to find out if the test is an instance of a class +that no longer exists. +.SS 0.10 and 0.11 plugins +.sp +All plugins written for nose 0.10 and 0.11 should work with nose 1.0. +.SS Options +.INDENT 0.0 +.TP +.B \-V, \-\-version +Output nose version and exit +.UNINDENT +.INDENT 0.0 +.TP +.B \-p, \-\-plugins +Output list of available plugins and exit. Combine with higher verbosity for greater detail +.UNINDENT +.INDENT 0.0 +.TP +.B \-v=DEFAULT, \-\-verbose=DEFAULT +Be more verbose. [NOSE_VERBOSE] +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-verbosity=VERBOSITY +Set verbosity; \-\-verbosity=2 is the same as \-v +.UNINDENT +.INDENT 0.0 +.TP +.B \-q=DEFAULT, \-\-quiet=DEFAULT +Be less verbose +.UNINDENT +.INDENT 0.0 +.TP +.B \-c=FILES, \-\-config=FILES +Load configuration from config file(s). May be specified multiple times; in that case, all config files will be loaded and combined +.UNINDENT +.INDENT 0.0 +.TP +.B \-w=WHERE, \-\-where=WHERE +Look for tests in this directory. May be specified multiple times. The first directory passed will be used as the working directory, in place of the current working directory, which is the default. Others will be added to the list of tests to execute. [NOSE_WHERE] +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-py3where=PY3WHERE +Look for tests in this directory under Python 3.x. Functions the same as \(aqwhere\(aq, but only applies if running under Python 3.x or above. Note that, if present under 3.x, this option completely replaces any directories specified with \(aqwhere\(aq, so the \(aqwhere\(aq option becomes ineffective. [NOSE_PY3WHERE] +.UNINDENT +.INDENT 0.0 +.TP +.B \-m=REGEX, \-\-match=REGEX, \-\-testmatch=REGEX +Files, directories, function names, and class names that match this regular expression are considered tests. Default: (?:^|[b_./\-])[Tt]est [NOSE_TESTMATCH] +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-tests=NAMES +Run these tests (comma\-separated list). This argument is useful mainly from configuration files; on the command line, just pass the tests to run as additional arguments with no switch. +.UNINDENT +.INDENT 0.0 +.TP +.B \-l=DEFAULT, \-\-debug=DEFAULT +Activate debug logging for one or more systems. Available debug loggers: nose, nose.importer, nose.inspector, nose.plugins, nose.result and nose.selector. Separate multiple names with a comma. +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-debug\-log=FILE +Log debug messages to this file (default: sys.stderr) +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-logging\-config=FILE, \-\-log\-config=FILE +Load logging config from this file \-\- bypasses all other logging config settings. +.UNINDENT +.INDENT 0.0 +.TP +.B \-I=REGEX, \-\-ignore\-files=REGEX +Completely ignore any file that matches this regular expression. Takes precedence over any other settings or plugins. Specifying this option will replace the default setting. Specify this option multiple times to add more regular expressions [NOSE_IGNORE_FILES] +.UNINDENT +.INDENT 0.0 +.TP +.B \-e=REGEX, \-\-exclude=REGEX +Don\(aqt run tests that match regular expression [NOSE_EXCLUDE] +.UNINDENT +.INDENT 0.0 +.TP +.B \-i=REGEX, \-\-include=REGEX +This regular expression will be applied to files, directories, function names, and class names for a chance to include additional tests that do not match TESTMATCH. Specify this option multiple times to add more regular expressions [NOSE_INCLUDE] +.UNINDENT +.INDENT 0.0 +.TP +.B \-x, \-\-stop +Stop running tests after the first error or failure +.UNINDENT +.INDENT 0.0 +.TP +.B \-P, \-\-no\-path\-adjustment +Don\(aqt make any changes to sys.path when loading tests [NOSE_NOPATH] +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-exe +Look for tests in python modules that are executable. Normal behavior is to exclude executable modules, since they may not be import\-safe [NOSE_INCLUDE_EXE] +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-noexe +DO NOT look for tests in python modules that are executable. (The default on the windows platform is to do so.) +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-traverse\-namespace +Traverse through all path entries of a namespace package +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-first\-package\-wins, \-\-first\-pkg\-wins, \-\-1st\-pkg\-wins +nose\(aqs importer will normally evict a package from sys.modules if it sees a package with the same name in a different location. Set this option to disable that behavior. +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-no\-byte\-compile +Prevent nose from byte\-compiling the source into .pyc files while nose is scanning for and running tests. +.UNINDENT +.INDENT 0.0 +.TP +.B \-a=ATTR, \-\-attr=ATTR +Run only tests that have attributes specified by ATTR [NOSE_ATTR] +.UNINDENT +.INDENT 0.0 +.TP +.B \-A=EXPR, \-\-eval\-attr=EXPR +Run only tests for whose attributes the Python expression EXPR evaluates to True [NOSE_EVAL_ATTR] +.UNINDENT +.INDENT 0.0 +.TP +.B \-s, \-\-nocapture +Don\(aqt capture stdout (any stdout output will be printed immediately) [NOSE_NOCAPTURE] +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-nologcapture +Disable logging capture plugin. Logging configuration will be left intact. [NOSE_NOLOGCAPTURE] +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-logging\-format=FORMAT +Specify custom format to print statements. Uses the same format as used by standard logging handlers. [NOSE_LOGFORMAT] +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-logging\-datefmt=FORMAT +Specify custom date/time format to print statements. Uses the same format as used by standard logging handlers. [NOSE_LOGDATEFMT] +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-logging\-filter=FILTER +Specify which statements to filter in/out. By default, everything is captured. If the output is too verbose, +use this option to filter out needless output. +Example: filter=foo will capture statements issued ONLY to + foo or foo.what.ever.sub but not foobar or other logger. +Specify multiple loggers with comma: filter=foo,bar,baz. +If any logger name is prefixed with a minus, eg filter=\-foo, +it will be excluded rather than included. Default: exclude logging messages from nose itself (\-nose). [NOSE_LOGFILTER] +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-logging\-clear\-handlers +Clear all other logging handlers +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-logging\-level=DEFAULT +Set the log level to capture +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-with\-coverage +Enable plugin Coverage: +Activate a coverage report using Ned Batchelder\(aqs coverage module. + [NOSE_WITH_COVERAGE] +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-cover\-package=PACKAGE +Restrict coverage output to selected packages [NOSE_COVER_PACKAGE] +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-cover\-erase +Erase previously collected coverage statistics before run +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-cover\-tests +Include test modules in coverage report [NOSE_COVER_TESTS] +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-cover\-min\-percentage=DEFAULT +Minimum percentage of coverage for tests to pass [NOSE_COVER_MIN_PERCENTAGE] +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-cover\-inclusive +Include all python files under working directory in coverage report. Useful for discovering holes in test coverage if not all files are imported by the test suite. [NOSE_COVER_INCLUSIVE] +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-cover\-html +Produce HTML coverage information +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-cover\-html\-dir=DIR +Produce HTML coverage information in dir +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-cover\-branches +Include branch coverage in coverage report [NOSE_COVER_BRANCHES] +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-cover\-xml +Produce XML coverage information +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-cover\-xml\-file=FILE +Produce XML coverage information in file +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-pdb +Drop into debugger on failures or errors +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-pdb\-failures +Drop into debugger on failures +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-pdb\-errors +Drop into debugger on errors +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-no\-deprecated +Disable special handling of DeprecatedTest exceptions. +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-with\-doctest +Enable plugin Doctest: +Activate doctest plugin to find and run doctests in non\-test modules. + [NOSE_WITH_DOCTEST] +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-doctest\-tests +Also look for doctests in test modules. Note that classes, methods and functions should have either doctests or non\-doctest tests, not both. [NOSE_DOCTEST_TESTS] +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-doctest\-extension=EXT +Also look for doctests in files with this extension [NOSE_DOCTEST_EXTENSION] +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-doctest\-result\-variable=VAR +Change the variable name set to the result of the last interpreter command from the default \(aq_\(aq. Can be used to avoid conflicts with the _() function used for text translation. [NOSE_DOCTEST_RESULT_VAR] +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-doctest\-fixtures=SUFFIX +Find fixtures for a doctest file in module with this name appended to the base name of the doctest file +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-doctest\-options=OPTIONS +Specify options to pass to doctest. Eg. \(aq+ELLIPSIS,+NORMALIZE_WHITESPACE\(aq +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-with\-isolation +Enable plugin IsolationPlugin: +Activate the isolation plugin to isolate changes to external +modules to a single test module or package. The isolation plugin +resets the contents of sys.modules after each test module or +package runs to its state before the test. PLEASE NOTE that this +plugin should not be used with the coverage plugin, or in any other case +where module reloading may produce undesirable side\-effects. + [NOSE_WITH_ISOLATION] +.UNINDENT +.INDENT 0.0 +.TP +.B \-d, \-\-detailed\-errors, \-\-failure\-detail +Add detail to error output by attempting to evaluate failed asserts [NOSE_DETAILED_ERRORS] +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-with\-profile +Enable plugin Profile: +Use this plugin to run tests using the hotshot profiler. + [NOSE_WITH_PROFILE] +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-profile\-sort=SORT +Set sort order for profiler output +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-profile\-stats\-file=FILE +Profiler stats file; default is a new temp file on each run +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-profile\-restrict=RESTRICT +Restrict profiler output. See help for pstats.Stats for details +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-no\-skip +Disable special handling of SkipTest exceptions. +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-with\-id +Enable plugin TestId: +Activate to add a test id (like #1) to each test name output. Activate +with \-\-failed to rerun failing tests only. + [NOSE_WITH_ID] +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-id\-file=FILE +Store test ids found in test runs in this file. Default is the file .noseids in the working directory. +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-failed +Run the tests that failed in the last test run. +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-processes=NUM +Spread test run among this many processes. Set a number equal to the number of processors or cores in your machine for best results. Pass a negative number to have the number of processes automatically set to the number of cores. Passing 0 means to disable parallel testing. Default is 0 unless NOSE_PROCESSES is set. [NOSE_PROCESSES] +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-process\-timeout=SECONDS +Set timeout for return of results from each test runner process. Default is 10. [NOSE_PROCESS_TIMEOUT] +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-process\-restartworker +If set, will restart each worker process once their tests are done, this helps control memory leaks from killing the system. [NOSE_PROCESS_RESTARTWORKER] +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-with\-xunit +Enable plugin Xunit: This plugin provides test results in the standard XUnit XML format. [NOSE_WITH_XUNIT] +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-xunit\-file=FILE +Path to xml file to store the xunit report in. Default is nosetests.xml in the working directory [NOSE_XUNIT_FILE] +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-xunit\-testsuite\-name=PACKAGE +Name of the testsuite in the xunit xml, generated by plugin. Default test suite name is nosetests. +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-all\-modules +Enable plugin AllModules: Collect tests from all python modules. + [NOSE_ALL_MODULES] +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-collect\-only +Enable collect\-only: +Collect and output test names only, don\(aqt run any tests. + [COLLECT_ONLY] +.UNINDENT +.SH AUTHOR +Nose developers +.SH COPYRIGHT +2009, Jason Pellerin +.\" Generated by docutils manpage writer. +. diff --git a/rabbitpy/message.py b/rabbitpy/message.py index 2eea572..a58e2d8 100644 --- a/rabbitpy/message.py +++ b/rabbitpy/message.py @@ -15,7 +15,7 @@ from pamqp import body from pamqp import header -from pamqp import specification +from pamqp import commands from rabbitpy import base from rabbitpy import exceptions @@ -34,8 +34,8 @@ class memoryview(object): pass -class Properties(specification.Basic.Properties): - """Proxy class for :py:class:`pamqp.specification.Basic.Properties`""" +class Properties(commands.Basic.Properties): + """Proxy class for :py:class:`pamqp.commands.Basic.Properties`""" pass @@ -184,7 +184,7 @@ def ack(self, all_previous=False): if not self.method: raise exceptions.ActionException('Can not ack non-received ' 'message') - basic_ack = specification.Basic.Ack(self.method.delivery_tag, + basic_ack = commands.Basic.Ack(self.method.delivery_tag, multiple=all_previous) self.channel.write_frame(basic_ack) @@ -212,7 +212,7 @@ def nack(self, requeue=False, all_previous=False): if not self.method: raise exceptions.ActionException('Can not nack non-received ' 'message') - basic_nack = specification.Basic.Nack(self.method.delivery_tag, + basic_nack = commands.Basic.Nack(self.method.delivery_tag, requeue=requeue, multiple=all_previous) self.channel.write_frame(basic_nack) @@ -261,7 +261,7 @@ def publish(self, exchange, routing_key='', mandatory=False, # Coerce the body to the proper type payload = utils.maybe_utf8_encode(self.body) - frames = [specification.Basic.Publish(exchange=exchange, + frames = [commands.Basic.Publish(exchange=exchange, routing_key=routing_key or '', mandatory=mandatory, immediate=immediate), @@ -286,9 +286,9 @@ def publish(self, exchange, routing_key='', mandatory=False, # If publisher confirmations are enabled, wait for the response if self.channel.publisher_confirms: response = self.channel.wait_for_confirmation() - if isinstance(response, specification.Basic.Ack): + if isinstance(response, commands.Basic.Ack): return True - elif isinstance(response, specification.Basic.Nack): + elif isinstance(response, commands.Basic.Nack): return False else: raise exceptions.UnexpectedResponseError(response) @@ -304,7 +304,7 @@ def reject(self, requeue=False): if not self.method: raise exceptions.ActionException('Can not reject non-received ' 'message') - basic_reject = specification.Basic.Reject(self.method.delivery_tag, + basic_reject = commands.Basic.Reject(self.method.delivery_tag, requeue=requeue) self.channel.write_frame(basic_reject) @@ -365,7 +365,7 @@ def _auto_serialize(self, body_value): def _coerce_properties(self): """Force properties to be set to the correct data type""" for key, value in self.properties.items(): - _type = specification.Basic.Properties.type(key) + _type = commands.Basic.Properties.amqp_type(key) if self.properties[key] is None: continue if _type == 'shortstr': @@ -394,19 +394,19 @@ def _invalid_properties(self): """ return [key for key in self.properties - if key not in specification.Basic.Properties.attributes()] + if key not in commands.Basic.Properties.attributes()] @property def _properties(self): """Return a new Basic.Properties object representing the message properties. - :rtype: pamqp.specification.Basic.Properties + :rtype: pamqp.commands.Basic.Properties """ self._prune_invalid_properties() self._coerce_properties() - return specification.Basic.Properties(**self.properties) + return commands.Basic.Properties(**self.properties) def _prune_invalid_properties(self): """Remove invalid properties from the message properties.""" diff --git a/rabbitpy/pyvenv.cfg b/rabbitpy/pyvenv.cfg new file mode 100644 index 0000000..3a16b05 --- /dev/null +++ b/rabbitpy/pyvenv.cfg @@ -0,0 +1,8 @@ +home = /Users/galuszkak/.pyenv/versions/3.8.2 +implementation = CPython +version_info = 3.8.2.final.0 +virtualenv = 20.0.10 +include-system-site-packages = false +base-prefix = /Users/galuszkak/.pyenv/versions/3.8.2 +base-exec-prefix = /Users/galuszkak/.pyenv/versions/3.8.2 +base-executable = /Users/galuszkak/.pyenv/versions/3.8.2/bin/python3.8 diff --git a/rabbitpy/share/man/man1/ipython.1.gz b/rabbitpy/share/man/man1/ipython.1.gz new file mode 100644 index 0000000..1134f76 Binary files /dev/null and b/rabbitpy/share/man/man1/ipython.1.gz differ diff --git a/rabbitpy/tx.py b/rabbitpy/tx.py index 5b8d415..e6d812c 100644 --- a/rabbitpy/tx.py +++ b/rabbitpy/tx.py @@ -4,7 +4,7 @@ """ import logging -from pamqp import specification as spec +from pamqp import commands from rabbitpy import base from rabbitpy import exceptions @@ -68,8 +68,8 @@ def select(self): :rtype: bool """ - response = self._rpc(spec.Tx.Select()) - result = isinstance(response, spec.Tx.SelectOk) + response = self._rpc(commands.Tx.Select()) + result = isinstance(response, commands.Tx.SelectOk) self._selected = result return result @@ -85,12 +85,12 @@ def commit(self): """ try: - response = self._rpc(spec.Tx.Commit()) + response = self._rpc(commands.Tx.Commit()) except exceptions.ChannelClosedException as error: LOGGER.warning('Error committing transaction: %s', error) raise exceptions.NoActiveTransactionError() self._selected = False - return isinstance(response, spec.Tx.CommitOk) + return isinstance(response, commands.Tx.CommitOk) def rollback(self): """Abandon the current transaction @@ -106,9 +106,9 @@ def rollback(self): """ try: - response = self._rpc(spec.Tx.Rollback()) + response = self._rpc(commands.Tx.Rollback()) except exceptions.ChannelClosedException as error: LOGGER.warning('Error rolling back transaction: %s', error) raise exceptions.NoActiveTransactionError() self._selected = False - return isinstance(response, spec.Tx.RollbackOk) + return isinstance(response, commands.Tx.RollbackOk) diff --git a/rabbitpy/utils.py b/rabbitpy/utils.py index 5187348..d18e5c8 100644 --- a/rabbitpy/utils.py +++ b/rabbitpy/utils.py @@ -4,20 +4,10 @@ """ import collections -# pylint: disable=unused-import,import-error -try: - import Queue as queue -except ImportError: - import queue +import queue import platform import socket -# pylint: disable=import-error -try: - from urllib import parse as _urlparse -except ImportError: - import urlparse as _urlparse - -from pamqp import PYTHON3 +from urllib import parse as _urlparse PYPY = platform.python_implementation() == 'PyPy' @@ -34,12 +24,8 @@ def maybe_utf8_encode(value): """ - if PYTHON3: - if is_string(value) and not isinstance(value, bytes): - return bytes(value, 'utf-8') - return value - if isinstance(value, unicode): # pylint: disable=undefined-variable - return value.encode('utf-8') + if is_string(value) and not isinstance(value, bytes): + return bytes(value, 'utf-8') return value @@ -86,9 +72,6 @@ def is_string(value): """ checks = [isinstance(value, bytes), isinstance(value, str)] - if not PYTHON3: - # pylint: disable=undefined-variable - checks.append(isinstance(value, unicode)) return any(checks) diff --git a/requirements.txt b/requirements.txt index 3fccece..75741a1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1 @@ -pamqp>=2.3.0,<3.0 +pamqp>=3.0,<4.0 diff --git a/setup.py b/setup.py index 43c2f6d..e6dbaaf 100644 --- a/setup.py +++ b/setup.py @@ -7,14 +7,10 @@ 'Intended Audience :: Developers', 'License :: OSI Approved :: BSD License', 'Operating System :: OS Independent', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.3', - 'Programming Language :: Python :: 3.4', - 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: Implementation :: CPython', 'Programming Language :: Python :: Implementation :: PyPy', 'Topic :: Communications', @@ -31,7 +27,7 @@ packages=['rabbitpy'], package_data={'': ['LICENSE', 'README.md']}, include_package_data=True, - install_requires=['pamqp>=2,<3'], + install_requires=['pamqp>=3,<4'], license='BSD', classifiers=classifiers, zip_safe=True) diff --git a/test-requirements.txt b/test-requirements.txt index d2f01db..f0a7228 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -10,5 +10,6 @@ flake8-import-order flake8-quotes flake8-rst-docstrings flake8-tuple +pylint codeclimate-test-reporter -r requirements.txt \ No newline at end of file diff --git a/tests/base_tests.py b/tests/base_tests.py index 7b21ec5..49549c4 100644 --- a/tests/base_tests.py +++ b/tests/base_tests.py @@ -24,11 +24,6 @@ def test_name_str(self): obj = base.AMQPClass(self.channel, 'Foo') self.assertIsInstance(obj.name, str) - @helpers.unittest.skipIf(utils.PYTHON3, 'No unicode in Python 3') - def test_name_unicode(self): - obj = base.AMQPClass(self.channel, unicode('Foo')) - self.assertIsInstance(obj.name, unicode) - def test_name_value(self): obj = base.AMQPClass(self.channel, 'Foo') self.assertEqual(obj.name, 'Foo') diff --git a/tests/events_tests.py b/tests/events_tests.py index 75580cf..db4eca4 100644 --- a/tests/events_tests.py +++ b/tests/events_tests.py @@ -4,10 +4,7 @@ """ import mock import threading -try: - import unittest2 as unittest -except ImportError: - import unittest +import unittest from rabbitpy import events diff --git a/tests/exchange_tests.py b/tests/exchange_tests.py index c6f951a..7ea7fee 100644 --- a/tests/exchange_tests.py +++ b/tests/exchange_tests.py @@ -3,7 +3,7 @@ """ import mock -from pamqp import specification +from pamqp import commands from rabbitpy import exchange @@ -14,55 +14,55 @@ class TxTests(helpers.TestCase): @mock.patch('rabbitpy.exchange.Exchange._rpc') def test_bind_sends_exchange_declare(self, rpc): - rpc.return_value = specification.Exchange.DeclareOk + rpc.return_value = commands.Exchange.DeclareOk obj = exchange.Exchange(self.channel, 'foo') obj.declare() self.assertIsInstance(rpc.mock_calls[0][1][0], - specification.Exchange.Declare) + commands.Exchange.Declare) @mock.patch('rabbitpy.exchange.Exchange._rpc') def test_bind_sends_exchange_delete(self, rpc): - rpc.return_value = specification.Exchange.DeleteOk + rpc.return_value = commands.Exchange.DeleteOk obj = exchange.Exchange(self.channel, 'foo') obj.delete() self.assertIsInstance(rpc.mock_calls[0][1][0], - specification.Exchange.Delete) + commands.Exchange.Delete) @mock.patch('rabbitpy.exchange.Exchange._rpc') def test_bind_sends_exchange_bind(self, rpc): - rpc.return_value = specification.Exchange.BindOk + rpc.return_value = commands.Exchange.BindOk obj = exchange.Exchange(self.channel, 'foo') obj.bind('a', 'b') self.assertIsInstance(rpc.mock_calls[0][1][0], - specification.Exchange.Bind) + commands.Exchange.Bind) @mock.patch('rabbitpy.exchange.Exchange._rpc') def test_bind_sends_exchange_unbind(self, rpc): - rpc.return_value = specification.Exchange.UnbindOk + rpc.return_value = commands.Exchange.UnbindOk obj = exchange.Exchange(self.channel, 'foo') obj.unbind('a', 'b') self.assertIsInstance(rpc.mock_calls[0][1][0], - specification.Exchange.Unbind) + commands.Exchange.Unbind) @mock.patch('rabbitpy.exchange.Exchange._rpc') def test_bind_sends_exchange_bind_obj(self, rpc): - rpc.return_value = specification.Exchange.BindOk + rpc.return_value = commands.Exchange.BindOk obj = exchange.Exchange(self.channel, 'foo') val = mock.Mock() val.name = 'bar' obj.bind(val, 'b') self.assertIsInstance(rpc.mock_calls[0][1][0], - specification.Exchange.Bind) + commands.Exchange.Bind) @mock.patch('rabbitpy.exchange.Exchange._rpc') def test_bind_sends_exchange_unbind_obj(self, rpc): - rpc.return_value = specification.Exchange.UnbindOk + rpc.return_value = commands.Exchange.UnbindOk obj = exchange.Exchange(self.channel, 'foo') val = mock.Mock() val.name = 'bar' obj.unbind(val, 'b') self.assertIsInstance(rpc.mock_calls[0][1][0], - specification.Exchange.Unbind) + commands.Exchange.Unbind) class DirectExchangeCreationTests(helpers.TestCase): diff --git a/tests/helpers.py b/tests/helpers.py index 64909ed..9215029 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -1,7 +1,4 @@ -try: - import unittest2 as unittest -except ImportError: - import unittest +import unittest import mock diff --git a/tests/integration_tests.py b/tests/integration_tests.py index b102a3b..a040426 100644 --- a/tests/integration_tests.py +++ b/tests/integration_tests.py @@ -3,14 +3,8 @@ import os import threading import time -try: - import unittest2 as unittest -except ImportError: - import unittest -try: - from urllib import parse -except ImportError: - import urlparse as parse +import unittest +from urllib import parse import uuid import rabbitpy @@ -251,7 +245,6 @@ def setUp(self): self.app_id = 'PublishAndConsumeIteratorTest' self.message_body = b'ABC1234567890' self.message_type = 'test' - self.msg = rabbitpy.Message(self.channel, self.message_body, {'app_id': self.app_id, diff --git a/tests/message_tests.py b/tests/message_tests.py index d4c1c6e..110ae23 100644 --- a/tests/message_tests.py +++ b/tests/message_tests.py @@ -12,7 +12,7 @@ import mock from pamqp import body from pamqp import header -from pamqp import specification +from pamqp import commands from rabbitpy import channel from rabbitpy import exceptions @@ -205,7 +205,7 @@ class TestDeliveredMessageObject(helpers.TestCase): def setUp(self): super(TestDeliveredMessageObject, self).setUp() - self.method = specification.Basic.Deliver(self.CONSUMER_TAG, + self.method = commands.Basic.Deliver(self.CONSUMER_TAG, self.DELIVERY_TAG, self.REDELIVERED, self.EXCHANGE, @@ -238,7 +238,7 @@ def test_ack_channel_write_frame_type(self): with mock.patch('rabbitpy.channel.Channel.write_frame') as wframe: self.msg.ack() frame_value = wframe.mock_calls[0][1][0] - self.assertIsInstance(frame_value, specification.Basic.Ack) + self.assertIsInstance(frame_value, commands.Basic.Ack) def test_ack_channel_write_frame_delivery_tag_value(self): with mock.patch('rabbitpy.channel.Channel.write_frame') as wframe: @@ -268,7 +268,7 @@ def test_nack_channel_write_frame_type(self): with mock.patch('rabbitpy.channel.Channel.write_frame') as wframe: self.msg.nack() frame_value = wframe.mock_calls[0][1][0] - self.assertIsInstance(frame_value, specification.Basic.Nack) + self.assertIsInstance(frame_value, commands.Basic.Nack) def test_nack_channel_write_frame_delivery_tag_value(self): with mock.patch('rabbitpy.channel.Channel.write_frame') as wframe: @@ -310,7 +310,7 @@ def test_reject_channel_write_frame_type(self): with mock.patch('rabbitpy.channel.Channel.write_frame') as wframe: self.msg.reject() frame_value = wframe.mock_calls[0][1][0] - self.assertIsInstance(frame_value, specification.Basic.Reject) + self.assertIsInstance(frame_value, commands.Basic.Reject) def test_reject_channel_write_frame_delivery_tag_value(self): with mock.patch('rabbitpy.channel.Channel.write_frame') as wframe: @@ -396,7 +396,7 @@ def setUp(self, write_frames): def test_publish_invokes_write_frame_with_basic_publish(self): self.assertIsInstance(self.write_frames.mock_calls[0][1][0][0], - specification.Basic.Publish) + commands.Basic.Publish) def test_publish_with_exchange_object(self): _exchange = exchange.Exchange(self.channel, self.EXCHANGE) @@ -493,14 +493,14 @@ def setUp(self, write_frames): self.msg = message.Message(self.channel, self.BODY) def test_confirm_ack_response_returns_true(self): - self._confirm_wait.return_value = specification.Basic.Ack() + self._confirm_wait.return_value = commands.Basic.Ack() self.assertTrue(self.msg.publish(self.EXCHANGE, self.ROUTING_KEY)) def test_confirm_nack_response_returns_false(self): - self._confirm_wait.return_value = specification.Basic.Nack() + self._confirm_wait.return_value = commands.Basic.Nack() self.assertFalse(self.msg.publish(self.EXCHANGE, self.ROUTING_KEY)) def test_confirm_other_raises(self): - self._confirm_wait.return_value = specification.Basic.Consume() + self._confirm_wait.return_value = commands.Basic.Consume() self.assertRaises(exceptions.UnexpectedResponseError, self.msg.publish, self.EXCHANGE, self.ROUTING_KEY) diff --git a/tests/queue_tests.py b/tests/queue_tests.py index d700985..94d0870 100644 --- a/tests/queue_tests.py +++ b/tests/queue_tests.py @@ -3,7 +3,7 @@ """ import mock -from pamqp import specification +from pamqp import commands from rabbitpy import amqp_queue from rabbitpy import channel @@ -141,12 +141,6 @@ def test_dlx_str(self): queue = amqp_queue.Queue(self.channel, dead_letter_exchange='dlx-name') self.assertIsInstance(queue.dead_letter_exchange, str) - @helpers.unittest.skipIf(utils.PYTHON3, 'No unicode in Python 3') - def test_dlx_unicode(self): - queue = amqp_queue.Queue(self.channel, - dead_letter_exchange=unicode('dlx-name')) - self.assertIsInstance(queue.dead_letter_exchange, unicode) - def test_message_dlx_validation(self): self.assertRaises(ValueError, amqp_queue.Queue, self.channel, '', True, False, True, None, None, None, True) @@ -170,13 +164,6 @@ def test_dlr_str(self): dead_letter_routing_key='routing-key') self.assertIsInstance(queue.dead_letter_routing_key, str) - @helpers.unittest.skipIf(utils.PYTHON3, 'No unicode in Python 3') - def test_dlr_unicode(self): - routing_key = unicode('routing-key') - queue = amqp_queue.Queue(self.channel, - dead_letter_routing_key=routing_key) - self.assertIsInstance(queue.dead_letter_routing_key, unicode) - def test_dlr_validation(self): self.assertRaises(ValueError, amqp_queue.Queue, self.channel, '', True, False, True, None, None, None, None, True) @@ -367,19 +354,19 @@ def setUp(self): def test_declare_invokes_write_frame_with_queue_declare(self, rpc): self.queue.declare() self.assertIsInstance(rpc.mock_calls[0][1][0], - specification.Queue.Declare) + commands.Queue.Declare) @mock.patch('rabbitpy.amqp_queue.Queue._rpc') def test_ha_declare_invokes_write_frame_with_queue_declare(self, rpc): self.queue.ha_declare() self.assertIsInstance(rpc.mock_calls[0][1][0], - specification.Queue.Declare) + commands.Queue.Declare) @mock.patch('rabbitpy.amqp_queue.Queue._rpc') def test_ha_declare_list_invokes_write_frame_with_queue_declare(self, rpc): self.queue.ha_declare(['foo', 'bar']) self.assertIsInstance(rpc.mock_calls[0][1][0], - specification.Queue.Declare) + commands.Queue.Declare) @mock.patch('rabbitpy.amqp_queue.Queue._rpc') def test_ha_declare_list_sets_proper_attributes(self, rpc): @@ -399,13 +386,13 @@ def test_ha_declare_list_invokes_write_frame_with_queue_declare(self, rpc): def test_bind_invokes_write_frame_with_queue_bind(self, rpc): self.queue.bind('foo', 'bar') self.assertIsInstance(rpc.mock_calls[0][1][0], - specification.Queue.Bind) + commands.Queue.Bind) @mock.patch('rabbitpy.amqp_queue.Queue._rpc') def test_unbind_invokes_write_frame_with_queue_declare(self, rpc): self.queue.unbind('foo', 'bar') self.assertIsInstance(rpc.mock_calls[0][1][0], - specification.Queue.Unbind) + commands.Queue.Unbind) @mock.patch('rabbitpy.amqp_queue.Queue._rpc') def test_unbind_with_obj_invokes_write_frame_with_queue_declare(self, rpc): @@ -413,17 +400,17 @@ def test_unbind_with_obj_invokes_write_frame_with_queue_declare(self, rpc): exchange.name = 'foo' self.queue.unbind(exchange, 'bar') self.assertIsInstance(rpc.mock_calls[0][1][0], - specification.Queue.Unbind) + commands.Queue.Unbind) @mock.patch('rabbitpy.amqp_queue.Queue._rpc') def test_unbind_invokes_write_frame_with_queue_delete(self, rpc): self.queue.delete() self.assertIsInstance(rpc.mock_calls[0][1][0], - specification.Queue.Delete) + commands.Queue.Delete) @mock.patch('rabbitpy.amqp_queue.Queue._rpc') def test_purge_invokes_write_frame_with_queue_purge(self, rpc): self.queue.purge() self.assertIsInstance(rpc.mock_calls[0][1][0], - specification.Queue.Purge) + commands.Queue.Purge) diff --git a/tests/tx_tests.py b/tests/tx_tests.py index c092e1b..89268de 100644 --- a/tests/tx_tests.py +++ b/tests/tx_tests.py @@ -3,7 +3,7 @@ """ import mock -from pamqp import specification +from pamqp import commands from rabbitpy import exceptions, tx @@ -25,7 +25,7 @@ def test_enter_invokes_select(self): @mock.patch('rabbitpy.tx.Tx._rpc') def test_exit_invokes_commit(self, rpc): - rpc.return_value = specification.Tx.SelectOk + rpc.return_value = commands.Tx.SelectOk with mock.patch('rabbitpy.tx.Tx.select') as select: with mock.patch('rabbitpy.tx.Tx.commit') as commit: with tx.Tx(self.channel) as transaction: @@ -34,7 +34,7 @@ def test_exit_invokes_commit(self, rpc): @mock.patch('rabbitpy.tx.Tx._rpc') def test_exit_on_exception_invokes_commit_with_selected(self, rpc): - rpc.return_value = specification.Tx.SelectOk + rpc.return_value = commands.Tx.SelectOk with mock.patch('rabbitpy.tx.Tx.select') as select: with mock.patch('rabbitpy.tx.Tx.rollback') as rollback: try: @@ -47,21 +47,21 @@ def test_exit_on_exception_invokes_commit_with_selected(self, rpc): @mock.patch('rabbitpy.tx.Tx._rpc') def test_select_invokes_rpc_with_tx_select(self, rpc): - rpc.return_value = specification.Tx.CommitOk + rpc.return_value = commands.Tx.CommitOk with tx.Tx(self.channel): pass self.assertIsInstance(rpc.mock_calls[0][1][0], - specification.Tx.Select) + commands.Tx.Select) @mock.patch('rabbitpy.tx.Tx._rpc') def test_commit_invokes_rpc_with_tx_commit(self, rpc): - rpc.return_value = specification.Tx.SelectOk + rpc.return_value = commands.Tx.SelectOk obj = tx.Tx(self.channel) obj.select() - rpc.return_value = specification.Tx.CommitOk + rpc.return_value = commands.Tx.CommitOk obj.commit() self.assertIsInstance(rpc.mock_calls[1][1][0], - specification.Tx.Commit) + commands.Tx.Commit) @mock.patch('rabbitpy.tx.Tx._rpc') def test_commit_raises_when_channel_closed(self, rpc): @@ -73,13 +73,13 @@ def test_commit_raises_when_channel_closed(self, rpc): @mock.patch('rabbitpy.tx.Tx._rpc') def test_rollback_invokes_rpc_with_tx_rollback(self, rpc): - rpc.return_value = specification.Tx.SelectOk + rpc.return_value = commands.Tx.SelectOk obj = tx.Tx(self.channel) obj.select() - rpc.return_value = specification.Tx.RollbackOk + rpc.return_value = commands.Tx.RollbackOk obj.rollback() self.assertIsInstance(rpc.mock_calls[1][1][0], - specification.Tx.Rollback) + commands.Tx.Rollback) @mock.patch('rabbitpy.tx.Tx._rpc') def test_rollback_raises_when_channel_closed(self, rpc): diff --git a/tests/utils_tests.py b/tests/utils_tests.py index 6aacc4f..ca35d06 100644 --- a/tests/utils_tests.py +++ b/tests/utils_tests.py @@ -2,10 +2,7 @@ Test the rabbitpy utils module """ -try: - import unittest2 as unittest -except ImportError: - import unittest +import unittest import sys from rabbitpy import utils @@ -56,10 +53,6 @@ def test_is_string_str(self): def test_is_string_bytes(self): self.assertTrue(utils.is_string(b'Foo')) - @unittest.skipIf(sys.version_info[0] == 3, 'No unicode obj in 3') - def test_is_string_unicode(self): - self.assertTrue(utils.is_string(unicode('Foo'))) - def test_is_string_false_int(self): self.assertFalse(utils.is_string(123)) diff --git a/tox.ini b/tox.ini index 6c5f3db..030f23c 100644 --- a/tox.ini +++ b/tox.ini @@ -1,9 +1,6 @@ [tox] indexserver = default = https://pypi.python.org/simple -envlist = py26,py27,py32,py33,py34 +envlist = py36,py37,py38 deps = -rrequirements.txt -commands=nosetests - -[tox:py26] -deps = unittest2 \ No newline at end of file +commands=nosetests \ No newline at end of file