Skip to content

Commit

Permalink
Documentation updates
Browse files Browse the repository at this point in the history
Noting that haigha is a python3 compatible library
haigha 0.5.2 release
  • Loading branch information
awestendorf committed May 16, 2012
1 parent edb4801 commit 228b98d
Show file tree
Hide file tree
Showing 8 changed files with 95 additions and 39 deletions.
8 changes: 6 additions & 2 deletions CHANGELOG
@@ -1,5 +1,5 @@
rabbitmq-extensions
===================
0.5.2
=====

Added haigha.connections.RabbitConnection to support RabbitMQ-specific
features. This includes `auto_delete` and `internal` parameters to
Expand All @@ -10,6 +10,10 @@ http://www.rabbitmq.com/blog/2011/02/10/introducing-publisher-confirms/

Removed `auto_delete` and `internal` parameters from common exchange.declare

Default transport is now the SocketTransport. This is unlikely to change again.

Implemented PEP 396.


0.5.1
=====
Expand Down
48 changes: 47 additions & 1 deletion DOCUMENTATION.rst
Expand Up @@ -2,7 +2,7 @@
Haigha
======

:Version: 0.4.5
:Version: 0.5.2
:Download: http://pypi.python.org/pypi/haigha
:Source: https://github.com/agoragames/haigha

Expand Down Expand Up @@ -296,6 +296,52 @@ Client Functional Specification

**TODO** Document other features that the client implements.

Connections
-----------

Any application must of course first connect to a broker. The `Connection`_ class implements 3 methods that any developer will need to be aware of to use the majority of its features.

* ``__init__`` Connection constructor, also establishes the socket connection
* ``channel`` Creates or fetches a `Channel`_
* ``read_frames`` Read any pending frames, process them and write frames that result from the processing

In addition, as of version 0.5.2, haigha supports the extensions exposed by RabbitMQ in the ``haigha.connections.RabbitConnection`` class. The interface is identical to the `Connection`_ class but its channels expose additional methods to match RabbitMQ's protocol. Briefly, these extensions are:

* ``exchange.declare`` Accepts ``auto_delete`` and ``internal`` keyword arguments
* ``exchange.bind`` Supports exchange to exchange bindings
* ``exchange.unbind`` To remove an exchange to exchange binding
* ``basic.set_ack_listener`` Local method to set a callback on publisher confirm ack
* ``basic.set_nack_listener`` Local method to set a callback on publisher confirm nack
* ``basic.publish`` Returns the message id when publisher confirms are enabled
* ``basic.nack`` Send a nack to the broker when rejecting a message
* ``confirm.select`` Enable publisher confirms


__init__
*********

The constructor takes many keyword arguments that will affect its behavior.

* ``debug`` Default ``False``. If ``True``, basic logging. If 2, verbose logging of frames.
* ``logger`` Default ``logging.root``. A `logging <http://docs.python.org/library/logging.html>`_ instance.
* ``user`` Default "guest". The AMQP user to authenticate as.
* ``password`` Default "guest". The password of the AMQP user.
* ``host`` Default "localhost".
* ``port`` Default 5672.
* ``vhost`` Default "/".
* ``connect_timeout`` Default 5 seconds. Time before socket connection fails.
* ``sock_opts`` Default None. Recommend at least ``{(socket.IPPROTO_TCP, socket.TCP_NODELAY) : 1}``
* ``hearbeat`` Default None (disabled). If 0, broker assigned. If >0, negotiated with broker.
* ``open_cb`` Default None. A no-arg method to be called after connection fully negotiated and pending frames written.
* ``close_cb`` Default None. A no-arg method to be called when connection closes due to protocol handshake or transport closure.
* ``login_method`` Defaults to "AMQPLAIN".
* ``locale`` Defaults to "en_US".
* ``client_properties`` A hash of properties to send in addition to ``{ 'library' : ..., 'library_version' : ... }``
* ``class_map`` Defaults to None. Optionally override the default mapping of AMQP ``class_id`` to the haigha `ProtocolClass`_ that implements the AMQP class.
* ``transport`` Defaults to "socket". If a string, maps ["socket","gevent","gevent_pool","event"] to ``SocketTransport``, ``GeventTransport``, ``GeventPoolTransport`` or ``EventTransport`` respectively. If a ``Transport`` object, uses it directly.



Messages and Content
--------------------

Expand Down
50 changes: 27 additions & 23 deletions README.rst
Expand Up @@ -2,10 +2,10 @@
Haigha - AMQP libevent Python client
=====================================

:Version: 0.5.1
:Version: 0.5.2
:Download: http://pypi.python.org/pypi/haigha
:Source: https://github.com/agoragames/haigha
:Keywords: python, amqp, rabbitmq, event, libevent
:Keywords: python, amqp, rabbitmq, event, libevent, gevent

.. contents::
:local:
Expand All @@ -21,6 +21,8 @@ The goals of haigha are performance, simplicity, and adherence to the form and f

By default, Haigha operates in a completely asynchronous mode, relying on callbacks to notify application code of responses from the broker. Where applicable, ``nowait`` defaults to ``True``. The application code is welcome to call a series of methods, and Haigha will manage the stack and synchronous handshakes in the event loop.

Starting with the 0.5.0 series, haigha natively supports 3 transport types; libevent, gevent and standard sockets. The socket implementation defaults to synchronous mode and is useful for an interactive console or scripting, and the gevent transport is the preferred asynchronous backend though it can also be used synchronously as well.

Documentation
=============

Expand All @@ -34,43 +36,43 @@ See the ``scripts`` directory for several examples, in particular the ``stress_t

from haigha.connection import Connection
from haigha.message import Message
import event


connection = Connection(
user='guest', password='guest',
vhost='/', host='localhost',
heartbeat=None, debug=True)

def consumer(msg):
print msg
connection.close()
event.timeout( 2, event.abort )
heartbeat=None, debug=True,
transport='socket')

ch = connection.channel()
ch.exchange.declare('test_exchange', 'direct', auto_delete=True)
ch.exchange.declare('test_exchange', 'direct')
ch.queue.declare('test_queue', auto_delete=True)
ch.queue.bind('test_queue', 'test_exchange', 'test_key')
ch.basic.consume('test_queue', consumer)
ch.basic.publish( Message('body', application_headers={'hello':'world'}),
'test_exchange', 'test_key' )
print ch.basic.get('test_queue')
connection.close()

event.dispatch()
Roadmap
=======

Future
======
The 0.5 series will focus on the following areas:

The 0.3.0 series will focus on the following areas:
* RabbitMQ extensions to the protocol
* Support and bug fixes for synchronous transport
* Documentation

* Full unit test coverage
* Implementation of error response codes according to spec
* Add callback chains where they're missing
* Documentation, including doctstrings, API docs, and tutorials
* Bug fixes
Beyond that, there is no specific order of features to implement. Generally, the following areas need to be addressed.

By the 0.4.0 series the library should be feature-complete and well documented. We'll then switch our focus to libevent itself, with the goal of supporting `gevent <http://www.gevent.org/>`_, `libev <http://software.schmorp.de/pkg/libev.html>`_ and `pypy <http://pypy.org/>`_.
* Documentation (there's always more)
* Improved error handling
* Implementation of error codes in the spec
* Testing and integration with brokers other than RabbitMQ
* Flow control
* Identify and improve inefficient code
* Edge cases in frame management
* Improvements to usabililty

Haigha has been tested exclusively with Python 2.6 and 2.7, but we intend for it to work with the 3.x series as well. Please `report <http://pypi.python.org/pypi/haigha>`_ any issues you may have.
Haigha has been tested exclusively with Python 2.6 and 2.7, but we intend for it to work with the 3.x series as well. Please `report <https://github.com/agoragames/haigha/issues>`_ any issues you may have.

Installation
============
Expand All @@ -89,6 +91,8 @@ If installing from source:

pip install -r requirements.txt

Note that haigha does not install either gevent or libevent support automatically. For libevent, haigha has been tested and deployed with the ``event-agora==0.4.1`` library.


Testing
=======
Expand Down
4 changes: 2 additions & 2 deletions haigha/__init__.py
@@ -1,7 +1,7 @@
'''
Copyright (c) 2011, Agora Games, LLC All rights reserved.
Copyright (c) 2012, Agora Games, LLC All rights reserved.
https://github.com/agoragames/haigha/blob/master/LICENSE.txt
'''

VERSION = "0.5.1"
__version__ = "0.5.2"
6 changes: 3 additions & 3 deletions haigha/connection.py
Expand Up @@ -34,7 +34,7 @@
#
LIBRARY_PROPERTIES = {
'library': 'Haigha',
'library_version': haigha.VERSION,
'library_version': haigha.__version__,
}

class Connection(object):
Expand Down Expand Up @@ -105,8 +105,8 @@ def __init__(self, **kwargs):
self._frames_read = 0
self._frames_written = 0

# Default to the gevent strategy
transport = kwargs.get('transport', 'gevent')
# Default to the socket strategy
transport = kwargs.get('transport', 'socket')
if not isinstance(transport, Transport):
if transport=='event':
from haigha.transports.event_transport import EventTransport
Expand Down
9 changes: 5 additions & 4 deletions haigha/tests/unit/connection_test.py
Expand Up @@ -7,14 +7,15 @@
import logging
from chai import Chai

from haigha import connection, VERSION
from haigha import connection, __version__
from haigha.connection import Connection, ConnectionChannel
from haigha.channel import Channel
from haigha.frames import *
from haigha.classes import *

from haigha.transports import event_transport
from haigha.transports import gevent_transport
from haigha.transports import socket_transport

class ConnectionTest(Chai):

Expand Down Expand Up @@ -69,7 +70,7 @@ def test_init_without_keyword_args(self):
mock( connection, 'ConnectionChannel' )

expect(connection.ConnectionChannel).args( conn, 0, {} ).returns( 'connection_channel' )
expect(gevent_transport.GeventTransport).args( conn ).returns( 'GeventTransport' )
expect(socket_transport.SocketTransport).args( conn ).returns( 'SocketTransport' )
expect(conn.connect).args( 'localhost', 5672 )

conn.__init__()
Expand All @@ -92,7 +93,7 @@ def test_init_without_keyword_args(self):
self.assertEqual( None, conn._client_properties )
self.assertEqual( conn._properties, {
'library': 'Haigha',
'library_version': VERSION,
'library_version': __version__,
} )
self.assertFalse( conn._closed )
self.assertFalse( conn._connected )
Expand All @@ -115,7 +116,7 @@ def test_init_without_keyword_args(self):
self.assertEqual( 65535, conn._channel_max )
self.assertEqual( 65535, conn._frame_max )
self.assertEqual( [], conn._output_frame_buffer )
self.assertEqual( 'GeventTransport', conn._transport )
self.assertEqual( 'SocketTransport', conn._transport )

def test_init_with_event_transport(self):
conn = Connection.__new__( Connection )
Expand Down
5 changes: 2 additions & 3 deletions haigha/transports/gevent_transport.py
Expand Up @@ -44,11 +44,10 @@ class GeventTransport(SocketTransport):
client is attaching to other data stores so those could be enough to yield.
'''

def __init__(self, *args):
def __init__(self, *args, **kwargs):
super(GeventTransport,self).__init__(*args)

# TODO: support both modes
self._synchronous = False
self._synchronous = kwargs.get('synchronous',False)
self._read_lock = Semaphore()
self._write_lock = Semaphore()

Expand Down
4 changes: 3 additions & 1 deletion setup.py
Expand Up @@ -11,7 +11,7 @@

setup(
name='haigha',
version=haigha.VERSION,
version=haigha.__version__,
author='Vitaly Babiy, Aaron Westendorf',
author_email="vbabiy@agoragames.com, aaron@agoragames.com",
packages = ['haigha', 'haigha.frames', 'haigha.classes', 'haigha.transports'],
Expand All @@ -30,6 +30,8 @@
"Topic :: System :: Distributed Computing",
"Topic :: Software Development :: Libraries :: Python Modules",
'Programming Language :: Python',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Topic :: Software Development :: Libraries'
]
)

0 comments on commit 228b98d

Please sign in to comment.