[qpid-proton] branch master updated: PROTON-2320 Apply first round of autopep8 (whitespace changes, mostly) (#285)

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[qpid-proton] branch master updated: PROTON-2320 Apply first round of autopep8 (whitespace changes, mostly) (#285)

jdanek
This is an automated email from the ASF dual-hosted git repository.

jdanek pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/qpid-proton.git


The following commit(s) were added to refs/heads/master by this push:
     new dd05347  PROTON-2320 Apply first round of autopep8 (whitespace changes, mostly) (#285)
dd05347 is described below

commit dd0534710e83f2ead0114550a6ee6c9c5abdaf54
Author: Jiri Daněk <[hidden email]>
AuthorDate: Thu Jan 14 18:36:12 2021 +0100

    PROTON-2320 Apply first round of autopep8 (whitespace changes, mostly) (#285)
---
 c/src/encodings.h.py                         |   17 +-
 c/src/protocol.h.py                          |  109 +-
 c/src/protocol.py                            |  135 +-
 c/tests/fdlimit.py                           |    6 +-
 python/docs/conf.py                          |    6 +-
 python/examples/abstract_server.py           |    6 +-
 python/examples/client.py                    |   11 +-
 python/examples/client_http.py               |    2 +
 python/examples/colour_send.py               |    7 +-
 python/examples/db_common.py                 |    6 +-
 python/examples/db_ctrl.py                   |    5 +-
 python/examples/db_recv.py                   |    8 +-
 python/examples/db_send.py                   |   12 +-
 python/examples/direct_recv.py               |    8 +-
 python/examples/direct_send.py               |    7 +-
 python/examples/helloworld.py                |    2 +
 python/examples/helloworld_blocking.py       |    3 +-
 python/examples/helloworld_direct.py         |    2 +
 python/examples/helloworld_direct_tornado.py |    2 +
 python/examples/helloworld_tornado.py        |    2 +
 python/examples/proton_server.py             |    5 +-
 python/examples/queue_browser.py             |    8 +-
 python/examples/recurring_timer.py           |    4 +-
 python/examples/recurring_timer_tornado.py   |    4 +-
 python/examples/selected_recv.py             |    8 +-
 python/examples/server.py                    |   10 +-
 python/examples/server_direct.py             |    8 +-
 python/examples/server_tx.py                 |    8 +-
 python/examples/simple_recv.py               |    8 +-
 python/examples/simple_send.py               |    7 +-
 python/examples/sync_client.py               |    9 +-
 python/examples/test_examples.py             |   10 +-
 python/examples/tx_recv.py                   |    8 +-
 python/examples/tx_recv_interactive.py       |    9 +-
 python/examples/tx_send.py                   |    7 +-
 python/proton/_common.py                     |    1 +
 python/proton/_compat.py                     |    6 +-
 python/proton/_condition.py                  |    7 +-
 python/proton/_data.py                       |   44 +-
 python/proton/_delivery.py                   |   10 +-
 python/proton/_endpoints.py                  |   14 +-
 python/proton/_events.py                     |    6 -
 python/proton/_handlers.py                   |   14 +-
 python/proton/_io.py                         |    8 +-
 python/proton/_message.py                    |    9 +-
 python/proton/_reactor.py                    |   51 +-
 python/proton/_tracing.py                    |    8 +-
 python/proton/_transport.py                  |   35 +-
 python/proton/_url.py                        |   11 +-
 python/proton/_utils.py                      |   14 +-
 python/proton/_wrapper.py                    |    3 +-
 python/setuputils/log.py                     |   12 +-
 python/setuputils/misc.py                    |   15 +-
 python/tests/proton_tests/__main__.py        |    2 +-
 python/tests/proton_tests/codec.py           |  979 ++---
 python/tests/proton_tests/common.py          |  332 +-
 python/tests/proton_tests/connect.py         |   37 +-
 python/tests/proton_tests/engine.py          | 5196 +++++++++++++-------------
 python/tests/proton_tests/handler.py         |  196 +-
 python/tests/proton_tests/interop.py         |   24 +-
 python/tests/proton_tests/main.py            |  983 ++---
 python/tests/proton_tests/message.py         |  595 +--
 python/tests/proton_tests/reactor.py         |   19 +-
 python/tests/proton_tests/sasl.py            | 1103 +++---
 python/tests/proton_tests/soak.py            |   24 +-
 python/tests/proton_tests/ssl.py             |  371 +-
 python/tests/proton_tests/transport.py       |  719 ++--
 python/tests/proton_tests/url.py             |   16 +-
 python/tests/proton_tests/utils.py           |   24 +-
 tests/py/test_subprocess.py                  |    5 +-
 tools/python/mllib/__init__.py               |   76 +-
 tools/python/mllib/dom.py                    |  435 ++-
 tools/python/mllib/parsers.py                |  122 +-
 tools/python/mllib/transforms.py             |  216 +-
 74 files changed, 6258 insertions(+), 5953 deletions(-)

diff --git a/c/src/encodings.h.py b/c/src/encodings.h.py
index 9f08c6c..c5dd996 100644
--- a/c/src/encodings.h.py
+++ b/c/src/encodings.h.py
@@ -19,7 +19,10 @@
 #
 
 from __future__ import print_function
-import mllib, optparse, os, sys
+import mllib
+import optparse
+import os
+import sys
 
 xml = os.path.join(os.path.dirname(__file__), "types.xml")
 doc = mllib.xml_parse(xml)
@@ -31,12 +34,12 @@ print()
 print("#define PNE_DESCRIPTOR          (0x00)")
 
 for enc in doc.query["amqp/section/type/encoding"]:
-  name = enc["@name"] or enc.parent["@name"]
-  # XXX: a bit hacky
-  if name == "ieee-754":
-    name = enc.parent["@name"]
-  cname = "PNE_" + name.replace("-", "_").upper()
-  print("#define %s%s(%s)" % (cname, " "*(20-len(cname)), enc["@code"]))
+    name = enc["@name"] or enc.parent["@name"]
+    # XXX: a bit hacky
+    if name == "ieee-754":
+        name = enc.parent["@name"]
+    cname = "PNE_" + name.replace("-", "_").upper()
+    print("#define %s%s(%s)" % (cname, " "*(20-len(cname)), enc["@code"]))
 
 print()
 print("#endif /* encodings.h */")
diff --git a/c/src/protocol.h.py b/c/src/protocol.h.py
index 321cf64..7e1bed5 100644
--- a/c/src/protocol.h.py
+++ b/c/src/protocol.h.py
@@ -30,33 +30,36 @@ print("#include \"proton/type_compat.h\"")
 fields = {}
 
 for type in TYPES:
-  fidx = 0
-  for f in type.query["field"]:
-    print("#define %s_%s (%s)" % (field_kw(type), field_kw(f), fidx))
-    fidx += 1
-    d = f["@default"]
-    if d:
-        ft = ftype(f)
-        # Don't bother to emit a boolean default that is False
-        if ft=="boolean" and d=="false": continue
-        # Don't output non numerics unless symbol
-        # We should really fully resolve to actual restricted value
-        # this is really true for symbols too which accidentally work
-        if ft=="symbol": d = '"' + d + '"'
-        elif d[0] not in '0123456789': continue
-        print("#define %s_%s_DEFAULT (%s) /* %s */" % (field_kw(type), field_kw(f), d, ft))
+    fidx = 0
+    for f in type.query["field"]:
+        print("#define %s_%s (%s)" % (field_kw(type), field_kw(f), fidx))
+        fidx += 1
+        d = f["@default"]
+        if d:
+            ft = ftype(f)
+            # Don't bother to emit a boolean default that is False
+            if ft == "boolean" and d == "false":
+                continue
+            # Don't output non numerics unless symbol
+            # We should really fully resolve to actual restricted value
+            # this is really true for symbols too which accidentally work
+            if ft == "symbol":
+                d = '"' + d + '"'
+            elif d[0] not in '0123456789':
+                continue
+            print("#define %s_%s_DEFAULT (%s) /* %s */" % (field_kw(type), field_kw(f), d, ft))
 
 idx = 0
 
 for type in TYPES:
-  desc = type["descriptor"]
-  name = type["@name"].upper().replace("-", "_")
-  print("#define %s_SYM (\"%s\")" % (name, desc["@name"]))
-  hi, lo = [int(x, 0) for x in desc["@code"].split(":")]
-  code = (hi << 32) + lo
-  print("#define %s ((uint64_t) %s)" % (name, code))
-  fields[code] = (type["@name"], [f["@name"] for f in type.query["field"]])
-  idx += 1
+    desc = type["descriptor"]
+    name = type["@name"].upper().replace("-", "_")
+    print("#define %s_SYM (\"%s\")" % (name, desc["@name"]))
+    hi, lo = [int(x, 0) for x in desc["@code"].split(":")]
+    code = (hi << 32) + lo
+    print("#define %s ((uint64_t) %s)" % (name, code))
+    fields[code] = (type["@name"], [f["@name"] for f in type.query["field"]])
+    idx += 1
 
 print("""
 #include <stddef.h>
@@ -79,7 +82,7 @@ for name, fnames in fields.values():
     strings.add(name)
     strings.update(fnames)
 for str in strings:
-    istr = str.replace("-", "_");
+    istr = str.replace("-", "_")
     print('  const char FIELD_STRINGS_%s[sizeof("%s")];' % (istr, str))
 print("};")
 print()
@@ -91,7 +94,7 @@ print()
 print('const struct FIELD_STRINGS FIELD_STRINGPOOL = {')
 print('  "",')
 for str in strings:
-    print('  "%s",'% str)
+    print('  "%s",' % str)
 print("};")
 print()
 print("/* This is an array of offsets into FIELD_STRINGPOOL */")
@@ -99,11 +102,11 @@ print("const uint16_t FIELD_NAME[] = {")
 print("  offsetof(struct FIELD_STRINGS, STRING0),")
 index = 1
 for i in range(256):
-  if i in fields:
-    name, fnames = fields[i]
-    iname = name.replace("-", "_");
-    print('  offsetof(struct FIELD_STRINGS, FIELD_STRINGS_%s), /* %d */' % (iname, index))
-    index += 1
+    if i in fields:
+        name, fnames = fields[i]
+        iname = name.replace("-", "_")
+        print('  offsetof(struct FIELD_STRINGS, FIELD_STRINGS_%s), /* %d */' % (iname, index))
+        index += 1
 print("};")
 
 print("/* This is an array of offsets into FIELD_STRINGPOOL */")
@@ -111,13 +114,13 @@ print("const uint16_t FIELD_FIELDS[] = {")
 print("  offsetof(struct FIELD_STRINGS, STRING0),")
 index = 1
 for i in range(256):
-  if i in fields:
-    name, fnames = fields[i]
-    if fnames:
-      for f in fnames:
-        ifname = f.replace("-", "_");
-        print('  offsetof(struct FIELD_STRINGS, FIELD_STRINGS_%s), /* %d (%s) */' % (ifname, index, name))
-        index += 1
+    if i in fields:
+        name, fnames = fields[i]
+        if fnames:
+            for f in fnames:
+                ifname = f.replace("-", "_")
+                print('  offsetof(struct FIELD_STRINGS, FIELD_STRINGS_%s), /* %d (%s) */' % (ifname, index, name))
+                index += 1
 print("};")
 
 print("const pn_fields_t FIELDS[] = {")
@@ -127,23 +130,27 @@ field_count = 1
 field_min = 256
 field_max = 0
 for i in range(256):
-  if i in fields:
-    if i>field_max: field_max = i
-    if i<field_min: field_min = i
+    if i in fields:
+        if i > field_max:
+            field_max = i
+        if i < field_min:
+            field_min = i
 
 for i in range(field_min, field_max+1):
-  if i in fields:
-    name, fnames = fields[i]
-    if fnames:
-      print('  {%d, %d, %d}, /* %d (%s) */' % (name_count, field_count, len(fnames), i, name))
-      field_count += len(fnames)
+    if i in fields:
+        name, fnames = fields[i]
+        if fnames:
+            print('  {%d, %d, %d}, /* %d (%s) */' % (name_count, field_count, len(fnames), i, name))
+            field_count += len(fnames)
+        else:
+            print('  {%d, 0, 0}, /* %d (%s) */' % (name_count, i, name))
+        name_count += 1
+        if i > field_max:
+            field_max = i
+        if i < field_min:
+            field_min = i
     else:
-      print('  {%d, 0, 0}, /* %d (%s) */' % (name_count, i, name))
-    name_count += 1
-    if i>field_max: field_max = i
-    if i<field_min: field_min = i
-  else:
-    print('  {0, 0, 0}, /* %d */' % i)
+        print('  {0, 0, 0}, /* %d */' % i)
 
 print("};")
 print()
diff --git a/c/src/protocol.py b/c/src/protocol.py
index 3f04973..921bf0b 100644
--- a/c/src/protocol.py
+++ b/c/src/protocol.py
@@ -16,15 +16,19 @@
 # specific language governing permissions and limitations
 # under the License.
 #
-import mllib, os, sys
+import mllib
+import os
+import sys
 
 doc = mllib.xml_parse(os.path.join(os.path.dirname(__file__), "transport.xml"))
 mdoc = mllib.xml_parse(os.path.join(os.path.dirname(__file__), "messaging.xml"))
 tdoc = mllib.xml_parse(os.path.join(os.path.dirname(__file__), "transactions.xml"))
 sdoc = mllib.xml_parse(os.path.join(os.path.dirname(__file__), "security.xml"))
 
+
 def eq(attr, value):
-  return lambda nd: nd[attr] == value
+    return lambda nd: nd[attr] == value
+
 
 TYPEStmp = doc.query["amqp/section/type", eq("@class", "composite")] + \
     mdoc.query["amqp/section/type", eq("@class", "composite")] + \
@@ -33,89 +37,98 @@ TYPEStmp = doc.query["amqp/section/type", eq("@class", "composite")] + \
     mdoc.query["amqp/section/type", eq("@provides", "section")]
 TYPES = []
 for ty in TYPEStmp:
-  if not ty in TYPES:
-    TYPES.append(ty)
+    if not ty in TYPES:
+        TYPES.append(ty)
 RESTRICTIONS = {}
 COMPOSITES = {}
 
 for type in doc.query["amqp/section/type"] + mdoc.query["amqp/section/type"] + \
-    sdoc.query["amqp/section/type"] + tdoc.query["amqp/section/type"]:
+        sdoc.query["amqp/section/type"] + tdoc.query["amqp/section/type"]:
+
+    source = type["@source"]
+    if source:
+        RESTRICTIONS[type["@name"]] = source
+    if type["@class"] == "composite":
+        COMPOSITES[type["@name"]] = type
 
-  source = type["@source"]
-  if source:
-    RESTRICTIONS[type["@name"]] = source
-  if type["@class"] == "composite":
-    COMPOSITES[type["@name"]] = type
 
 def resolve(name):
-  if name in RESTRICTIONS:
-    return resolve(RESTRICTIONS[name])
-  else:
-    return name
+    if name in RESTRICTIONS:
+        return resolve(RESTRICTIONS[name])
+    else:
+        return name
+
 
 TYPEMAP = {
-  "boolean": ("bool", "", ""),
-  "binary": ("pn_binary_t", "*", ""),
-  "string": ("wchar_t", "*", ""),
-  "symbol": ("char", "*", ""),
-  "ubyte": ("uint8_t", "", ""),
-  "ushort": ("uint16_t", "", ""),
-  "uint": ("uint32_t", "", ""),
-  "ulong": ("uint64_t", "", ""),
-  "timestamp": ("uint64_t", "", ""),
-  "list": ("pn_list_t", "*", ""),
-  "map": ("pn_map_t", "*", ""),
-  "box": ("pn_box_t", "*", ""),
-  "*": ("pn_object_t", "*", "")
-  }
+    "boolean": ("bool", "", ""),
+    "binary": ("pn_binary_t", "*", ""),
+    "string": ("wchar_t", "*", ""),
+    "symbol": ("char", "*", ""),
+    "ubyte": ("uint8_t", "", ""),
+    "ushort": ("uint16_t", "", ""),
+    "uint": ("uint32_t", "", ""),
+    "ulong": ("uint64_t", "", ""),
+    "timestamp": ("uint64_t", "", ""),
+    "list": ("pn_list_t", "*", ""),
+    "map": ("pn_map_t", "*", ""),
+    "box": ("pn_box_t", "*", ""),
+    "*": ("pn_object_t", "*", "")
+}
 
 CONSTRUCTORS = {
-  "boolean": "boolean",
-  "string": "string",
-  "symbol": "symbol",
-  "ubyte": "ubyte",
-  "ushort": "ushort",
-  "uint": "uint",
-  "ulong": "ulong",
-  "timestamp": "ulong"
-  }
+    "boolean": "boolean",
+    "string": "string",
+    "symbol": "symbol",
+    "ubyte": "ubyte",
+    "ushort": "ushort",
+    "uint": "uint",
+    "ulong": "ulong",
+    "timestamp": "ulong"
+}
 
 NULLABLE = set(["string", "symbol"])
 
+
 def fname(field):
-  return field["@name"].replace("-", "_")
+    return field["@name"].replace("-", "_")
+
 
 def tname(t):
-  return t["@name"].replace("-", "_")
+    return t["@name"].replace("-", "_")
+
 
 def multi(f):
-  return f["@multiple"] == "true"
+    return f["@multiple"] == "true"
+
 
 def ftype(field):
-  if multi(field):
-    return "list"
-  elif field["@type"] in COMPOSITES:
-    return "box"
-  else:
-    return resolve(field["@type"]).replace("-", "_")
+    if multi(field):
+        return "list"
+    elif field["@type"] in COMPOSITES:
+        return "box"
+    else:
+        return resolve(field["@type"]).replace("-", "_")
+
 
 def fconstruct(field, expr):
-  type = ftype(field)
-  if type in CONSTRUCTORS:
-    result = "pn_%s(mem, %s)" % (CONSTRUCTORS[type], expr)
-    if type in NULLABLE:
-      result = "%s ? %s : NULL" % (expr, result)
-  else:
-    result = expr
-  if multi(field):
-    result = "pn_box(mem, pn_boolean(mem, true), %s)" % result
-  return result
+    type = ftype(field)
+    if type in CONSTRUCTORS:
+        result = "pn_%s(mem, %s)" % (CONSTRUCTORS[type], expr)
+        if type in NULLABLE:
+            result = "%s ? %s : NULL" % (expr, result)
+    else:
+        result = expr
+    if multi(field):
+        result = "pn_box(mem, pn_boolean(mem, true), %s)" % result
+    return result
+
 
 def declaration(field):
-  name = fname(field)
-  type = ftype(field)
-  t, pre, post = TYPEMAP.get(type, (type, "", ""))
-  return t, "%s%s%s" % (pre, name, post)
+    name = fname(field)
+    type = ftype(field)
+    t, pre, post = TYPEMAP.get(type, (type, "", ""))
+    return t, "%s%s%s" % (pre, name, post)
+
 
 def field_kw(field):
-  return fname(field).upper()
+    return fname(field).upper()
diff --git a/c/tests/fdlimit.py b/c/tests/fdlimit.py
index 0749edf..8ef60ac 100644
--- a/c/tests/fdlimit.py
+++ b/c/tests/fdlimit.py
@@ -85,8 +85,10 @@ class FdLimitTest(unittest.TestCase):
                 self.assertEqual(sender.wait(), 0)
 
             # Additional send/receive should succeed now
-            self.assertIn("10 messages sent", test_subprocess.check_output(["send", "", b.port], universal_newlines=True))
-            self.assertIn("10 messages received", test_subprocess.check_output(["receive", "", b.port], universal_newlines=True))
+            self.assertIn("10 messages sent", test_subprocess.check_output(
+                ["send", "", b.port], universal_newlines=True))
+            self.assertIn("10 messages received", test_subprocess.check_output(
+                ["receive", "", b.port], universal_newlines=True))
 
 
 if __name__ == "__main__":
diff --git a/python/docs/conf.py b/python/docs/conf.py
index e57ebfe..b85eae8 100644
--- a/python/docs/conf.py
+++ b/python/docs/conf.py
@@ -32,9 +32,9 @@ try:
     with open(ver_file_path, 'r') as ver_file:
         ver_str = ver_file.read().replace('\n', '')
         if '-' in ver_str:
-            version = ver_str.split("-")[0] # Strip '-SNAPSHOT' from end of string
+            version = ver_str.split("-")[0]  # Strip '-SNAPSHOT' from end of string
         else:
-            version = ver_str;
+            version = ver_str
         release = version
     print('Proton version: %s' % version)
 except IOError:
@@ -53,7 +53,7 @@ except IOError:
 extensions = [
     'sphinx.ext.autodoc',
     'sphinx.ext.viewcode',
-    'sphinx.ext.mathjax', # needed for math formulas on some versions of Sphinx
+    'sphinx.ext.mathjax',  # needed for math formulas on some versions of Sphinx
 ]
 
 # Add any paths that contain templates here, relative to this directory.
diff --git a/python/examples/abstract_server.py b/python/examples/abstract_server.py
index f536486..6a7e312 100755
--- a/python/examples/abstract_server.py
+++ b/python/examples/abstract_server.py
@@ -22,6 +22,7 @@ from __future__ import print_function
 
 from proton_server import Server
 
+
 class Application(Server):
     def __init__(self, host, address):
         super(Application, self).__init__(host, address)
@@ -31,7 +32,8 @@ class Application(Server):
         self.send(response, reply_to)
         print("Request from: %s" % reply_to)
 
+
 try:
     Application("localhost:5672", "examples").run()
-except KeyboardInterrupt: pass
-
+except KeyboardInterrupt:
+    pass
diff --git a/python/examples/client.py b/python/examples/client.py
index 86f2c76..b149040 100755
--- a/python/examples/client.py
+++ b/python/examples/client.py
@@ -24,6 +24,7 @@ from proton import Message
 from proton.handlers import MessagingHandler
 from proton.reactor import Container, DynamicNodeProperties
 
+
 class Client(MessagingHandler):
     def __init__(self, url, requests):
         super(Client, self).__init__()
@@ -50,10 +51,11 @@ class Client(MessagingHandler):
         else:
             event.connection.close()
 
-REQUESTS= ["Twas brillig, and the slithy toves",
-           "Did gire and gymble in the wabe.",
-           "All mimsy were the borogroves,",
-           "And the mome raths outgrabe."]
+
+REQUESTS = ["Twas brillig, and the slithy toves",
+            "Did gire and gymble in the wabe.",
+            "All mimsy were the borogroves,",
+            "And the mome raths outgrabe."]
 
 parser = optparse.OptionParser(usage="usage: %prog [options]",
                                description="Send requests to the supplied address and print responses.")
@@ -62,4 +64,3 @@ parser.add_option("-a", "--address", default="localhost:5672/examples",
 opts, args = parser.parse_args()
 
 Container(Client(opts.address, args or REQUESTS)).run()
-
diff --git a/python/examples/client_http.py b/python/examples/client_http.py
index f756740..add9420 100755
--- a/python/examples/client_http.py
+++ b/python/examples/client_http.py
@@ -27,6 +27,7 @@ from proton import Message
 from proton.handlers import MessagingHandler
 from proton_tornado import Container
 
+
 class Client(MessagingHandler):
     def __init__(self, host, address):
         super(Client, self).__init__()
@@ -72,6 +73,7 @@ class Client(MessagingHandler):
         self.container.touch()
         return future
 
+
 class ExampleHandler(tornado.web.RequestHandler):
     def initialize(self, client):
         self.client = client
diff --git a/python/examples/colour_send.py b/python/examples/colour_send.py
index 1da1cf5..c7442d8 100755
--- a/python/examples/colour_send.py
+++ b/python/examples/colour_send.py
@@ -24,6 +24,7 @@ from proton import Message
 from proton.handlers import MessagingHandler
 from proton.reactor import Container
 
+
 class Send(MessagingHandler):
     def __init__(self, url, messages):
         super(Send, self).__init__()
@@ -42,7 +43,7 @@ class Send(MessagingHandler):
             else:
                 colour = 'green'
             content = '%s %d' % (colour, self.sent+1)
-            msg = Message(id=(self.sent+1), properties={'colour':colour}, body=content)
+            msg = Message(id=(self.sent+1), properties={'colour': colour}, body=content)
             event.sender.send(msg)
             self.sent += 1
 
@@ -55,6 +56,7 @@ class Send(MessagingHandler):
     def on_disconnected(self, event):
         self.sent = self.confirmed
 
+
 parser = optparse.OptionParser(usage="usage: %prog [options]",
                                description="Send messages to the supplied address.")
 parser.add_option("-a", "--address", default="localhost:5672/examples",
@@ -65,4 +67,5 @@ opts, args = parser.parse_args()
 
 try:
     Container(Send(opts.address, opts.messages)).run()
-except KeyboardInterrupt: pass
+except KeyboardInterrupt:
+    pass
diff --git a/python/examples/db_common.py b/python/examples/db_common.py
index 54af87b..c12417d 100755
--- a/python/examples/db_common.py
+++ b/python/examples/db_common.py
@@ -26,6 +26,7 @@ except:
 import sqlite3
 import threading
 
+
 class Db(object):
     def __init__(self, db, injector):
         self.db = db
@@ -35,7 +36,7 @@ class Db(object):
         self.pending_events = []
         self.running = True
         self.thread = threading.Thread(target=self._process)
-        self.thread.daemon=True
+        self.thread.daemon = True
         self.thread.start()
 
     def close(self):
@@ -110,7 +111,8 @@ class Db(object):
                     while True:
                         f(conn)
                         f = self.tasks.get(False)
-                except Queue.Empty: pass
+                except Queue.Empty:
+                    pass
                 conn.commit()
                 for event in self.pending_events:
                     self.injector.trigger(event)
diff --git a/python/examples/db_ctrl.py b/python/examples/db_ctrl.py
index 04770ce..a263f96 100755
--- a/python/examples/db_ctrl.py
+++ b/python/examples/db_ctrl.py
@@ -40,8 +40,9 @@ else:
         elif sys.argv[1] == "insert":
             while True:
                 l = sys.stdin.readline()
-                if not l: break
+                if not l:
+                    break
                 conn.execute("INSERT INTO records(description) VALUES (?)", (l.rstrip(),))
             conn.commit()
         else:
-            print("Unrecognised command: %s" %  sys.argv[1])
+            print("Unrecognised command: %s" % sys.argv[1])
diff --git a/python/examples/db_recv.py b/python/examples/db_recv.py
index ce27470..8e293ce 100755
--- a/python/examples/db_recv.py
+++ b/python/examples/db_recv.py
@@ -24,6 +24,7 @@ from proton.handlers import MessagingHandler
 from proton.reactor import ApplicationEvent, Container, EventInjector
 from db_common import Db
 
+
 class Recv(MessagingHandler):
     def __init__(self, url, count):
         super(Recv, self).__init__(auto_accept=False)
@@ -65,6 +66,7 @@ class Recv(MessagingHandler):
         else:
             self.accept(event.delivery)
 
+
 parser = optparse.OptionParser(usage="usage: %prog [options]")
 parser.add_option("-a", "--address", default="localhost:5672/examples",
                   help="address from which messages are received (default %default)")
@@ -74,7 +76,5 @@ opts, args = parser.parse_args()
 
 try:
     Container(Recv(opts.address, opts.messages)).run()
-except KeyboardInterrupt: pass
-
-
-
+except KeyboardInterrupt:
+    pass
diff --git a/python/examples/db_send.py b/python/examples/db_send.py
index c07dcc0..2060079 100755
--- a/python/examples/db_send.py
+++ b/python/examples/db_send.py
@@ -32,6 +32,7 @@ from proton.handlers import MessagingHandler
 from proton.reactor import ApplicationEvent, Container, EventInjector
 from db_common import Db
 
+
 class Send(MessagingHandler):
     def __init__(self, url, count):
         super(Send, self).__init__()
@@ -65,14 +66,16 @@ class Send(MessagingHandler):
         if not self.records.full():
             print("loading records...")
             self.load_count += 1
-            self.db.load(self.records, event=ApplicationEvent("records_loaded", link=self.sender, subject=self.load_count))
+            self.db.load(self.records, event=ApplicationEvent(
+                "records_loaded", link=self.sender, subject=self.load_count))
 
     def on_sendable(self, event):
         self.send()
 
     def send(self):
         while self.sender.credit and not self.records.empty():
-            if not self.keep_sending(): return
+            if not self.keep_sending():
+                return
             record = self.records.get(False)
             id = record['id']
             self.sender.send(Message(id=id, durable=True, body=record['description']), tag=str(id))
@@ -97,6 +100,7 @@ class Send(MessagingHandler):
         print("Rechecking for data...")
         self.request_records()
 
+
 parser = optparse.OptionParser(usage="usage: %prog [options]",
                                description="Send messages to the supplied address.")
 parser.add_option("-a", "--address", default="localhost:5672/examples",
@@ -107,5 +111,5 @@ opts, args = parser.parse_args()
 
 try:
     Container(Send(opts.address, opts.messages)).run()
-except KeyboardInterrupt: pass
-
+except KeyboardInterrupt:
+    pass
diff --git a/python/examples/direct_recv.py b/python/examples/direct_recv.py
index 1c6bf36..50551fc 100755
--- a/python/examples/direct_recv.py
+++ b/python/examples/direct_recv.py
@@ -23,6 +23,7 @@ import optparse
 from proton.handlers import MessagingHandler
 from proton.reactor import Container
 
+
 class Recv(MessagingHandler):
     def __init__(self, url, count):
         super(Recv, self).__init__()
@@ -45,6 +46,7 @@ class Recv(MessagingHandler):
                 event.connection.close()
                 self.acceptor.close()
 
+
 parser = optparse.OptionParser(usage="usage: %prog [options]")
 parser.add_option("-a", "--address", default="localhost:5672/examples",
                   help="address from which messages are received (default %default)")
@@ -54,7 +56,5 @@ opts, args = parser.parse_args()
 
 try:
     Container(Recv(opts.address, opts.messages)).run()
-except KeyboardInterrupt: pass
-
-
-
+except KeyboardInterrupt:
+    pass
diff --git a/python/examples/direct_send.py b/python/examples/direct_send.py
index 35bd2f5..8c29f0e 100755
--- a/python/examples/direct_send.py
+++ b/python/examples/direct_send.py
@@ -24,6 +24,7 @@ from proton import Message
 from proton.handlers import MessagingHandler
 from proton.reactor import Container
 
+
 class Send(MessagingHandler):
     def __init__(self, url, messages):
         super(Send, self).__init__()
@@ -37,7 +38,7 @@ class Send(MessagingHandler):
 
     def on_sendable(self, event):
         while event.sender.credit and self.sent < self.total:
-            msg = Message(id=(self.sent+1), body={'sequence':(self.sent+1)})
+            msg = Message(id=(self.sent+1), body={'sequence': (self.sent+1)})
             event.sender.send(msg)
             self.sent += 1
 
@@ -51,6 +52,7 @@ class Send(MessagingHandler):
     def on_disconnected(self, event):
         self.sent = self.confirmed
 
+
 parser = optparse.OptionParser(usage="usage: %prog [options]",
                                description="Send messages to the supplied address.")
 parser.add_option("-a", "--address", default="localhost:5672/examples",
@@ -61,4 +63,5 @@ opts, args = parser.parse_args()
 
 try:
     Container(Send(opts.address, opts.messages)).run()
-except KeyboardInterrupt: pass
+except KeyboardInterrupt:
+    pass
diff --git a/python/examples/helloworld.py b/python/examples/helloworld.py
index 7a91aa4..4e2adc9 100755
--- a/python/examples/helloworld.py
+++ b/python/examples/helloworld.py
@@ -23,6 +23,7 @@ from proton import Message
 from proton.handlers import MessagingHandler
 from proton.reactor import Container
 
+
 class HelloWorld(MessagingHandler):
     def __init__(self, server, address):
         super(HelloWorld, self).__init__()
@@ -42,4 +43,5 @@ class HelloWorld(MessagingHandler):
         print(event.message.body)
         event.connection.close()
 
+
 Container(HelloWorld("localhost:5672", "examples")).run()
diff --git a/python/examples/helloworld_blocking.py b/python/examples/helloworld_blocking.py
index 5a5ce6d..fb260d5 100755
--- a/python/examples/helloworld_blocking.py
+++ b/python/examples/helloworld_blocking.py
@@ -26,9 +26,8 @@ from proton.handlers import IncomingMessageHandler
 conn = BlockingConnection("localhost:5672")
 receiver = conn.create_receiver("examples")
 sender = conn.create_sender("examples")
-sender.send(Message(body="Hello World!"));
+sender.send(Message(body="Hello World!"))
 msg = receiver.receive(timeout=30)
 print(msg.body)
 receiver.accept()
 conn.close()
-
diff --git a/python/examples/helloworld_direct.py b/python/examples/helloworld_direct.py
index 0292abe..4218b53 100755
--- a/python/examples/helloworld_direct.py
+++ b/python/examples/helloworld_direct.py
@@ -23,6 +23,7 @@ from proton import Message
 from proton.handlers import MessagingHandler
 from proton.reactor import Container
 
+
 class HelloWorld(MessagingHandler):
     def __init__(self, url):
         super(HelloWorld, self).__init__()
@@ -45,4 +46,5 @@ class HelloWorld(MessagingHandler):
     def on_connection_closed(self, event):
         self.acceptor.close()
 
+
 Container(HelloWorld("localhost:8888/examples")).run()
diff --git a/python/examples/helloworld_direct_tornado.py b/python/examples/helloworld_direct_tornado.py
index a3b017a..2b3bbd2 100755
--- a/python/examples/helloworld_direct_tornado.py
+++ b/python/examples/helloworld_direct_tornado.py
@@ -23,6 +23,7 @@ from proton import Message
 from proton.handlers import MessagingHandler
 from proton_tornado import Container
 
+
 class HelloWorld(MessagingHandler):
     def __init__(self, url):
         super(HelloWorld, self).__init__()
@@ -45,4 +46,5 @@ class HelloWorld(MessagingHandler):
     def on_connection_closed(self, event):
         self.acceptor.close()
 
+
 Container(HelloWorld("localhost:8888/examples")).run()
diff --git a/python/examples/helloworld_tornado.py b/python/examples/helloworld_tornado.py
index 0781bbb..5604b21 100755
--- a/python/examples/helloworld_tornado.py
+++ b/python/examples/helloworld_tornado.py
@@ -23,6 +23,7 @@ from proton import Message
 from proton.handlers import MessagingHandler
 from proton_tornado import Container
 
+
 class HelloWorld(MessagingHandler):
     def __init__(self, server, address):
         super(HelloWorld, self).__init__()
@@ -42,4 +43,5 @@ class HelloWorld(MessagingHandler):
         print(event.message.body)
         event.connection.close()
 
+
 Container(HelloWorld("localhost:5672", "examples")).run()
diff --git a/python/examples/proton_server.py b/python/examples/proton_server.py
index 9351f55..6dfd807 100755
--- a/python/examples/proton_server.py
+++ b/python/examples/proton_server.py
@@ -22,6 +22,7 @@ from proton import Message
 from proton.reactor import Container
 from proton.handlers import MessagingHandler
 
+
 class Server(MessagingHandler):
     def __init__(self, host, address):
         super(Server, self).__init__()
@@ -34,7 +35,8 @@ class Server(MessagingHandler):
         self.on_request(event.message.body, event.message.reply_to)
 
     def on_connection_close(self, endpoint, error):
-        if error: print("Closed due to %s" % error)
+        if error:
+            print("Closed due to %s" % error)
         self.conn.close()
 
     def run(self):
@@ -48,4 +50,3 @@ class Server(MessagingHandler):
 
     def on_request(self, request, reply_to):
         pass
-
diff --git a/python/examples/queue_browser.py b/python/examples/queue_browser.py
index 34d2377..7f659f0 100755
--- a/python/examples/queue_browser.py
+++ b/python/examples/queue_browser.py
@@ -22,6 +22,7 @@ from __future__ import print_function
 from proton.reactor import Container, Copy
 from proton.handlers import MessagingHandler
 
+
 class Recv(MessagingHandler):
     def __init__(self):
         super(Recv, self).__init__()
@@ -35,9 +36,8 @@ class Recv(MessagingHandler):
         if event.receiver.queued == 0 and event.receiver.drained:
             event.connection.close()
 
+
 try:
     Container(Recv()).run()
-except KeyboardInterrupt: pass
-
-
-
+except KeyboardInterrupt:
+    pass
diff --git a/python/examples/recurring_timer.py b/python/examples/recurring_timer.py
index b59dbe1..58f3ffd 100755
--- a/python/examples/recurring_timer.py
+++ b/python/examples/recurring_timer.py
@@ -21,6 +21,7 @@
 from __future__ import print_function
 from proton.reactor import Container, Handler
 
+
 class Recurring(Handler):
     def __init__(self, period):
         self.period = period
@@ -33,11 +34,10 @@ class Recurring(Handler):
         print("Tick...")
         self.container.schedule(self.period, self)
 
+
 try:
     container = Container(Recurring(1.0))
     container.run()
 except KeyboardInterrupt:
     container.stop()
     print()
-
-
diff --git a/python/examples/recurring_timer_tornado.py b/python/examples/recurring_timer_tornado.py
index a9a7579..ff4c078 100755
--- a/python/examples/recurring_timer_tornado.py
+++ b/python/examples/recurring_timer_tornado.py
@@ -22,6 +22,7 @@ from __future__ import print_function
 from proton.reactor import Handler
 from proton_tornado import Container
 
+
 class Recurring(Handler):
     def __init__(self, period):
         self.period = period
@@ -34,11 +35,10 @@ class Recurring(Handler):
         print("Tick...")
         self.container.schedule(self.period, self)
 
+
 try:
     container = Container(Recurring(1.0))
     container.run()
 except KeyboardInterrupt:
     container.stop()
     print()
-
-
diff --git a/python/examples/selected_recv.py b/python/examples/selected_recv.py
index 0f9ded1..43b576b 100755
--- a/python/examples/selected_recv.py
+++ b/python/examples/selected_recv.py
@@ -24,6 +24,7 @@ from proton import Url
 from proton.reactor import Container, Selector
 from proton.handlers import MessagingHandler
 
+
 class Recv(MessagingHandler):
     def __init__(self, url, count):
         super(Recv, self).__init__()
@@ -42,6 +43,7 @@ class Recv(MessagingHandler):
             event.receiver.close()
             event.connection.close()
 
+
 parser = optparse.OptionParser(usage="usage: %prog [options]")
 parser.add_option("-a", "--address", default="localhost:5672/examples",
                   help="address from which messages are received (default %default)")
@@ -51,7 +53,5 @@ opts, args = parser.parse_args()
 
 try:
     Container(Recv(opts.address, opts.messages)).run()
-except KeyboardInterrupt: pass
-
-
-
+except KeyboardInterrupt:
+    pass
diff --git a/python/examples/server.py b/python/examples/server.py
index 5d7650a..eb0d66e 100755
--- a/python/examples/server.py
+++ b/python/examples/server.py
@@ -24,6 +24,7 @@ from proton import Message, Url
 from proton.handlers import MessagingHandler
 from proton.reactor import Container
 
+
 class Server(MessagingHandler):
     def __init__(self, url, address):
         super(Server, self).__init__()
@@ -40,7 +41,8 @@ class Server(MessagingHandler):
     def on_message(self, event):
         print("Received", event.message)
         self.server.send(Message(address=event.message.reply_to, body=event.message.body.upper(),
-                            correlation_id=event.message.correlation_id))
+                                 correlation_id=event.message.correlation_id))
+
 
 parser = optparse.OptionParser(usage="usage: %prog [options]")
 parser.add_option("-a", "--address", default="localhost:5672/examples",
@@ -51,7 +53,5 @@ url = Url(opts.address)
 
 try:
     Container(Server(url, url.path)).run()
-except KeyboardInterrupt: pass
-
-
-
+except KeyboardInterrupt:
+    pass
diff --git a/python/examples/server_direct.py b/python/examples/server_direct.py
index 71f73e9..8cc7d9c 100755
--- a/python/examples/server_direct.py
+++ b/python/examples/server_direct.py
@@ -25,6 +25,7 @@ from proton import Message
 from proton.handlers import MessagingHandler
 from proton.reactor import Container
 
+
 class Server(MessagingHandler):
     def __init__(self, url):
         super(Server, self).__init__()
@@ -58,9 +59,8 @@ class Server(MessagingHandler):
         sender.send(Message(address=event.message.reply_to, body=event.message.body.upper(),
                             correlation_id=event.message.correlation_id))
 
+
 try:
     Container(Server("0.0.0.0:8888")).run()
-except KeyboardInterrupt: pass
-
-
-
+except KeyboardInterrupt:
+    pass
diff --git a/python/examples/server_tx.py b/python/examples/server_tx.py
index 51e734c..731f9eb 100755
--- a/python/examples/server_tx.py
+++ b/python/examples/server_tx.py
@@ -23,6 +23,7 @@ from proton import Message
 from proton.reactor import Container
 from proton.handlers import MessagingHandler, TransactionHandler
 
+
 class TxRequest(TransactionHandler):
     def __init__(self, response, sender, request_delivery):
         super(TxRequest, self).__init__()
@@ -71,9 +72,8 @@ class TxServer(MessagingHandler):
         if event.connection.remote_offered_capabilities and 'ANONYMOUS-RELAY' in event.connection.remote_offered_capabilities:
             self.relay = self.container.create_sender(self.conn, None)
 
+
 try:
     Container(TxServer("localhost:5672", "examples")).run()
-except KeyboardInterrupt: pass
-
-
-
+except KeyboardInterrupt:
+    pass
diff --git a/python/examples/simple_recv.py b/python/examples/simple_recv.py
index 5322500..52724a3 100755
--- a/python/examples/simple_recv.py
+++ b/python/examples/simple_recv.py
@@ -23,6 +23,7 @@ import optparse
 from proton.handlers import MessagingHandler
 from proton.reactor import Container
 
+
 class Recv(MessagingHandler):
     def __init__(self, url, count):
         super(Recv, self).__init__()
@@ -44,6 +45,7 @@ class Recv(MessagingHandler):
                 event.receiver.close()
                 event.connection.close()
 
+
 parser = optparse.OptionParser(usage="usage: %prog [options]")
 parser.add_option("-a", "--address", default="localhost:5672/examples",
                   help="address from which messages are received (default %default)")
@@ -53,7 +55,5 @@ opts, args = parser.parse_args()
 
 try:
     Container(Recv(opts.address, opts.messages)).run()
-except KeyboardInterrupt: pass
-
-
-
+except KeyboardInterrupt:
+    pass
diff --git a/python/examples/simple_send.py b/python/examples/simple_send.py
index 7717a16..2cff11c 100755
--- a/python/examples/simple_send.py
+++ b/python/examples/simple_send.py
@@ -24,6 +24,7 @@ from proton import Message
 from proton.handlers import MessagingHandler
 from proton.reactor import Container
 
+
 class Send(MessagingHandler):
     def __init__(self, url, messages):
         super(Send, self).__init__()
@@ -37,7 +38,7 @@ class Send(MessagingHandler):
 
     def on_sendable(self, event):
         while event.sender.credit and self.sent < self.total:
-            msg = Message(id=(self.sent+1), body={'sequence':(self.sent+1)})
+            msg = Message(id=(self.sent+1), body={'sequence': (self.sent+1)})
             event.sender.send(msg)
             self.sent += 1
 
@@ -50,6 +51,7 @@ class Send(MessagingHandler):
     def on_disconnected(self, event):
         self.sent = self.confirmed
 
+
 parser = optparse.OptionParser(usage="usage: %prog [options]",
                                description="Send messages to the supplied address.")
 parser.add_option("-a", "--address", default="localhost:5672/examples",
@@ -60,4 +62,5 @@ opts, args = parser.parse_args()
 
 try:
     Container(Send(opts.address, opts.messages)).run()
-except KeyboardInterrupt: pass
+except KeyboardInterrupt:
+    pass
diff --git a/python/examples/sync_client.py b/python/examples/sync_client.py
index 7b86e29..9a395ae 100755
--- a/python/examples/sync_client.py
+++ b/python/examples/sync_client.py
@@ -43,13 +43,12 @@ url = Url(opts.address)
 client = SyncRequestResponse(BlockingConnection(url, timeout=opts.timeout), url.path)
 
 try:
-    REQUESTS= ["Twas brillig, and the slithy toves",
-               "Did gire and gymble in the wabe.",
-               "All mimsy were the borogroves,",
-               "And the mome raths outgrabe."]
+    REQUESTS = ["Twas brillig, and the slithy toves",
+                "Did gire and gymble in the wabe.",
+                "All mimsy were the borogroves,",
+                "And the mome raths outgrabe."]
     for request in REQUESTS:
         response = client.call(Message(body=request))
         print("%s => %s" % (request, response.body))
 finally:
     client.connection.close()
-
diff --git a/python/examples/test_examples.py b/python/examples/test_examples.py
index 8df68ec..d46ab01 100644
--- a/python/examples/test_examples.py
+++ b/python/examples/test_examples.py
@@ -82,7 +82,7 @@ class ExamplesTest(unittest.TestCase):
             actual = [remove_unicode_prefix(l.strip()) for l in r.stdout]
             expected_py2 = ["{'sequence': int32(%i)}" % (i+1,) for i in range(100)]
             expected_py3 = ["{'sequence': %i}" % (i+1,) for i in range(100)]
-            self.assertIn(actual,[expected_py2, expected_py3])
+            self.assertIn(actual, [expected_py2, expected_py3])
 
     def test_client_server(self, client=['client.py'], server=['server.py'], sleep=0):
         with Popen(server) as s:
@@ -109,10 +109,12 @@ class ExamplesTest(unittest.TestCase):
         self.test_client_server(client=['sync_client.py'], server=['server_tx.py'])
 
     def test_client_server_direct(self):
-        self.test_client_server(client=['client.py', '-a', 'localhost:8888/examples'], server=['server_direct.py'], sleep=0.5)
+        self.test_client_server(client=['client.py', '-a', 'localhost:8888/examples'],
+                                server=['server_direct.py'], sleep=0.5)
 
     def test_sync_client_server_direct(self):
-        self.test_client_server(client=['sync_client.py', '-a', 'localhost:8888/examples'], server=['server_direct.py'], sleep=0.5)
+        self.test_client_server(client=['sync_client.py', '-a', 'localhost:8888/examples'],
+                                server=['server_direct.py'], sleep=0.5)
 
     def test_db_send_recv(self):
         self.maxDiff = None
@@ -154,7 +156,7 @@ class ExamplesTest(unittest.TestCase):
             actual = [remove_unicode_prefix(l.strip()) for l in r.stdout]
             expected_py2 = ["{'sequence': int32(%i)}" % (i+1,) for i in range(100)]
             expected_py3 = ["{'sequence': %i}" % (i+1,) for i in range(100)]
-            self.assertIn(actual,[expected_py2, expected_py3])
+            self.assertIn(actual, [expected_py2, expected_py3])
 
     def test_direct_send_simple_recv(self):
         with Popen(['direct_send.py', '-a', 'localhost:8888']):
diff --git a/python/examples/tx_recv.py b/python/examples/tx_recv.py
index 4baddcf..bea05ab 100755
--- a/python/examples/tx_recv.py
+++ b/python/examples/tx_recv.py
@@ -24,6 +24,7 @@ from proton import Url
 from proton.reactor import Container
 from proton.handlers import MessagingHandler, TransactionHandler
 
+
 class TxRecv(MessagingHandler, TransactionHandler):
     def __init__(self, url, messages, batch_size):
         super(TxRecv, self).__init__(prefetch=0, auto_accept=False)
@@ -63,6 +64,7 @@ class TxRecv(MessagingHandler, TransactionHandler):
     def on_disconnected(self, event):
         self.current_batch = 0
 
+
 parser = optparse.OptionParser(usage="usage: %prog [options]")
 parser.add_option("-a", "--address", default="localhost:5672/examples",
                   help="address from which messages are received (default %default)")
@@ -74,7 +76,5 @@ opts, args = parser.parse_args()
 
 try:
     Container(TxRecv(opts.address, opts.messages, opts.batch_size)).run()
-except KeyboardInterrupt: pass
-
-
-
+except KeyboardInterrupt:
+    pass
diff --git a/python/examples/tx_recv_interactive.py b/python/examples/tx_recv_interactive.py
index c38f651..63bc76b 100755
--- a/python/examples/tx_recv_interactive.py
+++ b/python/examples/tx_recv_interactive.py
@@ -24,6 +24,7 @@ import threading
 from proton.reactor import ApplicationEvent, Container, EventInjector
 from proton.handlers import MessagingHandler, TransactionHandler
 
+
 class TxRecv(MessagingHandler, TransactionHandler):
     def __init__(self):
         super(TxRecv, self).__init__(prefetch=0, auto_accept=False)
@@ -65,12 +66,13 @@ class TxRecv(MessagingHandler, TransactionHandler):
         self.receiver.close()
         c.close()
 
+
 try:
     reactor = Container(TxRecv())
     events = EventInjector()
     reactor.selectable(events)
     thread = threading.Thread(target=reactor.run)
-    thread.daemon=True
+    thread.daemon = True
     thread.start()
 
     print("Enter 'fetch', 'commit' or 'abort'")
@@ -80,6 +82,5 @@ try:
             events.trigger(ApplicationEvent(line.strip()))
         else:
             break
-except KeyboardInterrupt: pass
-
-
+except KeyboardInterrupt:
+    pass
diff --git a/python/examples/tx_send.py b/python/examples/tx_send.py
index bda6780..3d53be5 100755
--- a/python/examples/tx_send.py
+++ b/python/examples/tx_send.py
@@ -24,6 +24,7 @@ from proton import Message, Url
 from proton.reactor import Container
 from proton.handlers import MessagingHandler, TransactionHandler
 
+
 class TxSend(MessagingHandler, TransactionHandler):
     def __init__(self, url, messages, batch_size):
         super(TxSend, self).__init__()
@@ -51,7 +52,7 @@ class TxSend(MessagingHandler, TransactionHandler):
     def send(self):
         while self.transaction and self.sender.credit and (self.committed + self.current_batch) < self.total:
             seq = self.committed + self.current_batch + 1
-            msg = Message(id=seq, body={'sequence':seq})
+            msg = Message(id=seq, body={'sequence': seq})
             self.transaction.send(self.sender, msg)
             self.current_batch += 1
             if self.current_batch == self.batch_size:
@@ -74,6 +75,7 @@ class TxSend(MessagingHandler, TransactionHandler):
     def on_disconnected(self, event):
         self.current_batch = 0
 
+
 parser = optparse.OptionParser(usage="usage: %prog [options]",
                                description="Send messages transactionally to the supplied address.")
 parser.add_option("-a", "--address", default="localhost:5672/examples",
@@ -86,4 +88,5 @@ opts, args = parser.parse_args()
 
 try:
     Container(TxSend(opts.address, opts.messages, opts.batch_size)).run()
-except KeyboardInterrupt: pass
+except KeyboardInterrupt:
+    pass
diff --git a/python/proton/_common.py b/python/proton/_common.py
index d64f408..3715c6a 100644
--- a/python/proton/_common.py
+++ b/python/proton/_common.py
@@ -77,6 +77,7 @@ def unicode2utf8(string):
     # Anything else illegal - specifically python3 bytes
     raise TypeError("Unrecognized string type: %r (%s)" % (string, type(string)))
 
+
 def utf82unicode(string):
     """Convert C strings returned from proton-c into python unicode"""
     if string is None:
diff --git a/python/proton/_compat.py b/python/proton/_compat.py
index 7380334..2235d35 100644
--- a/python/proton/_compat.py
+++ b/python/proton/_compat.py
@@ -27,11 +27,11 @@ import sys
 try:
     import Queue as queue
 except ImportError:
-    import queue # type: ignore
+    import queue  # type: ignore
 
 try:
     from urlparse import urlparse, urlunparse
-    from urllib import quote, unquote # type: ignore
+    from urllib import quote, unquote  # type: ignore
 except ImportError:
     from urllib.parse import urlparse, urlunparse, quote, unquote
 
@@ -59,7 +59,7 @@ if PY3:
 else:
     # the raise syntax will cause a parse error in Py3, so 'sneak' in a
     # definition that won't cause the parser to barf
-    exec ("""def raise_(t, v=None, tb=None):
+    exec("""def raise_(t, v=None, tb=None):
     raise t, v, tb
 """)
 
diff --git a/python/proton/_condition.py b/python/proton/_condition.py
index 6916bee..338c776 100644
--- a/python/proton/_condition.py
+++ b/python/proton/_condition.py
@@ -68,10 +68,11 @@ class Condition:
                                             if x])
 
     def __eq__(self, o):
-        if not isinstance(o, Condition): return False
+        if not isinstance(o, Condition):
+            return False
         return self.name == o.name and \
-               self.description == o.description and \
-               self.info == o.info
+            self.description == o.description and \
+            self.info == o.info
 
 
 def obj2cond(obj, cond):
diff --git a/python/proton/_data.py b/python/proton/_data.py
index e324e64..7cfe0bd 100644
--- a/python/proton/_data.py
+++ b/python/proton/_data.py
@@ -70,7 +70,7 @@ class UnmappedType:
 class ulong(long):
     """
     The ulong AMQP type.
-    
+
     An unsigned 64 bit integer in the range :math:`0` to :math:`2^{64} - 1` inclusive.
     """
 
@@ -86,7 +86,7 @@ class ulong(long):
 class timestamp(long):
     """
     The timestamp AMQP type.
-    
+
     An absolute point in time, represented by a signed 64 bit value measuring
     milliseconds since the epoch. This value is encoded using the Unix ``time_t``
     [IEEE1003] encoding of UTC, but with a precision of milliseconds. For
@@ -100,7 +100,7 @@ class timestamp(long):
 class symbol(unicode):
     """
     The symbol AMQP type.
-    
+
     Symbolic values from a constrained domain, represented by a sequence of ASCII characters.
     """
 
@@ -111,7 +111,7 @@ class symbol(unicode):
 class char(unicode):
     """
     The char AMQP type.
-    
+
     A 32 bit UTF-32BE encoded Unicode character.
     """
 
@@ -122,7 +122,7 @@ class char(unicode):
 class byte(int):
     """
     The byte AMQP type.
-    
+
     An 8 bit signed integer in the range :math:`-(2^7)` to :math:`2^7 - 1` inclusive.
     """
 
@@ -133,7 +133,7 @@ class byte(int):
 class short(int):
     """
     The short AMQP type.
-    
+
     A 16 bit signed integer in the range :math:`-(2^{15})` to :math:`2^{15} - 1` inclusive.
     """
 
@@ -144,7 +144,7 @@ class short(int):
 class int32(int):
     """
     The signed int AMQP type.
-    
+
     A 32 bit signed integer in the range :math:`-(2^{31})` to :math:`2^{31} - 1` inclusive.
     """
 
@@ -155,7 +155,7 @@ class int32(int):
 class ubyte(int):
     """
     The unsigned byte AMQP type.
-    
+
     An 8 bit unsigned integer in the range :math:`0` to :math:`2^8 - 1` inclusive.
     """
 
@@ -171,7 +171,7 @@ class ubyte(int):
 class ushort(int):
     """
     The unsigned short AMQP type.
-    
+
     A 16 bit unsigned integer in the range :math:`0` to :math:`2^{16} - 1` inclusive.
     """
 
@@ -187,7 +187,7 @@ class ushort(int):
 class uint(long):
     """
     The unsigned int AMQP type.
-    
+
     A 32 bit unsigned integer in the range :math:`0` to :math:`2^{32} - 1` inclusive.
     """
 
@@ -203,7 +203,7 @@ class uint(long):
 class float32(float):
     """
     The float AMQP type.
-    
+
     A 32 bit floating point number (IEEE 754-2008 binary32).
     """
 
@@ -214,7 +214,7 @@ class float32(float):
 class decimal32(int):
     """
     The decimal32 AMQP type.
-    
+
     A 32 bit decimal floating point  number (IEEE 754-2008 decimal32).
     """
 
@@ -225,7 +225,7 @@ class decimal32(int):
 class decimal64(long):
     """
     The decimal64 AMQP type.
-    
+
     A 64 bit decimal floating point number (IEEE 754-2008 decimal64).
     """
 
@@ -236,7 +236,7 @@ class decimal64(long):
 class decimal128(bytes):
     """
     The decimal128 AMQP type.
-    
+
     A 128-bit decimal floating-point number (IEEE 754-2008 decimal128).
     """
 
@@ -303,7 +303,7 @@ class Array(object):
     def __eq__(self, o):
         if isinstance(o, Array):
             return self.descriptor == o.descriptor and \
-                   self.type == o.type and self.elements == o.elements
+                self.type == o.type and self.elements == o.elements
         else:
             return False
 
@@ -334,6 +334,7 @@ def _check_is_symbol_or_ulong(s, raise_on_error=True):
 
 class RestrictedKeyDict(dict):
     """Parent class for :class:`PropertyDict` and :class:`AnnotationDict`"""
+
     def __init__(self, validation_fn, e=None, raise_on_error=True, **kwargs):
         super(RestrictedKeyDict, self).__init__()
         self.validation_fn = validation_fn
@@ -401,6 +402,7 @@ class PropertyDict(RestrictedKeyDict):
     :type raise_on_error: ``bool``
     :param kwargs: Keyword args for initializing a ``dict`` of the form key1=val1, key2=val2, ...
     """
+
     def __init__(self, e=None, raise_on_error=True, **kwargs):
         super(PropertyDict, self).__init__(_check_is_symbol, e, raise_on_error, **kwargs)
 
@@ -445,6 +447,7 @@ class AnnotationDict(RestrictedKeyDict):
     :type raise_on_error: ``bool``
     :param kwargs: Keyword args for initializing a ``dict`` of the form key1=val1, key2=val2, ...
     """
+
     def __init__(self, e=None, raise_on_error=True, **kwargs):
         super(AnnotationDict, self).__init__(_check_is_symbol_or_ulong, e, raise_on_error, **kwargs)
 
@@ -483,6 +486,7 @@ class SymbolList(list):
         an error.
     :type raise_on_error: ``bool``
     """
+
     def __init__(self, t=None, raise_on_error=True):
         super(SymbolList, self).__init__()
         self.raise_on_error = raise_on_error
@@ -639,7 +643,7 @@ class Data:
     def type_name(amqptype):
         """
         Return a string name for an AMQP type.
-        
+
         :param type: Numeric Proton AMQP type (`enum pn_type_t`)
         :type type: integer
         :rtype: String describing the AMQP type with numeric value `amqptype`
@@ -1412,7 +1416,7 @@ class Data:
         """
         Copy the contents of another pn_data_t object. Any values in the
         data object will be lost.
-        
+
         :param src: The source object from which to copy
         :type src: :class:`Data`
         :raise: :exc:`DataException` if there is a Proton error.
@@ -1566,7 +1570,8 @@ class Data:
         """
 
         count, described, type = self.get_array()
-        if type is None: return None
+        if type is None:
+            return None
         if self.enter():
             try:
                 if described:
@@ -1680,7 +1685,8 @@ class Data:
 
     def get_object(self):
         type = self.type()
-        if type is None: return None
+        if type is None:
+            return None
         getter = self.get_mappings.get(type)
         if getter:
             return getter(self)
diff --git a/python/proton/_delivery.py b/python/proton/_delivery.py
index 0f871cf..8b7a693 100644
--- a/python/proton/_delivery.py
+++ b/python/proton/_delivery.py
@@ -74,7 +74,7 @@ class Disposition(object):
     """
     A non terminal state indicating how much (if any) message data
     has been received for a delivery.
-    """    
+    """
 
     ACCEPTED = DispositionType(PN_ACCEPTED, "ACCEPTED")
     """
@@ -107,7 +107,6 @@ class Disposition(object):
     delivery being settled.
     """
 
-
     def __init__(self, impl, local):
         self._impl = impl
         self.local = local
@@ -121,13 +120,13 @@ class Disposition(object):
         Get the type of this disposition object.
 
         Defined values are:
-        
+
         * :const:`RECEIVED`
         * :const:`ACCEPTED`
         * :const:`REJECTED`
         * :const:`RELEASED`
         * :const:`MODIFIED`
-        
+
         :type: ``str``
         """
         return DispositionType.get(pn_disposition_type(self._impl))
@@ -269,7 +268,7 @@ class Delivery(Wrapper):
     """
     A non terminal state indicating how much (if any) message data
     has been received for a delivery.
-    """    
+    """
 
     ACCEPTED = Disposition.ACCEPTED
     """
@@ -302,7 +301,6 @@ class Delivery(Wrapper):
     delivery being settled.
     """
 
-
     @staticmethod
     def wrap(impl):
         if impl is None:
diff --git a/python/proton/_endpoints.py b/python/proton/_endpoints.py
index c5309ff..acbc745 100644
--- a/python/proton/_endpoints.py
+++ b/python/proton/_endpoints.py
@@ -88,7 +88,7 @@ class Endpoint(object):
     but also the last known state of the remote endpoint.
     """
 
-    LOCAL_UNINIT = PN_LOCAL_UNINIT
+    LOCAL_UNINIT = PN_LOCAL_UNINIT
     """ The local  endpoint state is uninitialized. """
 
     REMOTE_UNINIT = PN_REMOTE_UNINIT
@@ -521,7 +521,7 @@ class Connection(Wrapper, Endpoint):
         additional error details can be obtained using this property. The
         returned value is the error code defined by Proton in ``pn_error_t``
         (see ``error.h``).
-        
+
         :type: ``int``
         """
         return pn_error_code(pn_connection_error(self._impl))
@@ -682,7 +682,7 @@ class Session(Wrapper, Endpoint):
         will be set. This may be called without calling
         :meth:`open`, in this case it is equivalent to calling
         :meth:`open` followed by :meth:`close`.
-        
+
         """
         self._update_cond()
         pn_session_close(self._impl)
@@ -786,7 +786,8 @@ class Link(Wrapper, Endpoint):
 
     @staticmethod
     def wrap(impl):
-        if impl is None: return None
+        if impl is None:
+            return None
         if pn_link_is_sender(impl):
             return Sender(impl)
         else:
@@ -1243,7 +1244,6 @@ class Link(Wrapper, Endpoint):
         """
         return dat2obj(pn_link_remote_properties(self._impl))
 
-
     def _get_properties(self):
         return self._properties_dict
 
@@ -1391,7 +1391,7 @@ class Terminus(object):
     A source or target for messages.
     """
     UNSPECIFIED = PN_UNSPECIFIED
-    """A nonexistent terminus, may used as a source or target."""  
+    """A nonexistent terminus, may used as a source or target."""
     SOURCE = PN_SOURCE
     """A source of messages."""
     TARGET = PN_TARGET
@@ -1549,7 +1549,7 @@ class Terminus(object):
     def outcomes(self):
         """
         Outcomes of the source or target.
-
+
         :type: :class:`Data` containing an array of :class:`symbol`.
        """
         return Data(pn_terminus_outcomes(self._impl))
diff --git a/python/proton/_events.py b/python/proton/_events.py
index f1f54e7..df1f664 100644
--- a/python/proton/_events.py
+++ b/python/proton/_events.py
@@ -194,7 +194,6 @@ class Event(EventBase):
     TIMER_TASK = _core(PN_TIMER_TASK, "on_timer_task")
     """A timer event has occurred."""
 
-
     CONNECTION_INIT = _core(PN_CONNECTION_INIT, "on_connection_init")
     """
     The connection has been created. This is the first event that
@@ -245,7 +244,6 @@ class Event(EventBase):
     for a connection.
     """
 
-
     SESSION_INIT = _core(PN_SESSION_INIT, "on_session_init")
     """
     The session has been created. This is the first event that will
@@ -283,7 +281,6 @@ class Event(EventBase):
     for a session.
     """
 
-
     LINK_INIT = _core(PN_LINK_INIT, "on_link_init")
     """
     The link has been created. This is the first event that will ever
@@ -339,14 +336,12 @@ class Event(EventBase):
     link. Events of this type point to the relevant link.
     """
 
-
     DELIVERY = _core(PN_DELIVERY, "on_delivery")
     """
     A delivery has been created or updated. Events of this type point
     to the relevant delivery.
     """
 
-
     TRANSPORT = _core(PN_TRANSPORT, "on_transport")
     """
     The transport has new data to read and/or write. Events of this
@@ -379,7 +374,6 @@ class Event(EventBase):
     closed. Events of this type point to the relevant transport.
     """
 
-
     # These events are now internal events in the python code
     REACTOR_INIT = _internal("reactor_init")
     """
diff --git a/python/proton/_handlers.py b/python/proton/_handlers.py
index baae429..41df67c 100644
--- a/python/proton/_handlers.py
+++ b/python/proton/_handlers.py
@@ -160,6 +160,7 @@ class Acking(object):
     """
     A class containing methods for handling received messages.
     """
+
     def accept(self, delivery):
         """
         Accepts a received message.
@@ -245,7 +246,8 @@ class IncomingMessageHandler(Handler, Acking):
 
     def on_delivery(self, event):
         dlv = event.delivery
-        if not dlv.link.is_receiver: return
+        if not dlv.link.is_receiver:
+            return
         if dlv.aborted:
             self.on_aborted(event)
             dlv.settle()
@@ -1142,7 +1144,8 @@ class PythonIO:
         reactor = event.reactor
         # check if we are still quiesced, other handlers of
         # on_reactor_quiesced could have produced events to process
-        if not reactor.quiesced: return
+        if not reactor.quiesced:
+            return
 
         reading = []
         writing = []
@@ -1162,7 +1165,8 @@ class PythonIO:
             timeout = deadline - time.time()
         else:
             timeout = reactor.timeout
-        if timeout < 0: timeout = 0
+        if timeout < 0:
+            timeout = 0
         timeout = min(timeout, reactor.timeout)
         readable, writable, _ = IO.select(reading, writing, [], timeout)
 
@@ -1346,7 +1350,7 @@ class IOHandler(Handler):
     def update(transport, selectable, now):
         try:
             capacity = transport.capacity()
-            selectable.reading = capacity>0
+            selectable.reading = capacity > 0
         except:
             if transport.closed:
                 selectable.terminate()
@@ -1354,7 +1358,7 @@ class IOHandler(Handler):
                 transport._selectable = None
         try:
             pending = transport.pending()
-            selectable.writing = pending>0
+            selectable.writing = pending > 0
         except:
             if transport.closed:
                 selectable.terminate()
diff --git a/python/proton/_io.py b/python/proton/_io.py
index bda12db..20a5a44 100644
--- a/python/proton/_io.py
+++ b/python/proton/_io.py
@@ -28,6 +28,7 @@ from ._compat import socket_errno
 
 PN_INVALID_SOCKET = -1
 
+
 class IO(object):
 
     @staticmethod
@@ -144,9 +145,10 @@ class IO(object):
                     return IO.select(r, w, w, timeout)
 
                 t = max(0, min(timeout, self._deadline - now))
-                if len(r)==0 and len(w)==0:
-                    if t > 0: IO.sleep(t)
-                    return ([],[],[])
+                if len(r) == 0 and len(w) == 0:
+                    if t > 0:
+                        IO.sleep(t)
+                    return ([], [], [])
 
                 return IO.select(r, w, w, t)
 
diff --git a/python/proton/_message.py b/python/proton/_message.py
index ed791c9..c13ac53 100644
--- a/python/proton/_message.py
+++ b/python/proton/_message.py
@@ -548,9 +548,11 @@ class Message(object):
         :rtype: :class:`Delivery`
 
         """
-        if link.is_sender: return None
+        if link.is_sender:
+            return None
         dlv = link.current
-        if not dlv or dlv.partial: return None
+        if not dlv or dlv.partial:
+            return None
         dlv.encoded = link.recv(dlv.pending)
         link.advance()
         # the sender has already forgotten about the delivery, so we might
@@ -568,5 +570,6 @@ class Message(object):
                      "reply_to_group_id", "instructions", "annotations",
                      "properties", "body"):
             value = getattr(self, attr)
-            if value: props.append("%s=%r" % (attr, value))
+            if value:
+                props.append("%s=%r" % (attr, value))
         return "Message(%s)" % ", ".join(props)
diff --git a/python/proton/_reactor.py b/python/proton/_reactor.py
index fdffbaf..d11afd4 100644
--- a/python/proton/_reactor.py
+++ b/python/proton/_reactor.py
@@ -31,11 +31,11 @@ import uuid
 
 from cproton import PN_PYREF, PN_ACCEPTED, PN_EVENT_NONE
 
-from ._delivery import  Delivery
+from ._delivery import Delivery
 from ._endpoints import Connection, Endpoint, Link, Session, Terminus
 from ._exceptions import SSLUnavailable
 from ._data import Described, symbol, ulong
-from ._message import  Message
+from ._message import Message
 from ._transport import Transport, SSL, SSLDomain
 from ._url import Url
 from ._common import isstring, unicode2utf8, utf82unicode
@@ -100,6 +100,7 @@ class TimerSelectable(Selectable):
         self.deadline = self._reactor.timer_deadline
         self.update()
 
+
 class Reactor(object):
 
     def __init__(self, *handlers, **kwargs):
@@ -177,7 +178,8 @@ class Reactor(object):
         # TODO: Why do we timeout like this?
         self.timeout = 3.14159265359
         self.start()
-        while self.process(): pass
+        while self.process():
+            pass
         self.stop()
         self.process()
         # TODO: This isn't correct if we ever run again
@@ -195,7 +197,7 @@ class Reactor(object):
         self._selectable = TimerSelectable(self)
         self._selectable.deadline = self.timer_deadline
         # TODO set up fd to read for wakeups - but problematic on windows
-        #self._selectable.fileno(self._wakeup[0])
+        # self._selectable.fileno(self._wakeup[0])
         #self._selectable.reading = True
         self.update(self._selectable)
 
@@ -412,7 +414,7 @@ class EventInjector(object):
 
     def on_selectable_init(self, event):
         sel = event.context
-        #sel.fileno(self.fileno())
+        # sel.fileno(self.fileno())
         sel.reading = True
         sel.update()
 
@@ -492,11 +494,11 @@ class Transaction(object):
     a call to :meth:`proton.reactor.Container.declare_transaction`.
 
     To send messages under this transaction, use :meth:`send`.
-    
+
     To receive messages under this transaction, call :meth:`accept` once the
     message is received (typically from the
     :meth:`proton.handlers.MessagingHandler.on_message` callback).
-    
+
     To discharge the transaction, call either :meth:`commit`
     (for a successful transaction), or :meth:`abort` (for a failed transaction).
     """
@@ -633,6 +635,7 @@ class AtMostOnce(LinkOption):
     setting the sender link settle mode to :const:`proton.Link.SND_SETTLED`
     (ie pre-settled).
     """
+
     def apply(self, link):
         """
         Set the at-most-once delivery semantics on the link.
@@ -650,6 +653,7 @@ class AtLeastOnce(LinkOption):
     and the receiver link settle mode to :const:`proton.Link.RCV_FIRST`. This
     forces the receiver to settle all messages once they are successfully received.
     """
+
     def apply(self, link):
         """
         Set the at-least-once delivery semantics on the link.
@@ -665,6 +669,7 @@ class SenderOption(LinkOption):
     """
     Abstract class for sender options.
     """
+
     def apply(self, sender):
         """
         Set the option on the sender.
@@ -681,6 +686,7 @@ class ReceiverOption(LinkOption):
     """
     Abstract class for receiver options
     """
+
     def apply(self, receiver):
         """
         Set the option on the receiver.
@@ -702,6 +708,7 @@ class DynamicNodeProperties(LinkOption):
     :param props: A map of link options to be applied to a link.
     :type props: ``dict``
     """
+
     def __init__(self, props={}):
         self.properties = {}
         for k in props:
@@ -731,6 +738,7 @@ class Filter(ReceiverOption):
         containing the filter name, and the value a filter string.
     :type filter_set: ``dict``
     """
+
     def __init__(self, filter_set={}):
         self.filter_set = filter_set
 
@@ -755,7 +763,8 @@ class Selector(Filter):
     """
 
     def __init__(self, value, name='selector'):
-        super(Selector, self).__init__({symbol(name): Described(symbol('apache.org:selector-filter:string'), utf82unicode(value))})
+        super(Selector, self).__init__({symbol(name): Described(
+            symbol('apache.org:selector-filter:string'), utf82unicode(value))})
 
 
 class DurableSubscription(ReceiverOption):
@@ -765,6 +774,7 @@ class DurableSubscription(ReceiverOption):
     to :const:`proton.Terminus.DELIVERIES` and the source expiry policy to
     :const:`proton.Terminus.EXPIRE_NEVER`.
     """
+
     def apply(self, receiver):
         """
         Set durability on the specified receiver.
@@ -783,6 +793,7 @@ class Move(ReceiverOption):
     receivers. This is achieved by setting the receiver source distribution
     mode to :const:`proton.Terminus.DIST_MODE_MOVE`.
     """
+
     def apply(self, receiver):
         """
         Set message move semantics on the specified receiver.
@@ -800,6 +811,7 @@ class Copy(ReceiverOption):
     are. This is achieved by setting the receiver source distribution mode to
     :const:`proton.Terminus.DIST_MODE_COPY`.
     """
+
     def apply(self, receiver):
         """
         Set message copy semantics on the specified receiver.
@@ -814,9 +826,11 @@ def _apply_link_options(options, link):
     if options:
         if isinstance(options, list):
             for o in options:
-                if o.test(link): o.apply(link)
+                if o.test(link):
+                    o.apply(link)
         else:
-            if options.test(link): options.apply(link)
+            if options.test(link):
+                options.apply(link)
 
 
 def _create_session(connection, handler=None):
@@ -1030,7 +1044,7 @@ class _Connector(Handler):
             self._connect_sequence = ((delay, url) for delay in delay_iter(max_tries=1) for url in self.address)
         else:
             self._connect_sequence = ((delay, url) for delay in self.reconnect for url in self.address)
-        _, url = next(self._connect_sequence) # Ignore delay as we assume first delay must be 0
+        _, url = next(self._connect_sequence)  # Ignore delay as we assume first delay must be 0
         self._connect(event.connection, url)
 
     def on_connection_remote_open(self, event):
@@ -1040,10 +1054,11 @@ class _Connector(Handler):
         elif self.reconnect:
             self._connect_sequence = ((delay, url) for delay in self.reconnect for url in self.address)
         else:
-            self._connect_sequence = None # Help take out the garbage
+            self._connect_sequence = None  # Help take out the garbage
 
     def on_transport_closed(self, event):
         if self.connection is None:
+
             return
 
         if not self.connection.state & Endpoint.LOCAL_ACTIVE:
@@ -1088,6 +1103,7 @@ class SSLConfig(object):
         self.client.set_trusted_ca_db(certificate_db)
         self.server.set_trusted_ca_db(certificate_db)
 
+
 def _find_config_file():
     confname = 'connect.json'
     confpath = ['.', os.path.expanduser('~/.config/messaging'), '/etc/messaging']
@@ -1097,6 +1113,7 @@ def _find_config_file():
             return f
     return None
 
+
 def _get_default_config():
     conf = os.environ.get('MESSAGING_CONNECT_FILE') or _find_config_file()
     if conf and os.path.isfile(conf):
@@ -1107,24 +1124,27 @@ def _get_default_config():
     else:
         return {}
 
+
 def _strip_json_comments(json_text):
     """This strips c-style comments from text, taking into account '/*comments*/' and '//comments'
     nested inside a string etc."""
     def replacer(match):
         s = match.group(0)
         if s.startswith('/'):
-            return " " # note: a space and not an empty string
+            return " "  # note: a space and not an empty string
         else:
             return s
     pattern = re.compile(r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"', re.DOTALL | re.MULTILINE)
     return re.sub(pattern, replacer, json_text)
 
+
 def _get_default_port_for_scheme(scheme):
     if scheme == 'amqps':
         return 5671
     else:
         return 5672
 
+
 class Container(Reactor):
     """
     A representation of the AMQP concept of a 'container', which
@@ -1169,7 +1189,7 @@ class Container(Reactor):
         To use SSL/TLS for encryption (when an ``amqps`` URL scheme is used), the above
         configuration file must contain a ``tls`` submap containing the following
         configuration entries (See :class:`proton.SSLDomain` for details):
-        
+
         *   ``ca``: Path to a database of trusted CAs that the server will advertise.
         *   ``cert``: Path to a file/database containing the identifying certificate.
         *   ``key``: An optional key to access the identifying certificate.
@@ -1258,7 +1278,8 @@ class Container(Reactor):
         if not url and not urls and not address:
             config = _get_default_config()
             scheme = config.get('scheme', 'amqps')
-            _url = "%s://%s:%s" % (scheme, config.get('host', 'localhost'), config.get('port', _get_default_port_for_scheme(scheme)))
+            _url = "%s://%s:%s" % (scheme, config.get('host', 'localhost'),
+                                   config.get('port', _get_default_port_for_scheme(scheme)))
             _ssl_domain = None
             _kwargs = kwargs
             if config.get('user'):
diff --git a/python/proton/_tracing.py b/python/proton/_tracing.py
index a663bdf..c398a58 100644
--- a/python/proton/_tracing.py
+++ b/python/proton/_tracing.py
@@ -42,6 +42,7 @@ from proton.handlers import (
 _tracer = None
 _trace_key = proton.symbol('x-opt-qpid-tracestate')
 
+
 def get_tracer():
     global _tracer
     if _tracer is not None:
@@ -49,12 +50,14 @@ def get_tracer():
     exe = sys.argv[0] if sys.argv[0] else 'interactive-session'
     return init_tracer(os.path.basename(exe))
 
+
 def _fini_tracer():
     time.sleep(1)
     c = opentracing.global_tracer().close()
     while not c.done():
         time.sleep(0.5)
 
+
 def init_tracer(service_name):
     global _tracer
     if _tracer is not None:
@@ -95,6 +98,7 @@ class IncomingMessageHandler(ProtonIncomingMessageHandler):
                 with tracer.start_active_span('amqp-delivery-receive', ignore_active_span=True, tags=span_tags):
                     proton._events._dispatch(self.delegate, 'on_message', event)
 
+
 class OutgoingMessageHandler(ProtonOutgoingMessageHandler):
     def on_settled(self, event):
         if self.delegate is not None:
@@ -106,6 +110,7 @@ class OutgoingMessageHandler(ProtonOutgoingMessageHandler):
             span.finish()
             proton._events._dispatch(self.delegate, 'on_settled', event)
 
+
 class Sender(ProtonSender):
     def send(self, msg):
         tracer = get_tracer()
@@ -121,7 +126,7 @@ class Sender(ProtonSender):
         headers = {}
         tracer.inject(span, Format.TEXT_MAP, headers)
         if msg.annotations is None:
-            msg.annotations = { _trace_key: headers }
+            msg.annotations = {_trace_key: headers}
         else:
             msg.annotations[_trace_key] = headers
         delivery = ProtonSender.send(self, msg)
@@ -129,6 +134,7 @@ class Sender(ProtonSender):
         span.set_tag('delivery-tag', delivery.tag)
         return delivery
 
+
 # Monkey patch proton for tracing (need to patch both internal and external names)
 proton._handlers.IncomingMessageHandler = IncomingMessageHandler
 proton._handlers.OutgoingMessageHandler = OutgoingMessageHandler
diff --git a/python/proton/_transport.py b/python/proton/_transport.py
index fa2fe89..1b8272e 100644
--- a/python/proton/_transport.py
+++ b/python/proton/_transport.py
@@ -74,14 +74,12 @@ class Transport(Wrapper):
     TRACE_RAW = PN_TRACE_RAW
     """ Log raw binary data going in and out of the transport. """
 
-
     CLIENT = 1
     """ Transport mode is as a client. """
 
     SERVER = 2
     """ Transport mode is as a server. """
 
-
     @staticmethod
     def wrap(impl):
         if impl is None:
@@ -131,7 +129,7 @@ class Transport(Wrapper):
     def log(self, message):
         """
         Log a message using a transport's logging mechanism.
-        
+
         This can be useful in a debugging context as the log message will
         be prefixed with the transport's identifier.
 
@@ -201,7 +199,7 @@ class Transport(Wrapper):
     def user(self):
         """
         The authenticated user.
-
+
         On the client it will return whatever user was passed in to the
         :attr:`Connection.user` attribute of the bound connection.
 
@@ -279,7 +277,7 @@ class Transport(Wrapper):
         """
         Get the amount of free space for input following the transport's
         tail pointer.
-        
+
         :return: Available space for input in bytes.
         :rtype: ``int``
         :raise: :exc:`TransportException` if there is any Proton error.
@@ -639,7 +637,7 @@ class SASL(Wrapper):
 
         The returned value is only reliable after the ``PN_TRANSPORT_AUTHENTICATED``
         event has been received.
-        
+
         :rtype: The authentication mechanism selected by the SASL layer.
         """
         return pn_sasl_get_mech(self._sasl)
@@ -648,7 +646,7 @@ class SASL(Wrapper):
     def outcome(self):
         """
         Retrieve the outcome of SASL negotiation.
-        
+
         :rtype: * ``None`` if no negotiation has taken place.
                 * Otherwise the outcome of the negotiation.
         """
@@ -759,7 +757,6 @@ class SSLDomain(object):
     ANONYMOUS_PEER = PN_SSL_ANONYMOUS_PEER
     """Do not require a certificate nor cipher authorization."""
 
-
     def __init__(self, mode):
         self._domain = pn_ssl_domain(mode)
         if self._domain is None:
@@ -1033,7 +1030,7 @@ class SSL(object):
         """
         A convenience method to get a string that contains the :const:`CERT_COMMON_NAME`
         sub field of the subject field in the ssl certificate.
-        
+
         :return: A string containing the :const:`CERT_COMMON_NAME` sub field.
         :rtype: ``str``
         """
@@ -1043,7 +1040,7 @@ class SSL(object):
         """
         A convenience method to get a string that contains the :const:`CERT_ORGANIZATION_NAME`
         sub field of the subject field in the ssl certificate.
-        
+
         :return: A string containing the :const:`CERT_ORGANIZATION_NAME` sub field.
         :rtype: ``str``
         """
@@ -1053,7 +1050,7 @@ class SSL(object):
         """
         A convenience method to get a string that contains the :const:`CERT_ORGANIZATION_UNIT`
         sub field of the subject field in the ssl certificate.
-        
+
         :return: A string containing the :const:`CERT_ORGANIZATION_UNIT` sub field.
         :rtype: ``str``
         """
@@ -1063,7 +1060,7 @@ class SSL(object):
         """
         A convenience method to get a string that contains the :const:`CERT_CITY_OR_LOCALITY`
         sub field of the subject field in the ssl certificate.
-        
+
         :return: A string containing the :const:`CERT_CITY_OR_LOCALITY` sub field.
         :rtype: ``str``
         """
@@ -1073,7 +1070,7 @@ class SSL(object):
         """
         A convenience method to get a string that contains the :const:`CERT_COUNTRY_NAME`
         sub field of the subject field in the ssl certificate.
-        
+
         :return: A string containing the :const:`CERT_COUNTRY_NAME` sub field.
         :rtype: ``str``
         """
@@ -1083,7 +1080,7 @@ class SSL(object):
         """
         A convenience method to get a string that contains the :const:`CERT_STATE_OR_PROVINCE`
         sub field of the subject field in the ssl certificate.
-        
+
         :return: A string containing the :const:`CERT_STATE_OR_PROVINCE` sub field.
         :rtype: ``str``
         """
@@ -1121,7 +1118,7 @@ class SSL(object):
         """
         A convenience method to get the :const:`SHA1` fingerprint of the
         certificate.
-        
+
         :return: Hex fingerprint in a string, or ``None`` if an error occurred.
         :rtype: ``str`` or ``None``
         """
@@ -1131,7 +1128,7 @@ class SSL(object):
         """
         A convenience method to get the :const:`SHA256` fingerprint of the
         certificate.
-        
+
         :return: Hex fingerprint in a string, or ``None`` if an error occurred.
         :rtype: ``str`` or ``None``
         """
@@ -1142,7 +1139,7 @@ class SSL(object):
         """
         A convenience method to get the :const:`SHA512` fingerprint of the
         certificate.
-        
+
         :return: Hex fingerprint in a string, or ``None`` if an error occurred.
         :rtype: ``str`` or ``None``
         """
@@ -1153,7 +1150,7 @@ class SSL(object):
         """
         A convenience method to get the :const:`MD5` fingerprint of the
         certificate.
-        
+
         :return: Hex fingerprint in a string, or ``None`` if an error occurred.
         :rtype: ``str`` or ``None``
         """
@@ -1239,7 +1236,7 @@ class SSLSessionDetails(object):
     def get_session_id(self):
         """
         Get the unique identifier for this SSL session
-        
+
         :return: Session identifier
         :rtype: ``str``
         """
diff --git a/python/proton/_url.py b/python/proton/_url.py
index 2388912..2da0001 100644
--- a/python/proton/_url.py
+++ b/python/proton/_url.py
@@ -50,7 +50,7 @@ class Url(object):
     :ivar ~.host: Host name, ipv6 literal or ipv4 dotted quad.
     :ivar ~.port: Integer port.
     :ivar host_port: Returns host:port
-    
+
     :param url: URL string to parse.
     :type url: ``str``
     :param defaults: If ``True``, fill in missing default values in the URL.
@@ -66,7 +66,6 @@ class Url(object):
     AMQP = "amqp"
     """URL scheme for the AMQP protocol."""
 
-
     class Port(int):
         """An integer port number that can be constructed from a service name string"""
 
@@ -121,7 +120,8 @@ class Url(object):
                 if '/' in p[0] or not p[2].startswith('//'):
                     url = '//' + url
             u = urlparse(url)
-            if not u: raise ValueError("Invalid URL '%s'" % url)
+            if not u:
+                raise ValueError("Invalid URL '%s'" % url)
             self.scheme = None if not u.scheme else u.scheme
             self.username = u.username and unquote(u.username)
             self.password = u.password and unquote(u.password)
@@ -143,7 +143,8 @@ class Url(object):
         for k in kwargs:  # Let kwargs override values parsed from url
             getattr(self, k)  # Check for invalid kwargs
             setattr(self, k, kwargs[k])
-        if defaults: self.defaults()
+        if defaults:
+            self.defaults()
 
     @staticmethod
     def _parse_host_port(nl):
@@ -152,7 +153,7 @@ class Url(object):
         beforebrace = hostportsplit[0]
         afterbrace = hostportsplit[-1]
 
-        if len(hostportsplit)==1:
+        if len(hostportsplit) == 1:
             beforebrace = ''
         else:
             beforebrace += ']'
diff --git a/python/proton/_utils.py b/python/proton/_utils.py
index 5100f4c..ee7c267 100644
--- a/python/proton/_utils.py
+++ b/python/proton/_utils.py
@@ -90,6 +90,7 @@ class BlockingSender(BlockingLink):
     A synchronous sender wrapper. This is typically created by calling
     :meth:`BlockingConnection.create_sender`.
     """
+
     def __init__(self, connection, sender):
         super(BlockingSender, self).__init__(connection, sender)
         if self.link.target and self.link.target.address and self.link.target.address != self.link.remote_target.address:
@@ -137,6 +138,7 @@ class Fetcher(MessagingHandler):
     :param prefetch:
     :type prefetch:
     """
+
     def __init__(self, connection, prefetch):
         super(Fetcher, self).__init__(prefetch=prefetch, auto_accept=False)
         self.connection = connection
@@ -198,6 +200,7 @@ class BlockingReceiver(BlockingLink):
     A synchronous receiver wrapper. This is typically created by calling
     :meth:`BlockingConnection.create_receiver`.
     """
+
     def __init__(self, connection, receiver, fetcher, credit=1):
         super(BlockingReceiver, self).__init__(connection, receiver)
         if self.link.source and self.link.source.address and self.link.source.address != self.link.remote_source.address:
@@ -206,7 +209,8 @@ class BlockingReceiver(BlockingLink):
             # ...but close ourselves if peer does not
             self.link.close()
             raise LinkException("Failed to open receiver %s, source does not match" % self.link.name)
-        if credit: receiver.flow(credit)
+        if credit:
+            receiver.flow(credit)
         self.fetcher = fetcher
         self.container = connection.container
 
@@ -287,6 +291,7 @@ class LinkDetached(LinkException):
     :param link: The link which closed unexpectedly.
     :type link: :class:`proton.Link`
     """
+
     def __init__(self, link):
         self.link = link
         if link.is_sender:
@@ -310,6 +315,7 @@ class ConnectionClosed(ConnectionException):
     :param connection: The connection which closed unexpectedly.
     :type connection: :class:`proton.Connection`
     """
+
     def __init__(self, connection):
         self.connection = connection
         txt = "Connection %s closed" % connection.hostname
@@ -459,7 +465,8 @@ class BlockingConnection(Handler):
         """
         Hand control over to the event loop (e.g. if waiting indefinitely for incoming messages)
         """
-        while self.container.process(): pass
+        while self.container.process():
+            pass
         self.container.stop()
         self.container.process()
 
@@ -490,7 +497,8 @@ class BlockingConnection(Handler):
                     self.container.process()
                     if deadline < time.time():
                         txt = "Connection %s timed out" % self.url
-                        if msg: txt += ": " + msg
+                        if msg:
+                            txt += ": " + msg
                         raise Timeout(txt)
             finally:
                 self.container.timeout = container_timeout
diff --git a/python/proton/_wrapper.py b/python/proton/_wrapper.py
index 1e7a33a..4703b34 100644
--- a/python/proton/_wrapper.py
+++ b/python/proton/_wrapper.py
@@ -91,7 +91,8 @@ class Wrapper(object):
         self.__dict__["_impl"] = impl
         self.__dict__["_attrs"] = attrs
         self.__dict__["_record"] = record
-        if init: self._init()
+        if init:
+            self._init()
 
     def __getattr__(self, name):
         attrs = self.__dict__["_attrs"]
diff --git a/python/setuputils/log.py b/python/setuputils/log.py
index f11b255..06b8e50 100644
--- a/python/setuputils/log.py
+++ b/python/setuputils/log.py
@@ -1,19 +1,19 @@
-#-----------------------------------------------------------------------------
+# -----------------------------------------------------------------------------
 #  Copyright (C) PyZMQ Developers
 #  Distributed under the terms of the Modified BSD License.
 #
 #  This bundling code is largely adapted from pyzmq-static's get.sh by
 #  Brandon Craig-Rhodes, which is itself BSD licensed.
-#-----------------------------------------------------------------------------
+# -----------------------------------------------------------------------------
 
-#-----------------------------------------------------------------------------
+# -----------------------------------------------------------------------------
 # Logging (adapted from h5py: http://h5py.googlecode.com)
-#-----------------------------------------------------------------------------
+# -----------------------------------------------------------------------------
 
-#-----------------------------------------------------------------------------
+# -----------------------------------------------------------------------------
 #  This log code is largely adapted from pyzmq's code
 #  PyZMQ Developers, which is itself Modified BSD licensed.
-#-----------------------------------------------------------------------------
+# -----------------------------------------------------------------------------
 
 
 import os
diff --git a/python/setuputils/misc.py b/python/setuputils/misc.py
index 1aa5556..009190d 100644
--- a/python/setuputils/misc.py
+++ b/python/setuputils/misc.py
@@ -1,15 +1,15 @@
-#-----------------------------------------------------------------------------
+# -----------------------------------------------------------------------------
 #  Copyright (C) PyZMQ Developers
 #  Distributed under the terms of the Modified BSD License.
 #
 #  This bundling code is largely adapted from pyzmq-static's get.sh by
 #  Brandon Craig-Rhodes, which is itself BSD licensed.
-#-----------------------------------------------------------------------------
+# -----------------------------------------------------------------------------
 
-#-----------------------------------------------------------------------------
+# -----------------------------------------------------------------------------
 #  These functions were largely adapted from pyzmq's code
 #  PyZMQ Developers, which is itself Modified BSD licensed.
-#-----------------------------------------------------------------------------
+# -----------------------------------------------------------------------------
 
 
 import errno
@@ -19,6 +19,7 @@ import sys
 
 from . import log
 
+
 def _call_pkg_config(args):
     """Spawn a subprocess running pkg-config with the given args.
 
@@ -39,7 +40,6 @@ def _call_pkg_config(args):
     return None
 
 
-
 def pkg_config_version_installed(package, version=None, atleast=None):
     """Check if version of a package is is installed
 
@@ -60,7 +60,7 @@ def pkg_config_version_installed(package, version=None, atleast=None):
                                                version or atleast),
                           package])
     if p:
-        out,err = p.communicate()
+        out, err = p.communicate()
         if p.returncode:
             log.info("Did not find %s via pkg-config: %s" % (package, err))
             return False
@@ -78,9 +78,8 @@ def pkg_config_get_var(package, name):
     if not p:
         log.warn("pkg-config: var %s get failed, package %s", name, package)
         return ""
-    out,err = p.communicate()
+    out, err = p.communicate()
     if p.returncode:
         out = ""
         log.warn(err)
     return out.splitlines()[0]
-
diff --git a/python/tests/proton_tests/__main__.py b/python/tests/proton_tests/__main__.py
index 00697b7..6c1fea5 100644
--- a/python/tests/proton_tests/__main__.py
+++ b/python/tests/proton_tests/__main__.py
@@ -20,4 +20,4 @@
 from proton_tests.main import main
 
 if __name__ == '__main__':
-  main()
+    main()
diff --git a/python/tests/proton_tests/codec.py b/python/tests/proton_tests/codec.py
index e3bffe5..b63e1d6 100644
--- a/python/tests/proton_tests/codec.py
+++ b/python/tests/proton_tests/codec.py
@@ -27,493 +27,504 @@ from proton._compat import raise_
 
 from . import common
 
+
 class Test(common.Test):
 
-  def setUp(self):
-    self.data = Data()
+    def setUp(self):
+        self.data = Data()
+
+    def tearDown(self):
+        self.data = None
 
-  def tearDown(self):
-    self.data = None
 
 class DataTest(Test):
 
-  def testTopLevelNext(self):
-    assert self.data.next() is None
-    self.data.put_null()
-    self.data.put_bool(False)
-    self.data.put_int(0)
-    assert self.data.next() is None
-    self.data.rewind()
-    assert self.data.next() == Data.NULL
-    assert self.data.next() == Data.BOOL
-    assert self.data.next() == Data.INT
-    assert self.data.next() is None
-
-  def testNestedNext(self):
-    assert self.data.next() is None
-    self.data.put_null()
-    assert self.data.next() is None
-    self.data.put_list()
-    assert self.data.next() is None
-    self.data.put_bool(False)
-    assert self.data.next() is None
-    self.data.rewind()
-    assert self.data.next() is Data.NULL
-    assert self.data.next() is Data.LIST
-    self.data.enter()
-    assert self.data.next() is None
-    self.data.put_ubyte(0)
-    assert self.data.next() is None
-    self.data.put_uint(0)
-    assert self.data.next() is None
-    self.data.put_int(0)
-    assert self.data.next() is None
-    self.data.exit()
-    assert self.data.next() is Data.BOOL
-    assert self.data.next() is None
-
-    self.data.rewind()
-    assert self.data.next() is Data.NULL
-    assert self.data.next() is Data.LIST
-    assert self.data.enter()
-    assert self.data.next() is Data.UBYTE
-    assert self.data.next() is Data.UINT
-    assert self.data.next() is Data.INT
-    assert self.data.next() is None
-    assert self.data.exit()
-    assert self.data.next() is Data.BOOL
-    assert self.data.next() is None
-
-  def testEnterExit(self):
-    assert self.data.next() is None
-    assert not self.data.enter()
-    self.data.put_list()
-    assert self.data.enter()
-    assert self.data.next() is None
-    self.data.put_list()
-    assert self.data.enter()
-    self.data.put_list()
-    assert self.data.enter()
-    assert self.data.exit()
-    assert self.data.get_list() == 0
-    assert self.data.exit()
-    assert self.data.get_list() == 1
-    assert self.data.exit()
-    assert self.data.get_list() == 1
-    assert not self.data.exit()
-    assert self.data.get_list() == 1
-    assert self.data.next() is None
-
-    self.data.rewind()
-    assert self.data.next() is Data.LIST
-    assert self.data.get_list() == 1
-    assert self.data.enter()
-    assert self.data.next() is Data.LIST
-    assert self.data.get_list() == 1
-    assert self.data.enter()
-    assert self.data.next() is Data.LIST
-    assert self.data.get_list() == 0
-    assert self.data.enter()
-    assert self.data.next() is None
-    assert self.data.exit()
-    assert self.data.get_list() == 0
-    assert self.data.exit()
-    assert self.data.get_list() == 1
-    assert self.data.exit()
-    assert self.data.get_list() == 1
-    assert not self.data.exit()
-
-
-  def put(self, putter, v):
-    """More informative exception from putters, include bad value"""
-    try:
-      putter(v)
-    except Exception:
-      etype, value, trace = sys.exc_info()
-      raise_(etype, etype("%s(%r): %s" % (putter.__name__, v, value)), trace)
-    return putter
-
-  # (bits, signed) for each integer type
-  INT_TYPES = {
-    "byte": (8, True),
-    "ubyte": (8, False),
-    "short": (16, True),
-    "ushort": (16, False),
-    "int": (32, True),
-    "uint": (32, False),
-    "long": (64, True),
-    "ulong": (64, False)
-  }
-
-  def int_values(self, dtype):
-    """Set of test values for integer type dtype, include extreme and medial values"""
-    bits, signed = self.INT_TYPES[dtype]
-    values = [0, 1, 2, 5, 42]
-    if signed:
-      min, max = -2**(bits-1), 2**(bits-1)-1
-      values.append(max // 2)
-      values += [-i for i in values if i]
-      values += [min, max]
-    else:
-      max = 2**(bits) - 1
-      values += [max // 2, max]
-    return sorted(values)
-
-  def _testArray(self, dtype, descriptor, atype, *values):
-    if dtype: dTYPE = getattr(self.data, dtype.upper())
-    aTYPE = getattr(self.data, atype.upper())
-    self.data.put_array(dtype is not None, aTYPE)
-    self.data.enter()
-    if dtype is not None:
-      putter = getattr(self.data, "put_%s" % dtype)
-      self.put(putter, descriptor)
-    putter = getattr(self.data, "put_%s" % atype)
-    for v in values:
-      self.put(putter, v)
-    self.data.exit()
-    self.data.rewind()
-    assert self.data.next() == Data.ARRAY
-    count, described, type = self.data.get_array()
-    assert count == len(values), count
-    if dtype is None:
-      assert described == False
-    else:
-      assert described == True
-    assert type == aTYPE, type
-    assert self.data.enter()
-    if described:
-      assert self.data.next() == dTYPE
-      getter = getattr(self.data, "get_%s" % dtype)
-      gotten = getter()
-      assert gotten == descriptor, gotten
-    if values:
-      getter = getattr(self.data, "get_%s" % atype)
-      for v in values:
-        assert self.data.next() == aTYPE
-        gotten = getter()
-        assert gotten == v, gotten
-    assert self.data.next() is None
-    assert self.data.exit()
-
-  def testStringArray(self):
-    self._testArray(None, None, "string", "one", "two", "three")
-
-  def testDescribedStringArray(self):
-    self._testArray("symbol", "url", "string", "one", "two", "three")
-
-  def _test_int_array(self, atype):
-    self._testArray(None, None, atype, *self.int_values(atype))
-
-  def testByteArray(self): self._test_int_array("byte")
-  def testUbyteArray(self): self._test_int_array("ubyte")
-  def testShortArray(self): self._test_int_array("short")
-  def testUshortArray(self): self._test_int_array("ushort")
-  def testIntArray(self): self._test_int_array("int")
-  def testUintArray(self): self._test_int_array("uint")
-  def testLongArray(self): self._test_int_array("long")
-  def testUlongArray(self): self._test_int_array("ulong")
-
-  def testUUIDArray(self):
-    self._testArray(None, None, "uuid", uuid4(), uuid4(), uuid4())
-
-  def testEmptyArray(self):
-    self._testArray(None, None, "null")
-
-  def testDescribedEmptyArray(self):
-    self._testArray("long", 0, "null")
-
-  def testPropertyDict(self):
-    a = PropertyDict(one=1, two=2, three=3)
-    b = PropertyDict({'one': 1, 'two': 2, 'three': 3})
-    c = PropertyDict(zip(['one', 'two', 'three'], [1, 2, 3]))
-    d = PropertyDict([('two', 2), ('one', 1), ('three', 3)])
-    e = PropertyDict({symbol('three'): 3, symbol('one'): 1, symbol('two'): 2})
-    f = PropertyDict(a)
-    g = PropertyDict()
-    g['one'] = 1
-    g[symbol('two')] = 2
-    g['three'] = 3
-    assert a == b == c == d == e == f == g
-    for k in a.keys():
-        assert isinstance(k, symbol)
-    self.assertRaises(KeyError, AnnotationDict, {'one': 1, None: 'none'})
-    self.assertRaises(KeyError, AnnotationDict, {'one': 1, 1.23: 4})
-
-  def testPropertyDictNoRaiseError(self):
-    a = PropertyDict(one=1, two=2, three=3, raise_on_error=False)
-    a[4] = 'four'
-    b = PropertyDict({'one': 1, 'two': 2, 'three': 3, 4: 'four'}, raise_on_error=False)
-    c = PropertyDict(zip(['one', 'two', 'three', 4], [1, 2, 3, 'four']), raise_on_error=False)
-    d = PropertyDict([('two', 2), ('one', 1), ('three', 3), (4, 'four')], raise_on_error=False)
-    e = PropertyDict({4: 'four', symbol('three'): 3, symbol('one'): 1, symbol('two'): 2}, raise_on_error=False)
-    f = PropertyDict(a, raise_on_error=False)
-    g = PropertyDict(raise_on_error=False)
-    g['one'] = 1
-    g[4] = 'four'
-    g[symbol('two')] = 2
-    g['three'] = 3
-    assert a == b == c == d == e == f == g
-
-  def testAnnotationDict(self):
-    # AnnotationMap c'tor calls update(), so this method is also covered
-    a = AnnotationDict(one=1, two=2, three=3)
-    a[ulong(4)] = 'four'
-    b = AnnotationDict({'one': 1, 'two': 2, 'three': 3, ulong(4): 'four'})
-    c = AnnotationDict(zip(['one', 'two', 'three', ulong(4)], [1, 2, 3, 'four']))
-    d = AnnotationDict([('two', 2), ('one', 1), ('three', 3), (ulong(4), 'four')])
-    e = AnnotationDict({symbol('three'): 3, ulong(4): 'four', symbol('one'): 1, symbol('two'): 2})
-    f = AnnotationDict(a)
-    g = AnnotationDict()
-    g[ulong(4)] = 'four'
-    g['one'] = 1
-    g[symbol('two')] = 2
-    g['three'] = 3
-    assert a == b == c == d == e == f == g
-    for k in a.keys():
-        assert isinstance(k, (symbol, ulong))
-    self.assertRaises(KeyError, AnnotationDict, {'one': 1, None: 'none'})
-    self.assertRaises(KeyError, AnnotationDict, {'one': 1, 1.23: 4})
-
-  def testAnnotationDictNoRaiseError(self):
-    a = AnnotationDict(one=1, two=2, three=3, raise_on_error=False)
-    a[ulong(4)] = 'four'
-    a[5] = 'five'
-    b = AnnotationDict({'one': 1, 'two': 2, 'three': 3, ulong(4): 'four', 5: 'five'}, raise_on_error=False)
-    c = AnnotationDict(zip(['one', 'two', 'three', ulong(4), 5], [1, 2, 3, 'four', 'five']), raise_on_error=False)
-    d = AnnotationDict([('two', 2), ('one', 1), ('three', 3), (ulong(4), 'four'), (5, 'five')], raise_on_error=False)
-    e = AnnotationDict({5: 'five', symbol('three'): 3, ulong(4): 'four', symbol('one'): 1, symbol('two'): 2}, raise_on_error=False)
-    f = AnnotationDict(a, raise_on_error=False)
-    g = AnnotationDict(raise_on_error=False)
-    g[ulong(4)] = 'four'
-    g['one'] = 1
-    g[symbol('two')] = 2
-    g[5] = 'five'
-    g['three'] = 3
-    assert a == b == c == d == e == f == g
-
-  def testSymbolList(self):
-    a = SymbolList(['one', 'two', 'three'])
-    b = SymbolList([symbol('one'), symbol('two'), symbol('three')])
-    c = SymbolList()
-    c.append('one')
-    c.extend([symbol('two'), 'three'])
-    d1 = SymbolList(['one'])
-    d2 = SymbolList(['two', symbol('three')])
-    d = d1 + d2
-    e = SymbolList(['one'])
-    e += SymbolList(['two', symbol('three')])
-    f = SymbolList(['one', 'hello', 'goodbye'])
-    f[1] = symbol('two')
-    f[2] = 'three'
-    g = SymbolList(a)
-    assert a == b == c == d == e == f == g
-    for v in a:
-        assert isinstance(v, symbol)
-    self.assertRaises(TypeError, SymbolList, ['one', None])
-    self.assertRaises(TypeError, SymbolList, ['one', 2])
-    self.assertRaises(TypeError, SymbolList, ['one', ['two']])
-    self.assertRaises(TypeError, SymbolList, ['one', {'two': 3}])
-
-  def testSymbolListNoRaiseError(self):
-    a = SymbolList(['one', 'two', 'three', 4], raise_on_error=False)
-    b = SymbolList([symbol('one'), symbol('two'), symbol('three'), 4], raise_on_error=False)
-    c = SymbolList(raise_on_error=False)
-    c.append('one')
-    c.extend([symbol('two'), 'three', 4])
-    d1 = SymbolList(['one'], raise_on_error=False)
-    d2 = SymbolList(['two', symbol('three'), 4], raise_on_error=False)
-    d = d1 + d2
-    e = SymbolList(['one'], raise_on_error=False)
-    e += SymbolList(['two', symbol('three'), 4], raise_on_error=False)
-    f = SymbolList(['one', 'hello', 'goodbye', 'what?'], raise_on_error=False)
-    f[1] = symbol('two')
-    f[2] = 'three'
-    f[3] = 4
-    g = SymbolList(a, raise_on_error=False)
-    assert a == b == c == d == e == f == g
-
-  def _test(self, dtype, *values, **kwargs):
-    eq=kwargs.get("eq", lambda x, y: x == y)
-    ntype = getattr(Data, dtype.upper())
-    putter = getattr(self.data, "put_%s" % dtype)
-    getter = getattr(self.data, "get_%s" % dtype)
-
-    for v in values:
-      self.put(putter, v)
-      gotten = getter()
-      assert eq(gotten, v), (gotten, v)
-
-    self.data.rewind()
-
-    for v in values:
-      vtype = self.data.next()
-      assert vtype == ntype, vtype
-      gotten = getter()
-      assert eq(gotten, v), (gotten, v)
-
-    encoded = self.data.encode()
-    copy = Data(0)
-    while encoded:
-      n = copy.decode(encoded)
-      encoded = encoded[n:]
-    copy.rewind()
-
-    cgetter = getattr(copy, "get_%s" % dtype)
-
-    for v in values:
-      vtype = copy.next()
-      assert vtype == ntype, vtype
-      gotten = cgetter()
-      assert eq(gotten, v), (gotten, v)
-
-  def _test_int(self, itype):
-    self._test(itype, *self.int_values(itype))
-
-  def testByte(self): self._test_int("byte")
-  def testUbyte(self):
-    self._test_int("ubyte")
-    self.assertRaises(AssertionError, ubyte, -1)
-  def testShort(self): self._test_int("short")
-  def testUshort(self):
-    self._test("ushort")
-    self.assertRaises(AssertionError, ushort, -1)
-  def testInt(self): self._test_int("int")
-  def testUint(self):
-    self._test_int("uint")
-    self.assertRaises(AssertionError, uint, -1)
-  def testLong(self): self._test_int("long")
-  def testUlong(self):
-    self._test_int("ulong")
-    self.assertRaises(AssertionError, ulong, -1)
-
-  def testString(self):
-    self._test("string", "one", "two", "three", "this is a test", "")
-
-  def testFloat(self):
-    # we have to use a special comparison here because python
-    # internally only uses doubles and converting between floats and
-    # doubles is imprecise
-    self._test("float", 0, 1, 2, 3, 0.1, 0.2, 0.3, -1, -2, -3, -0.1, -0.2, -0.3,
-               eq=lambda x, y: x - y < 0.000001)
-
-  def testDouble(self):
-    self._test("double", 0, 1, 2, 3, 0.1, 0.2, 0.3, -1, -2, -3, -0.1, -0.2, -0.3)
-
-  def testBinary(self):
-    self._test("binary", b"this", b"is", b"a", b"test",b"of" b"b\x00inary")
-
-  def testSymbol(self):
-    self._test("symbol", symbol("this is a symbol test"), symbol("bleh"), symbol("blah"))
-
-  def testTimestamp(self):
-    self._test("timestamp", timestamp(0), timestamp(12345), timestamp(1000000))
-
-  def testChar(self):
-    self._test("char", char('a'), char('b'), char('c'), char(u'\u20AC'))
-
-  def testUUID(self):
-    self._test("uuid", uuid4(), uuid4(), uuid4())
-
-  def testDecimal32(self):
-    self._test("decimal32", decimal32(0), decimal32(1), decimal32(2), decimal32(3), decimal32(4), decimal32(2**30))
-
-  def testDecimal64(self):
-    self._test("decimal64", decimal64(0), decimal64(1), decimal64(2), decimal64(3), decimal64(4), decimal64(2**60))
-
-  def testDecimal128(self):
-    self._test("decimal128", decimal128(b"fdsaasdf;lkjjkl;"), decimal128(b"x"*16))
-
-  def testCopy(self):
-    self.data.put_described()
-    self.data.enter()
-    self.data.put_ulong(123)
-    self.data.put_map()
-    self.data.enter()
-    self.data.put_string("pi")
-    self.data.put_double(3.14159265359)
-
-    dst = Data()
-    dst.copy(self.data)
-
-    copy = dst.format()
-    orig = self.data.format()
-    assert copy == orig, (copy, orig)
-
-  def testCopyNested(self):
-    nested = [1, 2, 3, [4, 5, 6], 7, 8, 9]
-    self.data.put_object(nested)
-    dst = Data()
-    dst.copy(self.data)
-    assert dst.format() == self.data.format()
-
-  def testCopyNestedArray(self):
-    nested = [Array(UNDESCRIBED, Data.LIST,
-                    ["first", [Array(UNDESCRIBED, Data.INT, 1,2,3)]],
-                    ["second", [Array(UNDESCRIBED, Data.INT, 1,2,3)]],
-                    ["third", [Array(UNDESCRIBED, Data.INT, 1,2,3)]],
-                    ),
-              "end"]
-    self.data.put_object(nested)
-    dst = Data()
-    dst.copy(self.data)
-    assert dst.format() == self.data.format()
-
-  def testRoundTrip(self):
-    obj = {symbol("key"): timestamp(1234),
-           ulong(123): "blah",
-           char("c"): "bleh",
-           u"desc": Described(symbol("url"), u"http://example.org"),
-           u"array": Array(UNDESCRIBED, Data.INT, 1, 2, 3),
-           u"list": [1, 2, 3, None, 4],
-           u"boolean": True}
-    self.data.put_object(obj)
-    enc = self.data.encode()
-    data = Data()
-    data.decode(enc)
-    data.rewind()
-    assert data.next()
-    copy = data.get_object()
-    assert copy == obj, (copy, obj)
-
-  def testBuffer(self):
-    try:
-      self.data.put_object(buffer(b"foo"))
-    except NameError:
-      # python >= 3.0 does not have `buffer`
-      return
-    data = Data()
-    data.decode(self.data.encode())
-    data.rewind()
-    assert data.next()
-    assert data.type() == Data.BINARY
-    assert data.get_object() == b"foo"
-
-  def testMemoryView(self):
-    self.data.put_object(memoryview(b"foo"))
-    data = Data()
-    data.decode(self.data.encode())
-    data.rewind()
-    assert data.next()
-    assert data.type() == Data.BINARY
-    assert data.get_object() == b"foo"
-
-  def testLookup(self):
-    obj = {symbol("key"): u"value",
-           symbol("pi"): 3.14159,
-           symbol("list"): [1, 2, 3, 4]}
-    self.data.put_object(obj)
-    self.data.rewind()
-    self.data.next()
-    self.data.enter()
-    self.data.narrow()
-    assert self.data.lookup("pi")
-    assert self.data.get_object() == 3.14159
-    self.data.rewind()
-    assert self.data.lookup("key")
-    assert self.data.get_object() == u"value"
-    self.data.rewind()
-    assert self.data.lookup("list")
-    assert self.data.get_object() == [1, 2, 3, 4]
-    self.data.widen()
-    self.data.rewind()
-    assert not self.data.lookup("pi")
+    def testTopLevelNext(self):
+        assert self.data.next() is None
+        self.data.put_null()
+        self.data.put_bool(False)
+        self.data.put_int(0)
+        assert self.data.next() is None
+        self.data.rewind()
+        assert self.data.next() == Data.NULL
+        assert self.data.next() == Data.BOOL
+        assert self.data.next() == Data.INT
+        assert self.data.next() is None
+
+    def testNestedNext(self):
+        assert self.data.next() is None
+        self.data.put_null()
+        assert self.data.next() is None
+        self.data.put_list()
+        assert self.data.next() is None
+        self.data.put_bool(False)
+        assert self.data.next() is None
+        self.data.rewind()
+        assert self.data.next() is Data.NULL
+        assert self.data.next() is Data.LIST
+        self.data.enter()
+        assert self.data.next() is None
+        self.data.put_ubyte(0)
+        assert self.data.next() is None
+        self.data.put_uint(0)
+        assert self.data.next() is None
+        self.data.put_int(0)
+        assert self.data.next() is None
+        self.data.exit()
+        assert self.data.next() is Data.BOOL
+        assert self.data.next() is None
+
+        self.data.rewind()
+        assert self.data.next() is Data.NULL
+        assert self.data.next() is Data.LIST
+        assert self.data.enter()
+        assert self.data.next() is Data.UBYTE
+        assert self.data.next() is Data.UINT
+        assert self.data.next() is Data.INT
+        assert self.data.next() is None
+        assert self.data.exit()
+        assert self.data.next() is Data.BOOL
+        assert self.data.next() is None
+
+    def testEnterExit(self):
+        assert self.data.next() is None
+        assert not self.data.enter()
+        self.data.put_list()
+        assert self.data.enter()
+        assert self.data.next() is None
+        self.data.put_list()
+        assert self.data.enter()
+        self.data.put_list()
+        assert self.data.enter()
+        assert self.data.exit()
+        assert self.data.get_list() == 0
+        assert self.data.exit()
+        assert self.data.get_list() == 1
+        assert self.data.exit()
+        assert self.data.get_list() == 1
+        assert not self.data.exit()
+        assert self.data.get_list() == 1
+        assert self.data.next() is None
+
+        self.data.rewind()
+        assert self.data.next() is Data.LIST
+        assert self.data.get_list() == 1
+        assert self.data.enter()
+        assert self.data.next() is Data.LIST
+        assert self.data.get_list() == 1
+        assert self.data.enter()
+        assert self.data.next() is Data.LIST
+        assert self.data.get_list() == 0
+        assert self.data.enter()
+        assert self.data.next() is None
+        assert self.data.exit()
+        assert self.data.get_list() == 0
+        assert self.data.exit()
+        assert self.data.get_list() == 1
+        assert self.data.exit()
+        assert self.data.get_list() == 1
+        assert not self.data.exit()
+
+    def put(self, putter, v):
+        """More informative exception from putters, include bad value"""
+        try:
+            putter(v)
+        except Exception:
+            etype, value, trace = sys.exc_info()
+            raise_(etype, etype("%s(%r): %s" % (putter.__name__, v, value)), trace)
+        return putter
+
+    # (bits, signed) for each integer type
+    INT_TYPES = {
+        "byte": (8, True),
+        "ubyte": (8, False),
+        "short": (16, True),
+        "ushort": (16, False),
+        "int": (32, True),
+        "uint": (32, False),
+        "long": (64, True),
+        "ulong": (64, False)
+    }
+
+    def int_values(self, dtype):
+        """Set of test values for integer type dtype, include extreme and medial values"""
+        bits, signed = self.INT_TYPES[dtype]
+        values = [0, 1, 2, 5, 42]
+        if signed:
+            min, max = -2**(bits-1), 2**(bits-1)-1
+            values.append(max // 2)
+            values += [-i for i in values if i]
+            values += [min, max]
+        else:
+            max = 2**(bits) - 1
+            values += [max // 2, max]
+        return sorted(values)
+
+    def _testArray(self, dtype, descriptor, atype, *values):
+        if dtype:
+            dTYPE = getattr(self.data, dtype.upper())
+        aTYPE = getattr(self.data, atype.upper())
+        self.data.put_array(dtype is not None, aTYPE)
+        self.data.enter()
+        if dtype is not None:
+            putter = getattr(self.data, "put_%s" % dtype)
+            self.put(putter, descriptor)
+        putter = getattr(self.data, "put_%s" % atype)
+        for v in values:
+            self.put(putter, v)
+        self.data.exit()
+        self.data.rewind()
+        assert self.data.next() == Data.ARRAY
+        count, described, type = self.data.get_array()
+        assert count == len(values), count
+        if dtype is None:
+            assert described == False
+        else:
+            assert described == True
+        assert type == aTYPE, type
+        assert self.data.enter()
+        if described:
+            assert self.data.next() == dTYPE
+            getter = getattr(self.data, "get_%s" % dtype)
+            gotten = getter()
+            assert gotten == descriptor, gotten
+        if values:
+            getter = getattr(self.data, "get_%s" % atype)
+            for v in values:
+                assert self.data.next() == aTYPE
+                gotten = getter()
+                assert gotten == v, gotten
+        assert self.data.next() is None
+        assert self.data.exit()
+
+    def testStringArray(self):
+        self._testArray(None, None, "string", "one", "two", "three")
+
+    def testDescribedStringArray(self):
+        self._testArray("symbol", "url", "string", "one", "two", "three")
+
+    def _test_int_array(self, atype):
+        self._testArray(None, None, atype, *self.int_values(atype))
+
+    def testByteArray(self): self._test_int_array("byte")
+    def testUbyteArray(self): self._test_int_array("ubyte")
+    def testShortArray(self): self._test_int_array("short")
+    def testUshortArray(self): self._test_int_array("ushort")
+    def testIntArray(self): self._test_int_array("int")
+    def testUintArray(self): self._test_int_array("uint")
+    def testLongArray(self): self._test_int_array("long")
+    def testUlongArray(self): self._test_int_array("ulong")
+
+    def testUUIDArray(self):
+        self._testArray(None, None, "uuid", uuid4(), uuid4(), uuid4())
+
+    def testEmptyArray(self):
+        self._testArray(None, None, "null")
+
+    def testDescribedEmptyArray(self):
+        self._testArray("long", 0, "null")
+
+    def testPropertyDict(self):
+        a = PropertyDict(one=1, two=2, three=3)
+        b = PropertyDict({'one': 1, 'two': 2, 'three': 3})
+        c = PropertyDict(zip(['one', 'two', 'three'], [1, 2, 3]))
+        d = PropertyDict([('two', 2), ('one', 1), ('three', 3)])
+        e = PropertyDict({symbol('three'): 3, symbol('one'): 1, symbol('two'): 2})
+        f = PropertyDict(a)
+        g = PropertyDict()
+        g['one'] = 1
+        g[symbol('two')] = 2
+        g['three'] = 3
+        assert a == b == c == d == e == f == g
+        for k in a.keys():
+            assert isinstance(k, symbol)
+        self.assertRaises(KeyError, AnnotationDict, {'one': 1, None: 'none'})
+        self.assertRaises(KeyError, AnnotationDict, {'one': 1, 1.23: 4})
+
+    def testPropertyDictNoRaiseError(self):
+        a = PropertyDict(one=1, two=2, three=3, raise_on_error=False)
+        a[4] = 'four'
+        b = PropertyDict({'one': 1, 'two': 2, 'three': 3, 4: 'four'}, raise_on_error=False)
+        c = PropertyDict(zip(['one', 'two', 'three', 4], [1, 2, 3, 'four']), raise_on_error=False)
+        d = PropertyDict([('two', 2), ('one', 1), ('three', 3), (4, 'four')], raise_on_error=False)
+        e = PropertyDict({4: 'four', symbol('three'): 3, symbol('one'): 1, symbol('two'): 2}, raise_on_error=False)
+        f = PropertyDict(a, raise_on_error=False)
+        g = PropertyDict(raise_on_error=False)
+        g['one'] = 1
+        g[4] = 'four'
+        g[symbol('two')] = 2
+        g['three'] = 3
+        assert a == b == c == d == e == f == g
+
+    def testAnnotationDict(self):
+        # AnnotationMap c'tor calls update(), so this method is also covered
+        a = AnnotationDict(one=1, two=2, three=3)
+        a[ulong(4)] = 'four'
+        b = AnnotationDict({'one': 1, 'two': 2, 'three': 3, ulong(4): 'four'})
+        c = AnnotationDict(zip(['one', 'two', 'three', ulong(4)], [1, 2, 3, 'four']))
+        d = AnnotationDict([('two', 2), ('one', 1), ('three', 3), (ulong(4), 'four')])
+        e = AnnotationDict({symbol('three'): 3, ulong(4): 'four', symbol('one'): 1, symbol('two'): 2})
+        f = AnnotationDict(a)
+        g = AnnotationDict()
+        g[ulong(4)] = 'four'
+        g['one'] = 1
+        g[symbol('two')] = 2
+        g['three'] = 3
+        assert a == b == c == d == e == f == g
+        for k in a.keys():
+            assert isinstance(k, (symbol, ulong))
+        self.assertRaises(KeyError, AnnotationDict, {'one': 1, None: 'none'})
+        self.assertRaises(KeyError, AnnotationDict, {'one': 1, 1.23: 4})
+
+    def testAnnotationDictNoRaiseError(self):
+        a = AnnotationDict(one=1, two=2, three=3, raise_on_error=False)
+        a[ulong(4)] = 'four'
+        a[5] = 'five'
+        b = AnnotationDict({'one': 1, 'two': 2, 'three': 3, ulong(4): 'four', 5: 'five'}, raise_on_error=False)
+        c = AnnotationDict(zip(['one', 'two', 'three', ulong(4), 5], [1, 2, 3, 'four', 'five']), raise_on_error=False)
+        d = AnnotationDict([('two', 2), ('one', 1), ('three', 3),
+                            (ulong(4), 'four'), (5, 'five')], raise_on_error=False)
+        e = AnnotationDict({5: 'five', symbol('three'): 3, ulong(4): 'four',
+                            symbol('one'): 1, symbol('two'): 2}, raise_on_error=False)
+        f = AnnotationDict(a, raise_on_error=False)
+        g = AnnotationDict(raise_on_error=False)
+        g[ulong(4)] = 'four'
+        g['one'] = 1
+        g[symbol('two')] = 2
+        g[5] = 'five'
+        g['three'] = 3
+        assert a == b == c == d == e == f == g
+
+    def testSymbolList(self):
+        a = SymbolList(['one', 'two', 'three'])
+        b = SymbolList([symbol('one'), symbol('two'), symbol('three')])
+        c = SymbolList()
+        c.append('one')
+        c.extend([symbol('two'), 'three'])
+        d1 = SymbolList(['one'])
+        d2 = SymbolList(['two', symbol('three')])
+        d = d1 + d2
+        e = SymbolList(['one'])
+        e += SymbolList(['two', symbol('three')])
+        f = SymbolList(['one', 'hello', 'goodbye'])
+        f[1] = symbol('two')
+        f[2] = 'three'
+        g = SymbolList(a)
+        assert a == b == c == d == e == f == g
+        for v in a:
+            assert isinstance(v, symbol)
+        self.assertRaises(TypeError, SymbolList, ['one', None])
+        self.assertRaises(TypeError, SymbolList, ['one', 2])
+        self.assertRaises(TypeError, SymbolList, ['one', ['two']])
+        self.assertRaises(TypeError, SymbolList, ['one', {'two': 3}])
+
+    def testSymbolListNoRaiseError(self):
+        a = SymbolList(['one', 'two', 'three', 4], raise_on_error=False)
+        b = SymbolList([symbol('one'), symbol('two'), symbol('three'), 4], raise_on_error=False)
+        c = SymbolList(raise_on_error=False)
+        c.append('one')
+        c.extend([symbol('two'), 'three', 4])
+        d1 = SymbolList(['one'], raise_on_error=False)
+        d2 = SymbolList(['two', symbol('three'), 4], raise_on_error=False)
+        d = d1 + d2
+        e = SymbolList(['one'], raise_on_error=False)
+        e += SymbolList(['two', symbol('three'), 4], raise_on_error=False)
+        f = SymbolList(['one', 'hello', 'goodbye', 'what?'], raise_on_error=False)
+        f[1] = symbol('two')
+        f[2] = 'three'
+        f[3] = 4
+        g = SymbolList(a, raise_on_error=False)
+        assert a == b == c == d == e == f == g
+
+    def _test(self, dtype, *values, **kwargs):
+        eq = kwargs.get("eq", lambda x, y: x == y)
+        ntype = getattr(Data, dtype.upper())
+        putter = getattr(self.data, "put_%s" % dtype)
+        getter = getattr(self.data, "get_%s" % dtype)
+
+        for v in values:
+            self.put(putter, v)
+            gotten = getter()
+            assert eq(gotten, v), (gotten, v)
+
+        self.data.rewind()
+
+        for v in values:
+            vtype = self.data.next()
+            assert vtype == ntype, vtype
+            gotten = getter()
+            assert eq(gotten, v), (gotten, v)
+
+        encoded = self.data.encode()
+        copy = Data(0)
+        while encoded:
+            n = copy.decode(encoded)
+            encoded = encoded[n:]
+        copy.rewind()
+
+        cgetter = getattr(copy, "get_%s" % dtype)
+
+        for v in values:
+            vtype = copy.next()
+            assert vtype == ntype, vtype
+            gotten = cgetter()
+            assert eq(gotten, v), (gotten, v)
+
+    def _test_int(self, itype):
+        self._test(itype, *self.int_values(itype))
+
+    def testByte(self): self._test_int("byte")
+
+    def testUbyte(self):
+        self._test_int("ubyte")
+        self.assertRaises(AssertionError, ubyte, -1)
+
+    def testShort(self): self._test_int("short")
+
+    def testUshort(self):
+        self._test("ushort")
+        self.assertRaises(AssertionError, ushort, -1)
+
+    def testInt(self): self._test_int("int")
+
+    def testUint(self):
+        self._test_int("uint")
+        self.assertRaises(AssertionError, uint, -1)
+
+    def testLong(self): self._test_int("long")
+
+    def testUlong(self):
+        self._test_int("ulong")
+        self.assertRaises(AssertionError, ulong, -1)
+
+    def testString(self):
+        self._test("string", "one", "two", "three", "this is a test", "")
+
+    def testFloat(self):
+        # we have to use a special comparison here because python
+        # internally only uses doubles and converting between floats and
+        # doubles is imprecise
+        self._test("float", 0, 1, 2, 3, 0.1, 0.2, 0.3, -1, -2, -3, -0.1, -0.2, -0.3,
+                   eq=lambda x, y: x - y < 0.000001)
+
+    def testDouble(self):
+        self._test("double", 0, 1, 2, 3, 0.1, 0.2, 0.3, -1, -2, -3, -0.1, -0.2, -0.3)
+
+    def testBinary(self):
+        self._test("binary", b"this", b"is", b"a", b"test", b"of" b"b\x00inary")
+
+    def testSymbol(self):
+        self._test("symbol", symbol("this is a symbol test"), symbol("bleh"), symbol("blah"))
+
+    def testTimestamp(self):
+        self._test("timestamp", timestamp(0), timestamp(12345), timestamp(1000000))
+
+    def testChar(self):
+        self._test("char", char('a'), char('b'), char('c'), char(u'\u20AC'))
+
+    def testUUID(self):
+        self._test("uuid", uuid4(), uuid4(), uuid4())
+
+    def testDecimal32(self):
+        self._test("decimal32", decimal32(0), decimal32(1), decimal32(2), decimal32(3), decimal32(4), decimal32(2**30))
+
+    def testDecimal64(self):
+        self._test("decimal64", decimal64(0), decimal64(1), decimal64(2), decimal64(3), decimal64(4), decimal64(2**60))
+
+    def testDecimal128(self):
+        self._test("decimal128", decimal128(b"fdsaasdf;lkjjkl;"), decimal128(b"x"*16))
+
+    def testCopy(self):
+        self.data.put_described()
+        self.data.enter()
+        self.data.put_ulong(123)
+        self.data.put_map()
+        self.data.enter()
+        self.data.put_string("pi")
+        self.data.put_double(3.14159265359)
+
+        dst = Data()
+        dst.copy(self.data)
+
+        copy = dst.format()
+        orig = self.data.format()
+        assert copy == orig, (copy, orig)
+
+    def testCopyNested(self):
+        nested = [1, 2, 3, [4, 5, 6], 7, 8, 9]
+        self.data.put_object(nested)
+        dst = Data()
+        dst.copy(self.data)
+        assert dst.format() == self.data.format()
+
+    def testCopyNestedArray(self):
+        nested = [Array(UNDESCRIBED, Data.LIST,
+                        ["first", [Array(UNDESCRIBED, Data.INT, 1, 2, 3)]],
+                        ["second", [Array(UNDESCRIBED, Data.INT, 1, 2, 3)]],
+                        ["third", [Array(UNDESCRIBED, Data.INT, 1, 2, 3)]],
+                        ),
+                  "end"]
+        self.data.put_object(nested)
+        dst = Data()
+        dst.copy(self.data)
+        assert dst.format() == self.data.format()
+
+    def testRoundTrip(self):
+        obj = {symbol("key"): timestamp(1234),
+               ulong(123): "blah",
+               char("c"): "bleh",
+               u"desc": Described(symbol("url"), u"http://example.org"),
+               u"array": Array(UNDESCRIBED, Data.INT, 1, 2, 3),
+               u"list": [1, 2, 3, None, 4],
+               u"boolean": True}
+        self.data.put_object(obj)
+        enc = self.data.encode()
+        data = Data()
+        data.decode(enc)
+        data.rewind()
+        assert data.next()
+        copy = data.get_object()
+        assert copy == obj, (copy, obj)
+
+    def testBuffer(self):
+        try:
+            self.data.put_object(buffer(b"foo"))
+        except NameError:
+            # python >= 3.0 does not have `buffer`
+            return
+        data = Data()
+        data.decode(self.data.encode())
+        data.rewind()
+        assert data.next()
+        assert data.type() == Data.BINARY
+        assert data.get_object() == b"foo"
+
+    def testMemoryView(self):
+        self.data.put_object(memoryview(b"foo"))
+        data = Data()
+        data.decode(self.data.encode())
+        data.rewind()
+        assert data.next()
+        assert data.type() == Data.BINARY
+        assert data.get_object() == b"foo"
+
+    def testLookup(self):
+        obj = {symbol("key"): u"value",
+               symbol("pi"): 3.14159,
+               symbol("list"): [1, 2, 3, 4]}
+        self.data.put_object(obj)
+        self.data.rewind()
+        self.data.next()
+        self.data.enter()
+        self.data.narrow()
+        assert self.data.lookup("pi")
+        assert self.data.get_object() == 3.14159
+        self.data.rewind()
+        assert self.data.lookup("key")
+        assert self.data.get_object() == u"value"
+        self.data.rewind()
+        assert self.data.lookup("list")
+        assert self.data.get_object() == [1, 2, 3, 4]
+        self.data.widen()
+        self.data.rewind()
+        assert not self.data.lookup("pi")
diff --git a/python/tests/proton_tests/common.py b/python/tests/proton_tests/common.py
index 89d90bd..1e2e9a9 100644
--- a/python/tests/proton_tests/common.py
+++ b/python/tests/proton_tests/common.py
@@ -22,11 +22,13 @@ from __future__ import absolute_import
 from unittest import TestCase
 from unittest import SkipTest
 
-import sys, os, subprocess
+import sys
+import os
+import subprocess
 from random import randint
 from threading import Thread
 from socket import socket, AF_INET, SOCK_STREAM
-from subprocess import Popen,PIPE,STDOUT
+from subprocess import Popen, PIPE, STDOUT
 from string import Template
 
 from proton import SASL, SSL
@@ -35,59 +37,63 @@ from proton.handlers import Handshaker, FlowController
 
 
 def free_tcp_ports(count=1):
-  """ return a list of 'count' TCP ports that are free to used (ie. unbound)
-  """
-  retry = 0
-  ports = []
-  sockets = []
-  while len(ports) != count:
-    port = randint(49152, 65535)
-    sockets.append( socket( AF_INET, SOCK_STREAM ) )
-    try:
-      sockets[-1].bind( ("0.0.0.0", port ) )
-      ports.append( port )
-      retry = 0
-    except:
-      retry += 1
-      assert retry != 100, "No free sockets available for test!"
-  for s in sockets:
-    s.close()
-  return ports
+    """ return a list of 'count' TCP ports that are free to used (ie. unbound)
+    """
+    retry = 0
+    ports = []
+    sockets = []
+    while len(ports) != count:
+        port = randint(49152, 65535)
+        sockets.append(socket(AF_INET, SOCK_STREAM))
+        try:
+            sockets[-1].bind(("0.0.0.0", port))
+            ports.append(port)
+            retry = 0
+        except:
+            retry += 1
+            assert retry != 100, "No free sockets available for test!"
+    for s in sockets:
+        s.close()
+    return ports
+
 
 def free_tcp_port():
-  return free_tcp_ports(1)[0]
+    return free_tcp_ports(1)[0]
+
 
 def pump_uni(src, dst, buffer_size=1024):
-  p = src.pending()
-  c = dst.capacity()
+    p = src.pending()
+    c = dst.capacity()
+
+    if c < 0:
+        if p < 0:
+            return False
+        else:
+            src.close_head()
+            return True
 
-  if c < 0:
     if p < 0:
-      return False
+        dst.close_tail()
+    elif p == 0 or c == 0:
+        return False
     else:
-      src.close_head()
-      return True
+        binary = src.peek(min(c, buffer_size))
+        dst.push(binary)
+        src.pop(len(binary))
 
-  if p < 0:
-    dst.close_tail()
-  elif p == 0 or c == 0:
-    return False
-  else:
-    binary = src.peek(min(c, buffer_size))
-    dst.push(binary)
-    src.pop(len(binary))
+    return True
 
-  return True
 
 def pump(transport1, transport2, buffer_size=1024):
-  """ Transfer all pending bytes between two Proton engines
-      by repeatedly calling peek/pop and push.
-      Asserts that each engine accepts some bytes every time
-      (unless it's already closed).
-  """
-  while (pump_uni(transport1, transport2, buffer_size) or
-         pump_uni(transport2, transport1, buffer_size)):
-    pass
+    """ Transfer all pending bytes between two Proton engines
+        by repeatedly calling peek/pop and push.
+        Asserts that each engine accepts some bytes every time
+        (unless it's already closed).
+    """
+    while (pump_uni(transport1, transport2, buffer_size) or
+           pump_uni(transport2, transport1, buffer_size)):
+        pass
+
 
 def findfileinpath(filename, searchpath):
     """Find filename in the searchpath
@@ -99,153 +105,163 @@ def findfileinpath(filename, searchpath):
             return os.path.abspath(os.path.join(path, filename))
     return None
 
+
 def isSSLPresent():
     return SSL.present()
 
+
 createdSASLDb = False
 
+
 def _cyrusSetup(conf_dir):
-  """Write out simple SASL config.
-  """
-  saslpasswd = ""
-  if 'SASLPASSWD' in os.environ:
-    saslpasswd = os.environ['SASLPASSWD']
-  else:
-    saslpasswd = findfileinpath('saslpasswd2', os.getenv('PATH')) or ""
-  if os.path.exists(saslpasswd):
-    t = Template("""sasldb_path: ${db}
+    """Write out simple SASL config.
+    """
+    saslpasswd = ""
+    if 'SASLPASSWD' in os.environ:
+        saslpasswd = os.environ['SASLPASSWD']
+    else:
+        saslpasswd = findfileinpath('saslpasswd2', os.getenv('PATH')) or ""
+    if os.path.exists(saslpasswd):
+        t = Template("""sasldb_path: ${db}
 mech_list: EXTERNAL DIGEST-MD5 SCRAM-SHA-1 CRAM-MD5 PLAIN ANONYMOUS
 """)
-    abs_conf_dir = os.path.abspath(conf_dir)
-    subprocess.call(args=['rm','-rf',abs_conf_dir])
-    os.mkdir(abs_conf_dir)
-    db = os.path.join(abs_conf_dir,'proton.sasldb')
-    conf = os.path.join(abs_conf_dir,'proton-server.conf')
-    f = open(conf, 'w')
-    f.write(t.substitute(db=db))
-    f.close()
-
-    cmd_template = Template("echo password | ${saslpasswd} -c -p -f ${db} -u proton user")
-    cmd = cmd_template.substitute(db=db, saslpasswd=saslpasswd)
-    subprocess.call(args=cmd, shell=True)
-
-    os.environ['PN_SASL_CONFIG_PATH'] = abs_conf_dir
-    global createdSASLDb
-    createdSASLDb = True
+        abs_conf_dir = os.path.abspath(conf_dir)
+        subprocess.call(args=['rm', '-rf', abs_conf_dir])
+        os.mkdir(abs_conf_dir)
+        db = os.path.join(abs_conf_dir, 'proton.sasldb')
+        conf = os.path.join(abs_conf_dir, 'proton-server.conf')
+        f = open(conf, 'w')
+        f.write(t.substitute(db=db))
+        f.close()
+
+        cmd_template = Template("echo password | ${saslpasswd} -c -p -f ${db} -u proton user")
+        cmd = cmd_template.substitute(db=db, saslpasswd=saslpasswd)
+        subprocess.call(args=cmd, shell=True)
+
+        os.environ['PN_SASL_CONFIG_PATH'] = abs_conf_dir
+        global createdSASLDb
+        createdSASLDb = True
+
 
 # Globally initialize Cyrus SASL configuration
 if SASL.extended():
-  _cyrusSetup('sasl-conf')
+    _cyrusSetup('sasl-conf')
+
 
 def ensureCanTestExtendedSASL():
-  if not SASL.extended():
-    raise Skipped('Extended SASL not supported')
-  if not createdSASLDb:
-    raise Skipped("Can't Test Extended SASL: Couldn't create auth db")
+    if not SASL.extended():
+        raise Skipped('Extended SASL not supported')
+    if not createdSASLDb:
+        raise Skipped("Can't Test Extended SASL: Couldn't create auth db")
+
 
 class DefaultConfig:
     defines = {}
 
+
 class Test(TestCase):
-  config = DefaultConfig()
+    config = DefaultConfig()
 
-  def __init__(self, name):
-    super(Test, self).__init__(name)
-    self.name = name
+    def __init__(self, name):
+        super(Test, self).__init__(name)
+        self.name = name
 
-  def configure(self, config):
-    self.config = config
+    def configure(self, config):
+        self.config = config
 
-  def default(self, name, value, **profiles):
-    default = value
-    profile = self.config.defines.get("profile")
-    if profile:
-      default = profiles.get(profile, default)
-    return self.config.defines.get(name, default)
+    def default(self, name, value, **profiles):
+        default = value
+        profile = self.config.defines.get("profile")
+        if profile:
+            default = profiles.get(profile, default)
+        return self.config.defines.get(name, default)
 
-  @property
-  def delay(self):
-    return float(self.default("delay", "1", fast="0.1"))
+    @property
+    def delay(self):
+        return float(self.default("delay", "1", fast="0.1"))
 
-  @property
-  def timeout(self):
-    return float(self.default("timeout", "60", fast="10"))
+    @property
+    def timeout(self):
+        return float(self.default("timeout", "60", fast="10"))
 
-  @property
-  def verbose(self):
-    return int(self.default("verbose", 0))
+    @property
+    def verbose(self):
+        return int(self.default("verbose", 0))
 
 
 class Skipped(SkipTest):
-  skipped = True
+    skipped = True
 
 
 class TestServer(object):
-  """ Base class for creating test-specific message servers.
-  """
-  def __init__(self, **kwargs):
-    self.args = kwargs
-    self.reactor = Container(self)
-    self.host = "127.0.0.1"
-    self.port = 0
-    if "host" in kwargs:
-      self.host = kwargs["host"]
-    if "port" in kwargs:
-      self.port = kwargs["port"]
-    self.handlers = [FlowController(10), Handshaker()]
-    self.thread = Thread(name="server-thread", target=self.run)
-    self.thread.daemon = True
-    self.running = True
-    self.conditions = []
-
-  def start(self):
-    self.reactor.start()
-    retry = 0
-    if self.port == 0:
-      self.port = str(randint(49152, 65535))
-      retry = 10
-    while retry > 0:
-      try:
-        self.acceptor = self.reactor.acceptor(self.host, self.port)
-        break
-      except IOError:
-        self.port = str(randint(49152, 65535))
-        retry -= 1
-    assert retry > 0, "No free port for server to listen on!"
-    self.thread.start()
-
-  def stop(self):
-    self.running = False
-    self.reactor.wakeup()
-    self.thread.join()
-
-  # Note: all following methods all run under the thread:
-
-  def run(self):
-    self.reactor.timeout = 3.14159265359
-    while self.reactor.process():
-      if not self.running:
-        self.acceptor.close()
-        self.reactor.stop()
-        break
-
-  def on_connection_bound(self, event):
-    if "idle_timeout" in self.args:
-      event.transport.idle_timeout = self.args["idle_timeout"]
-
-  def on_connection_local_close(self, event):
-    self.conditions.append(event.connection.condition)
-
-  def on_delivery(self, event):
-    event.delivery.settle()
+    """ Base class for creating test-specific message servers.
+    """
+
+    def __init__(self, **kwargs):
+        self.args = kwargs
+        self.reactor = Container(self)
+        self.host = "127.0.0.1"
+        self.port = 0
+        if "host" in kwargs:
+            self.host = kwargs["host"]
+        if "port" in kwargs:
+            self.port = kwargs["port"]
+        self.handlers = [FlowController(10), Handshaker()]
+        self.thread = Thread(name="server-thread", target=self.run)
+        self.thread.daemon = True
+        self.running = True
+        self.conditions = []
+
+    def start(self):
+        self.reactor.start()
+        retry = 0
+        if self.port == 0:
+            self.port = str(randint(49152, 65535))
+            retry = 10
+        while retry > 0:
+            try:
+                self.acceptor = self.reactor.acceptor(self.host, self.port)
+                break
+            except IOError:
+                self.port = str(randint(49152, 65535))
+                retry -= 1
+        assert retry > 0, "No free port for server to listen on!"
+        self.thread.start()
+
+    def stop(self):
+        self.running = False
+        self.reactor.wakeup()
+        self.thread.join()
+
+    # Note: all following methods all run under the thread:
+
+    def run(self):
+        self.reactor.timeout = 3.14159265359
+        while self.reactor.process():
+            if not self.running:
+                self.acceptor.close()
+                self.reactor.stop()
+                break
+
+    def on_connection_bound(self, event):
+        if "idle_timeout" in self.args:
+            event.transport.idle_timeout = self.args["idle_timeout"]
+
+    def on_connection_local_close(self, event):
+        self.conditions.append(event.connection.condition)
+
+    def on_delivery(self, event):
+        event.delivery.settle()
 
 #
 # Classes that wrap the messenger applications msgr-send and msgr-recv.
 # These applications reside in the c/tools directory
 #
 
+
 class MessengerApp(object):
     """ Interface to control a MessengerApp """
+
     def __init__(self):
         self._cmdline = None
         # options common to Receivers and Senders:
@@ -283,7 +299,7 @@ class MessengerApp(object):
 
             # NOTE(flaper87): Skip the test if the command is not found.
             if e.errno == 2:
-              raise Skipped("Skipping test - %s" % msg)
+                raise Skipped("Skipping test - %s" % msg)
             assert False, msg
 
         self._ready()  # wait for it to initialize
@@ -303,7 +319,7 @@ class MessengerApp(object):
         return self._process.returncode
 
     def stdout(self):
-        #self._process.communicate()[0]
+        # self._process.communicate()[0]
         if not self._output or not self._output[0]:
             return "*** NO STDOUT ***"
         return self._output[0]
@@ -342,6 +358,7 @@ class MessengerApp(object):
 
 class MessengerSender(MessengerApp):
     """ Interface to configure a sending MessengerApp """
+
     def __init__(self):
         MessengerApp.__init__(self)
         self._command = None
@@ -401,6 +418,7 @@ class MessengerSender(MessengerApp):
 
 class MessengerReceiver(MessengerApp):
     """ Interface to configure a receiving MessengerApp """
+
     def __init__(self):
         MessengerApp.__init__(self)
         self._command = None
@@ -457,21 +475,25 @@ class MessengerReceiver(MessengerApp):
         r = self._process.stdout.readline()
         assert r.strip() == "READY", "Unexpected input while waiting for receiver to initialize: %s" % r
 
+
 class MessengerSenderC(MessengerSender):
     def __init__(self):
         MessengerSender.__init__(self)
         self._command = ["msgr-send"]
 
+
 class MessengerReceiverC(MessengerReceiver):
     def __init__(self):
         MessengerReceiver.__init__(self)
         self._command = ["msgr-recv"]
 
+
 class ReactorSenderC(MessengerSender):
     def __init__(self):
         MessengerSender.__init__(self)
         self._command = ["reactor-send"]
 
+
 class ReactorReceiverC(MessengerReceiver):
     def __init__(self):
         MessengerReceiver.__init__(self)
diff --git a/python/tests/proton_tests/connect.py b/python/tests/proton_tests/connect.py
index 794e29b..696da6d 100644
--- a/python/tests/proton_tests/connect.py
+++ b/python/tests/proton_tests/connect.py
@@ -27,10 +27,12 @@ from proton.reactor import Container
 from proton.handlers import MessagingHandler
 from .ssl import _testpath
 
+
 def write_connect_conf(obj):
     with open('connect.json', 'w') as outfile:
         json.dump(obj, outfile)
 
+
 class Server(MessagingHandler):
     def __init__(self, expected_user=None, scheme='amqps'):
         super(Server, self).__init__()
@@ -52,6 +54,7 @@ class Server(MessagingHandler):
         event.connection.close()
         self.listener.close()
 
+
 class Client(MessagingHandler):
     def __init__(self):
         super(Client, self).__init__()
@@ -61,13 +64,14 @@ class Client(MessagingHandler):
         self.opened = True
         event.connection.close()
 
+
 class ConnectConfigTest(Test):
     def test_port(self):
         ensureCanTestExtendedSASL()
         server = Server()
         container = Container(server)
         client = Client()
-        write_connect_conf({'port':server.port})
+        write_connect_conf({'port': server.port})
         container.connect(handler=client, reconnect=False)
         container.run()
         assert client.opened == True
@@ -79,7 +83,7 @@ class ConnectConfigTest(Test):
         server = Server(user)
         container = Container(server)
         client = Client()
-        write_connect_conf({'port':server.port, 'user':user, 'password':password})
+        write_connect_conf({'port': server.port, 'user': user, 'password': password})
         container.connect(handler=client, reconnect=False)
         container.run()
         assert client.opened == True
@@ -94,11 +98,11 @@ class ConnectConfigTest(Test):
                                              'server-password')
         client = Client()
         config = {
-            'scheme':'amqps',
-            'port':server.port,
+            'scheme': 'amqps',
+            'port': server.port,
             'tls': {
                 'verify': False
-             }
+            }
         }
         write_connect_conf(config)
         container.connect(handler=client, reconnect=False)
@@ -113,13 +117,13 @@ class ConnectConfigTest(Test):
                                              _testpath('server-private-key-lh.pem'),
                                              'server-password')
         container.ssl.server.set_trusted_ca_db(_testpath('ca-certificate.pem'))
-        container.ssl.server.set_peer_authentication( SSLDomain.VERIFY_PEER,
-                                                      _testpath('ca-certificate.pem') )
+        container.ssl.server.set_peer_authentication(SSLDomain.VERIFY_PEER,
+                                                     _testpath('ca-certificate.pem'))
 
         client = Client()
         config = {
-            'scheme':'amqps',
-            'port':server.port,
+            'scheme': 'amqps',
+            'port': server.port,
             'sasl': {
                 'mechanisms': 'EXTERNAL'
             },
@@ -145,18 +149,18 @@ class ConnectConfigTest(Test):
                                              _testpath('server-private-key-lh.pem'),
                                              'server-password')
         container.ssl.server.set_trusted_ca_db(_testpath('ca-certificate.pem'))
-        container.ssl.server.set_peer_authentication( SSLDomain.VERIFY_PEER,
-                                                      _testpath('ca-certificate.pem') )
+        container.ssl.server.set_peer_authentication(SSLDomain.VERIFY_PEER,
+                                                     _testpath('ca-certificate.pem'))
 
         client = Client()
         config = {
-            'scheme':'amqps',
-            'port':server.port,
-            'user':user,
-            'password':password,
+            'scheme': 'amqps',
+            'port': server.port,
+            'user': user,
+            'password': password,
             'sasl': {
                 'mechanisms': 'PLAIN'
-             },
+            },
             'tls': {
                 'cert': _testpath('client-certificate.pem'),
                 'key': _testpath('client-private-key-no-password.pem'),
@@ -168,4 +172,3 @@ class ConnectConfigTest(Test):
         container.connect(handler=client, reconnect=False)
         container.run()
         assert client.opened == True
-
diff --git a/python/tests/proton_tests/engine.py b/python/tests/proton_tests/engine.py
index 70d10c8..e20d691 100644
--- a/python/tests/proton_tests/engine.py
+++ b/python/tests/proton_tests/engine.py
@@ -19,7 +19,8 @@
 
 from __future__ import absolute_import
 
-import os, gc
+import os
+import gc
 from time import time, sleep
 from proton import *
 from proton.reactor import Container
@@ -29,7 +30,7 @@ from .common import pump, Skipped
 
 # older versions of gc do not provide the garbage list
 if not hasattr(gc, "garbage"):
-  gc.garbage=[]
+    gc.garbage = []
 
 # future test areas
 #  + different permutations of setup
@@ -53,2803 +54,2822 @@ except:
 
 OUTPUT_SIZE = 10*1024
 
+
 class Test(common.Test):
 
-  def __init__(self, *args):
-    common.Test.__init__(self, *args)
-    self._wires = []
-
-  def connection(self):
-    c1 = Connection()
-    c2 = Connection()
-    t1 = Transport()
-    t1.bind(c1)
-    t2 = Transport()
-    t2.bind(c2)
-    self._wires.append((c1, t1, c2, t2))
-
-    mask1 = 0
-    mask2 = 0
-
-    for cat in ("TRACE_FRM", "TRACE_RAW"):
-      trc = os.environ.get("PN_%s" % cat)
-      if trc and trc.lower() in ("1", "2", "yes", "true"):
-        mask1 = mask1 | getattr(Transport, cat)
-      if trc == "2":
-        mask2 = mask2 | getattr(Transport, cat)
-    t1.trace(mask1)
-    t2.trace(mask2)
-
-    return c1, c2
-
-  def link(self, name, max_frame=None, idle_timeout=None):
-    c1, c2 = self.connection()
-    if max_frame:
-      c1.transport.max_frame_size = max_frame[0]
-      c2.transport.max_frame_size = max_frame[1]
-    if idle_timeout:
-      # idle_timeout in seconds expressed as float
-      c1.transport.idle_timeout = idle_timeout[0]
-      c2.transport.idle_timeout = idle_timeout[1]
-    c1.open()
-    c2.open()
-    ssn1 = c1.session()
-    ssn1.open()
-    self.pump()
-    ssn2 = c2.session_head(Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_ACTIVE)
-    ssn2.open()
-    self.pump()
-    snd = ssn1.sender(name)
-    rcv = ssn2.receiver(name)
-    return snd, rcv
-
-  def cleanup(self):
-    self._wires = []
-
-  def pump(self, buffer_size=OUTPUT_SIZE):
-    for c1, t1, c2, t2 in self._wires:
-      pump(t1, t2, buffer_size)
+    def __init__(self, *args):
+        common.Test.__init__(self, *args)
+        self._wires = []
+
+    def connection(self):
+        c1 = Connection()
+        c2 = Connection()
+        t1 = Transport()
+        t1.bind(c1)
+        t2 = Transport()
+        t2.bind(c2)
+        self._wires.append((c1, t1, c2, t2))
+
+        mask1 = 0
+        mask2 = 0
+
+        for cat in ("TRACE_FRM", "TRACE_RAW"):
+            trc = os.environ.get("PN_%s" % cat)
+            if trc and trc.lower() in ("1", "2", "yes", "true"):
+                mask1 = mask1 | getattr(Transport, cat)
+            if trc == "2":
+                mask2 = mask2 | getattr(Transport, cat)
+        t1.trace(mask1)
+        t2.trace(mask2)
+
+        return c1, c2
+
+    def link(self, name, max_frame=None, idle_timeout=None):
+        c1, c2 = self.connection()
+        if max_frame:
+            c1.transport.max_frame_size = max_frame[0]
+            c2.transport.max_frame_size = max_frame[1]
+        if idle_timeout:
+            # idle_timeout in seconds expressed as float
+            c1.transport.idle_timeout = idle_timeout[0]
+            c2.transport.idle_timeout = idle_timeout[1]
+        c1.open()
+        c2.open()
+        ssn1 = c1.session()
+        ssn1.open()
+        self.pump()
+        ssn2 = c2.session_head(Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_ACTIVE)
+        ssn2.open()
+        self.pump()
+        snd = ssn1.sender(name)
+        rcv = ssn2.receiver(name)
+        return snd, rcv
+
+    def cleanup(self):
+        self._wires = []
+
+    def pump(self, buffer_size=OUTPUT_SIZE):
+        for c1, t1, c2, t2 in self._wires:
+            pump(t1, t2, buffer_size)
+
 
 class ConnectionTest(Test):
 
-  def setUp(self):
-    gc.enable()
-    self.c1, self.c2 = self.connection()
+    def setUp(self):
+        gc.enable()
+        self.c1, self.c2 = self.connection()
+
+    def cleanup(self):
+        # release resources created by this class
+        super(ConnectionTest, self).cleanup()
+        self.c1 = None
+        self.c2 = None
+
+    def tearDown(self):
+        self.cleanup()
+        gc.collect()
+        assert not gc.garbage
+
+    def test_open_close(self):
+        assert self.c1.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
+        assert self.c2.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
+
+        self.c1.open()
+        self.pump()
+
+        assert self.c1.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_UNINIT
+        assert self.c2.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_ACTIVE
+
+        self.c2.open()
+        self.pump()
+
+        assert self.c1.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+        assert self.c2.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
 
-  def cleanup(self):
-    # release resources created by this class
-    super(ConnectionTest, self).cleanup()
-    self.c1 = None
-    self.c2 = None
+        self.c1.close()
+        self.pump()
 
-  def tearDown(self):
-    self.cleanup()
-    gc.collect()
-    assert not gc.garbage
+        assert self.c1.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
+        assert self.c2.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED
 
-  def test_open_close(self):
-    assert self.c1.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
-    assert self.c2.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
+        self.c2.close()
+        self.pump()
 
-    self.c1.open()
-    self.pump()
+        assert self.c1.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
+        assert self.c2.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
 
-    assert self.c1.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_UNINIT
-    assert self.c2.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_ACTIVE
+    def test_simultaneous_open_close(self):
+        assert self.c1.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
+        assert self.c2.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
 
-    self.c2.open()
-    self.pump()
+        self.c1.open()
+        self.c2.open()
 
-    assert self.c1.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-    assert self.c2.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+        self.pump()
 
-    self.c1.close()
-    self.pump()
+        assert self.c1.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+        assert self.c2.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
 
-    assert self.c1.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
-    assert self.c2.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED
+        self.c1.close()
+        self.c2.close()
 
-    self.c2.close()
-    self.pump()
+        self.pump()
 
-    assert self.c1.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
-    assert self.c2.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
+        assert self.c1.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
+        assert self.c2.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
 
-  def test_simultaneous_open_close(self):
-    assert self.c1.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
-    assert self.c2.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
+    def test_capabilities_array(self):
+        self.c1.offered_capabilities = Array(UNDESCRIBED, Data.SYMBOL,
+                                             symbol("O_one"),
+                                             symbol("O_two"),
+                                             symbol("O_three"))
 
-    self.c1.open()
-    self.c2.open()
+        self.c1.desired_capabilities = Array(UNDESCRIBED, Data.SYMBOL,
+                                             symbol("D_one"),
+                                             symbol("D_two"),
+                                             symbol("D_three"))
+        self.c1.open()
 
-    self.pump()
+        assert self.c2.remote_offered_capabilities is None
+        assert self.c2.remote_desired_capabilities is None
 
-    assert self.c1.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-    assert self.c2.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+        self.pump()
 
-    self.c1.close()
-    self.c2.close()
+        assert self.c2.remote_offered_capabilities == self.c1.offered_capabilities, \
+            (self.c2.remote_offered_capabilities, self.c1.offered_capabilities)
+        assert self.c2.remote_desired_capabilities == self.c1.desired_capabilities, \
+            (self.c2.remote_desired_capabilities, self.c1.desired_capabilities)
 
-    self.pump()
+    def test_capabilities_symbol_list(self):
+        self.c1.offered_capabilities = SymbolList(['O_one', 'O_two', symbol('O_three')])
+        self.c1.desired_capabilities = SymbolList([symbol('D_one'), 'D_two', 'D_three'])
+        self.c1.open()
 
-    assert self.c1.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
-    assert self.c2.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
+        assert self.c2.remote_offered_capabilities is None
+        assert self.c2.remote_desired_capabilities is None
 
-  def test_capabilities_array(self):
-    self.c1.offered_capabilities = Array(UNDESCRIBED, Data.SYMBOL,
-                                         symbol("O_one"),
-                                         symbol("O_two"),
-                                         symbol("O_three"))
+        self.pump()
 
-    self.c1.desired_capabilities = Array(UNDESCRIBED, Data.SYMBOL,
-                                         symbol("D_one"),
-                                         symbol("D_two"),
-                                         symbol("D_three"))
-    self.c1.open()
+        assert self.c2.remote_offered_capabilities == self.c1.offered_capabilities, \
+            (self.c2.remote_offered_capabilities, self.c1.offered_capabilities)
+        assert self.c2.remote_desired_capabilities == self.c1.desired_capabilities, \
+            (self.c2.remote_desired_capabilities, self.c1.desired_capabilities)
 
-    assert self.c2.remote_offered_capabilities is None
-    assert self.c2.remote_desired_capabilities is None
+    def test_condition(self):
+        self.c1.open()
+        self.c2.open()
+        self.pump()
+        assert self.c1.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+        assert self.c2.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
 
-    self.pump()
+        cond = Condition("blah:bleh", "this is a description", {symbol("foo"): "bar"})
+        self.c1.condition = cond
+        self.c1.close()
+
+        self.pump()
+
+        assert self.c1.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
+        assert self.c2.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED
+
+        rcond = self.c2.remote_condition
+        assert rcond == cond, (rcond, cond)
+
+    def test_properties(self, p1=PropertyDict(key=symbol("value")), p2=None):
+        self.c1.properties = p1
+        self.c2.properties = p2
+        self.c1.open()
+        self.c2.open()
+        self.pump()
+
+        assert self.c2.remote_properties == p1, (self.c2.remote_properties, p1)
+        assert self.c1.remote_properties == p2, (self.c1.remote_properties, p2)
+
+    # The proton implementation limits channel_max to 32767.
+    # If I set the application's limit lower than that, I should
+    # get my wish.  If I set it higher -- not.
+    def test_channel_max_low(self, value=1234):
+        self.c1.transport.channel_max = value
+        self.c1.open()
+        self.pump()
+        assert self.c1.transport.channel_max == value, (self.c1.transport.channel_max, value)
+
+    def test_channel_max_high(self, value=65535):
+        self.c1.transport.channel_max = value
+        self.c1.open()
+        self.pump()
+        assert self.c1.transport.channel_max == 32767, (self.c1.transport.channel_max, value)
+
+    def test_channel_max_raise_and_lower(self):
+        upper_limit = 32767
+
+        # It's OK to lower the max below upper_limit.
+        self.c1.transport.channel_max = 12345
+        assert self.c1.transport.channel_max == 12345
+
+        # But it won't let us raise the limit above PN_IMPL_CHANNEL_MAX.
+        self.c1.transport.channel_max = 65535
+        assert self.c1.transport.channel_max == upper_limit
+
+        # send the OPEN frame
+        self.c1.open()
+        self.pump()
+
+        # Now it's too late to make any change, because
+        # we have already sent the OPEN frame.
+        try:
+            self.c1.transport.channel_max = 666
+            assert False, "expected session exception"
+        except:
+            pass
+
+        assert self.c1.transport.channel_max == upper_limit
+
+    # TODO: Currently failing test - PROTON-1759 - skip
+
+    def test_channel_max_limits_sessions(self):
+        raise Skipped('Test fails - PROTON-1759')
+        # This is an index -- so max number of channels should be 1.
+        self.c1.transport.channel_max = 0
+        self.c1.open()
+        self.c2.open()
+        ssn_0 = self.c2.session()
+        assert ssn_0 != None
+        ssn_0.open()
+        self.pump()
+        try:
+            ssn_1 = self.c2.session()
+            ssn_1.open()
+            self.pump()
+            assert False, "expected session exception"
+        except SessionException:
+            pass
+
+    def test_cleanup(self):
+        self.c1.open()
+        self.c2.open()
+        self.pump()
+        assert self.c1.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+        assert self.c2.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+        t1 = self.c1.transport
+        t2 = self.c2.transport
+        c2 = self.c2
+        self.c1.close()
+        # release all references to C1, except that held by the transport
+        self.cleanup()
+        gc.collect()
+        # transport should flush last state from C1:
+        pump(t1, t2)
+        assert c2.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED
+
+    def test_user_config(self):
+        self.c1.user = "vindaloo"
+        self.c1.password = "secret"
+        self.c1.open()
+        self.pump()
+
+        self.c2.user = "leela"
+        self.c2.password = "trustno1"
+        self.c2.open()
+        self.pump()
+
+        assert self.c1.user == "vindaloo", self.c1.user
+        assert self.c1.password == None, self.c1.password
+        assert self.c2.user == "leela", self.c2.user
+        assert self.c2.password == None, self.c2.password
 
-    assert self.c2.remote_offered_capabilities == self.c1.offered_capabilities, \
-        (self.c2.remote_offered_capabilities, self.c1.offered_capabilities)
-    assert self.c2.remote_desired_capabilities == self.c1.desired_capabilities, \
-        (self.c2.remote_desired_capabilities, self.c1.desired_capabilities)
-
-  def test_capabilities_symbol_list(self):
-    self.c1.offered_capabilities = SymbolList(['O_one', 'O_two', symbol('O_three')])
-    self.c1.desired_capabilities = SymbolList([symbol('D_one'), 'D_two', 'D_three'])
-    self.c1.open()
-
-    assert self.c2.remote_offered_capabilities is None
-    assert self.c2.remote_desired_capabilities is None
-
-    self.pump()
-
-    assert self.c2.remote_offered_capabilities == self.c1.offered_capabilities, \
-        (self.c2.remote_offered_capabilities, self.c1.offered_capabilities)
-    assert self.c2.remote_desired_capabilities == self.c1.desired_capabilities, \
-        (self.c2.remote_desired_capabilities, self.c1.desired_capabilities)
-
-  def test_condition(self):
-    self.c1.open()
-    self.c2.open()
-    self.pump()
-    assert self.c1.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-    assert self.c2.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-
-    cond = Condition("blah:bleh", "this is a description", {symbol("foo"): "bar"})
-    self.c1.condition = cond
-    self.c1.close()
-
-    self.pump()
-
-    assert self.c1.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
-    assert self.c2.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED
-
-    rcond = self.c2.remote_condition
-    assert rcond == cond, (rcond, cond)
-
-  def test_properties(self, p1=PropertyDict(key=symbol("value")), p2=None):
-    self.c1.properties = p1
-    self.c2.properties = p2
-    self.c1.open()
-    self.c2.open()
-    self.pump()
-
-    assert self.c2.remote_properties == p1, (self.c2.remote_properties, p1)
-    assert self.c1.remote_properties == p2, (self.c1.remote_properties, p2)
-
-  # The proton implementation limits channel_max to 32767.
-  # If I set the application's limit lower than that, I should
-  # get my wish.  If I set it higher -- not.
-  def test_channel_max_low(self, value=1234):
-    self.c1.transport.channel_max = value
-    self.c1.open()
-    self.pump()
-    assert self.c1.transport.channel_max == value, (self.c1.transport.channel_max, value)
-
-  def test_channel_max_high(self, value=65535):
-    self.c1.transport.channel_max = value
-    self.c1.open()
-    self.pump()
-    assert self.c1.transport.channel_max == 32767, (self.c1.transport.channel_max, value)
-
-  def test_channel_max_raise_and_lower(self):
-    upper_limit = 32767
-
-    # It's OK to lower the max below upper_limit.
-    self.c1.transport.channel_max = 12345
-    assert self.c1.transport.channel_max == 12345
-
-    # But it won't let us raise the limit above PN_IMPL_CHANNEL_MAX.
-    self.c1.transport.channel_max = 65535
-    assert self.c1.transport.channel_max == upper_limit
-
-    # send the OPEN frame
-    self.c1.open()
-    self.pump()
-
-    # Now it's too late to make any change, because
-    # we have already sent the OPEN frame.
-    try:
-      self.c1.transport.channel_max = 666
-      assert False, "expected session exception"
-    except:
-      pass
-
-    assert self.c1.transport.channel_max == upper_limit
-
-
-  # TODO: Currently failing test - PROTON-1759 - skip
-  def test_channel_max_limits_sessions(self):
-    raise Skipped('Test fails - PROTON-1759')
-    # This is an index -- so max number of channels should be 1.
-    self.c1.transport.channel_max = 0
-    self.c1.open()
-    self.c2.open()
-    ssn_0 = self.c2.session()
-    assert ssn_0 != None
-    ssn_0.open()
-    self.pump()
-    try:
-      ssn_1 = self.c2.session()
-      ssn_1.open()
-      self.pump()
-      assert False, "expected session exception"
-    except SessionException:
-      pass
-
-  def test_cleanup(self):
-    self.c1.open()
-    self.c2.open()
-    self.pump()
-    assert self.c1.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-    assert self.c2.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-    t1 = self.c1.transport
-    t2 = self.c2.transport
-    c2 = self.c2
-    self.c1.close()
-    # release all references to C1, except that held by the transport
-    self.cleanup()
-    gc.collect()
-    # transport should flush last state from C1:
-    pump(t1, t2)
-    assert c2.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED
-
-  def test_user_config(self):
-    self.c1.user = "vindaloo"
-    self.c1.password = "secret"
-    self.c1.open()
-    self.pump()
-
-    self.c2.user = "leela"
-    self.c2.password = "trustno1"
-    self.c2.open()
-    self.pump()
-
-    assert self.c1.user == "vindaloo", self.c1.user
-    assert self.c1.password == None, self.c1.password
-    assert self.c2.user == "leela", self.c2.user
-    assert self.c2.password == None, self.c2.password
 
 class SessionTest(Test):
 
-  def setUp(self):
-    gc.enable()
-    self.c1, self.c2 = self.connection()
-    self.ssn = self.c1.session()
-    self.c1.open()
-    self.c2.open()
+    def setUp(self):
+        gc.enable()
+        self.c1, self.c2 = self.connection()
+        self.ssn = self.c1.session()
+        self.c1.open()
+        self.c2.open()
 
-  def cleanup(self):
-    # release resources created by this class
-    super(SessionTest, self).cleanup()
-    self.c1 = None
-    self.c2 = None
-    self.ssn = None
+    def cleanup(self):
+        # release resources created by this class
+        super(SessionTest, self).cleanup()
+        self.c1 = None
+        self.c2 = None
+        self.ssn = None
 
-  def tearDown(self):
-    self.cleanup()
-    gc.collect()
-    assert not gc.garbage
+    def tearDown(self):
+        self.cleanup()
+        gc.collect()
+        assert not gc.garbage
 
-  def test_open_close(self):
-    assert self.ssn.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
+    def test_open_close(self):
+        assert self.ssn.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
 
-    self.ssn.open()
+        self.ssn.open()
 
-    assert self.ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_UNINIT
+        assert self.ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_UNINIT
 
-    self.pump()
+        self.pump()
 
-    assert self.ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_UNINIT
+        assert self.ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_UNINIT
 
-    ssn = self.c2.session_head(Endpoint.REMOTE_ACTIVE | Endpoint.LOCAL_UNINIT)
+        ssn = self.c2.session_head(Endpoint.REMOTE_ACTIVE | Endpoint.LOCAL_UNINIT)
 
-    assert ssn != None
-    assert ssn.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_ACTIVE
-    assert self.ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_UNINIT
+        assert ssn != None
+        assert ssn.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_ACTIVE
+        assert self.ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_UNINIT
 
-    ssn.open()
+        ssn.open()
 
-    assert ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-    assert self.ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_UNINIT
+        assert ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+        assert self.ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_UNINIT
 
-    self.pump()
+        self.pump()
 
-    assert ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-    assert self.ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+        assert ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+        assert self.ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
 
-    ssn.close()
+        ssn.close()
 
-    assert ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
-    assert self.ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+        assert ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
+        assert self.ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
 
-    self.pump()
+        self.pump()
 
-    assert ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
-    assert self.ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED
+        assert ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
+        assert self.ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED
 
-    self.ssn.close()
+        self.ssn.close()
 
-    assert ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
-    assert self.ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
+        assert ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
+        assert self.ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
 
-    self.pump()
+        self.pump()
 
-    assert ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
-    assert self.ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
+        assert ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
+        assert self.ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
 
-  def test_simultaneous_close(self):
-    self.ssn.open()
-    self.pump()
-    ssn = self.c2.session_head(Endpoint.REMOTE_ACTIVE | Endpoint.LOCAL_UNINIT)
-    assert ssn != None
-    ssn.open()
-    self.pump()
+    def test_simultaneous_close(self):
+        self.ssn.open()
+        self.pump()
+        ssn = self.c2.session_head(Endpoint.REMOTE_ACTIVE | Endpoint.LOCAL_UNINIT)
+        assert ssn != None
+        ssn.open()
+        self.pump()
 
-    assert self.ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-    assert ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+        assert self.ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+        assert ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
 
-    self.ssn.close()
-    ssn.close()
+        self.ssn.close()
+        ssn.close()
 
-    assert self.ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
-    assert ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
+        assert self.ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
+        assert ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
 
-    self.pump()
+        self.pump()
 
-    assert self.ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
-    assert ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
+        assert self.ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
+        assert ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
 
-  def test_closing_connection(self):
-    self.ssn.open()
-    self.pump()
-    self.c1.close()
-    self.pump()
-    self.ssn.close()
-    self.pump()
+    def test_closing_connection(self):
+        self.ssn.open()
+        self.pump()
+        self.c1.close()
+        self.pump()
+        self.ssn.close()
+        self.pump()
 
-  def test_condition(self):
-    self.ssn.open()
-    self.pump()
-    ssn = self.c2.session_head(Endpoint.REMOTE_ACTIVE | Endpoint.LOCAL_UNINIT)
-    assert ssn != None
-    ssn.open()
-    self.pump()
+    def test_condition(self):
+        self.ssn.open()
+        self.pump()
+        ssn = self.c2.session_head(Endpoint.REMOTE_ACTIVE | Endpoint.LOCAL_UNINIT)
+        assert ssn != None
+        ssn.open()
+        self.pump()
 
-    assert self.ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-    assert ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+        assert self.ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+        assert ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
 
-    cond = Condition("blah:bleh", "this is a description", {symbol("foo"): "bar"})
-    self.ssn.condition = cond
-    self.ssn.close()
+        cond = Condition("blah:bleh", "this is a description", {symbol("foo"): "bar"})
+        self.ssn.condition = cond
+        self.ssn.close()
 
-    self.pump()
+        self.pump()
 
-    assert self.ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
-    assert ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED
+        assert self.ssn.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
+        assert ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED
 
-    rcond = ssn.remote_condition
-    assert rcond == cond, (rcond, cond)
+        rcond = ssn.remote_condition
+        assert rcond == cond, (rcond, cond)
 
-  def test_cleanup(self):
-    snd, rcv = self.link("test-link")
-    snd.open()
-    rcv.open()
-    self.pump()
-    snd_ssn = snd.session
-    rcv_ssn = rcv.session
-    assert rcv_ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-    self.ssn = None
-    snd_ssn.close()
-    snd_ssn.free()
-    del snd_ssn
-    gc.collect()
-    self.pump()
-    assert rcv_ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED
+    def test_cleanup(self):
+        snd, rcv = self.link("test-link")
+        snd.open()
+        rcv.open()
+        self.pump()
+        snd_ssn = snd.session
+        rcv_ssn = rcv.session
+        assert rcv_ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+        self.ssn = None
+        snd_ssn.close()
+        snd_ssn.free()
+        del snd_ssn
+        gc.collect()
+        self.pump()
+        assert rcv_ssn.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED
+
+    def test_reopen_on_same_session_without_free(self):
+        """
+        confirm that a link is correctly opened when attaching to a previously
+        closed link *that has not been freed yet* on the same session
+        """
+        self.ssn.open()
+        self.pump()
+
+        ssn2 = self.c2.session_head(Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_ACTIVE)
+        ssn2.open()
+        self.pump()
+        snd = self.ssn.sender("test-link")
+        rcv = ssn2.receiver("test-link")
 
-  def test_reopen_on_same_session_without_free(self):
-    """
-    confirm that a link is correctly opened when attaching to a previously
-    closed link *that has not been freed yet* on the same session
-    """
-    self.ssn.open()
-    self.pump()
+        assert snd.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
+        assert rcv.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
 
-    ssn2 = self.c2.session_head(Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_ACTIVE)
-    ssn2.open()
-    self.pump()
-    snd = self.ssn.sender("test-link")
-    rcv = ssn2.receiver("test-link")
+        snd.open()
+        rcv.open()
+        self.pump()
+
+        assert snd.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+        assert rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
 
-    assert snd.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
-    assert rcv.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
+        snd.close()
+        rcv.close()
+        self.pump()
 
-    snd.open()
-    rcv.open()
-    self.pump()
+        assert snd.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
+        assert rcv.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
 
-    assert snd.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-    assert rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-
-    snd.close()
-    rcv.close()
-    self.pump()
-
-    assert snd.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
-    assert rcv.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
-
-    snd = self.ssn.sender("test-link")
-    rcv = ssn2.receiver("test-link")
-    assert snd.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
-    assert rcv.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
-
-    snd.open()
-    rcv.open()
-    self.pump()
-
-    assert snd.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-    assert rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-
-  def test_set_get_outgoing_window(self):
-    assert self.ssn.outgoing_window == 2147483647
-
-    self.ssn.outgoing_window = 1024
-    assert self.ssn.outgoing_window == 1024
+        snd = self.ssn.sender("test-link")
+        rcv = ssn2.receiver("test-link")
+        assert snd.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
+        assert rcv.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
+
+        snd.open()
+        rcv.open()
+        self.pump()
+
+        assert snd.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+        assert rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+
+    def test_set_get_outgoing_window(self):
+        assert self.ssn.outgoing_window == 2147483647
+
+        self.ssn.outgoing_window = 1024
+        assert self.ssn.outgoing_window == 1024
 
 
 class LinkTest(Test):
 
-  def setUp(self):
-    gc.enable()
-    self.snd, self.rcv = self.link("test-link")
+    def setUp(self):
+        gc.enable()
+        self.snd, self.rcv = self.link("test-link")
+
+    def cleanup(self):
+        # release resources created by this class
+        super(LinkTest, self).cleanup()
+        self.snd = None
+        self.rcv = None
+
+    def tearDown(self):
+        self.cleanup()
+        gc.collect()
+        assert not gc.garbage, gc.garbage
+
+    def test_open_close(self):
+        assert self.snd.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
+        assert self.rcv.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
+
+        self.snd.open()
+
+        assert self.snd.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_UNINIT
+        assert self.rcv.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
+
+        self.pump()
+
+        assert self.snd.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_UNINIT
+        assert self.rcv.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_ACTIVE
+
+        self.rcv.open()
+
+        assert self.snd.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_UNINIT
+        assert self.rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+
+        self.pump()
+
+        assert self.snd.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+        assert self.rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+
+        self.snd.close()
+
+        assert self.snd.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
+        assert self.rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+
+        self.pump()
+
+        assert self.snd.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
+        assert self.rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED
+
+        self.rcv.close()
+
+        assert self.snd.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
+        assert self.rcv.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
+
+        self.pump()
+
+        assert self.snd.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
+        assert self.rcv.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
+
+    def test_simultaneous_open_close(self):
+        assert self.snd.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
+        assert self.rcv.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
+
+        self.snd.open()
+        self.rcv.open()
+
+        assert self.snd.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_UNINIT
+        assert self.rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_UNINIT
+
+        self.pump()
+
+        assert self.snd.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+        assert self.rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+
+        self.snd.close()
+        self.rcv.close()
+
+        assert self.snd.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
+        assert self.rcv.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
+
+        self.pump()
+
+        assert self.snd.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
+        assert self.rcv.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
+
+    def test_multiple(self):
+        rcv = self.snd.session.receiver("second-rcv")
+        assert rcv.name == "second-rcv"
+        self.snd.open()
+        rcv.open()
+        self.pump()
+        c2 = self.rcv.session.connection
+        l = c2.link_head(Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_ACTIVE)
+        while l:
+            l.open()
+            l = l.next(Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_ACTIVE)
+        self.pump()
+
+        assert self.snd
+        assert rcv
+        self.snd.close()
+        rcv.close()
+        ssn = rcv.session
+        conn = ssn.connection
+        ssn.close()
+        conn.close()
+        self.pump()
+
+    def test_closing_session(self):
+        self.snd.open()
+        self.rcv.open()
+        ssn1 = self.snd.session
+        self.pump()
+        ssn1.close()
+        self.pump()
+        self.snd.close()
+        self.pump()
+
+    def test_closing_connection(self):
+        self.snd.open()
+        self.rcv.open()
+        ssn1 = self.snd.session
+        c1 = ssn1.connection
+        self.pump()
+        c1.close()
+        self.pump()
+        self.snd.close()
+        self.pump()
+
+    def assertEqualTermini(self, t1, t2):
+        assert t1.type == t2.type, (t1.type, t2.type)
+        assert t1.address == t2.address, (t1.address, t2.address)
+        assert t1.durability == t2.durability, (t1.durability, t2.durability)
+        assert t1.expiry_policy == t2.expiry_policy, (t1.expiry_policy, t2.expiry_policy)
+        assert t1.timeout == t2.timeout, (t1.timeout, t2.timeout)
+        assert t1.dynamic == t2.dynamic, (t1.dynamic, t2.dynamic)
+        for attr in ["properties", "capabilities", "outcomes", "filter"]:
+            d1 = getattr(t1, attr)
+            d2 = getattr(t2, attr)
+            assert d1.format() == d2.format(), (attr, d1.format(), d2.format())
+
+    def _test_source_target(self, config_source, config_target):
+        if config_source is None:
+            self.snd.source.type = Terminus.UNSPECIFIED
+        else:
+            config_source(self.snd.source)
+        if config_target is None:
+            self.snd.target.type = Terminus.UNSPECIFIED
+        else:
+            config_target(self.snd.target)
+        self.snd.open()
+        self.pump()
+        self.assertEqualTermini(self.rcv.remote_source, self.snd.source)
+        self.assertEqualTermini(self.rcv.remote_target, self.snd.target)
+        self.rcv.target.copy(self.rcv.remote_target)
+        self.rcv.source.copy(self.rcv.remote_source)
+        self.rcv.open()
+        self.pump()
+        self.assertEqualTermini(self.snd.remote_target, self.snd.target)
+        self.assertEqualTermini(self.snd.remote_source, self.snd.source)
+
+    def test_source_target(self):
+        self._test_source_target(TerminusConfig(address="source"),
+                                 TerminusConfig(address="target"))
+
+    def test_source(self):
+        self._test_source_target(TerminusConfig(address="source"), None)
+
+    def test_target(self):
+        self._test_source_target(None, TerminusConfig(address="target"))
+
+    def test_coordinator(self):
+        caps = Array(UNDESCRIBED, Data.SYMBOL, symbol("amqp:local-transactions"))
+        self._test_source_target(None, TerminusConfig(type=Terminus.COORDINATOR,
+                                                      capabilities=caps))
+
+    def test_source_target_full(self):
+        self._test_source_target(TerminusConfig(address="source",
+                                                timeout=3,
+                                                dist_mode=Terminus.DIST_MODE_MOVE,
+                                                filter=[("int", 1), ("symbol", "two"), ("string", "three")],
+                                                capabilities=["one", "two", "three"]),
+                                 TerminusConfig(address="source",
+                                                timeout=7,
+                                                capabilities=None))
+
+    def test_distribution_mode(self):
+        self._test_source_target(TerminusConfig(address="source",
+                                                dist_mode=Terminus.DIST_MODE_COPY),
+                                 TerminusConfig(address="target"))
+        assert self.rcv.remote_source.distribution_mode == Terminus.DIST_MODE_COPY
+        assert self.rcv.remote_target.distribution_mode == Terminus.DIST_MODE_UNSPECIFIED
+
+    def test_dynamic_link(self):
+        self._test_source_target(TerminusConfig(address=None, dynamic=True), None)
+        assert self.rcv.remote_source.dynamic
+        assert self.rcv.remote_source.address is None
+
+    def test_condition(self):
+        self.snd.open()
+        self.rcv.open()
+        self.pump()
 
-  def cleanup(self):
-    # release resources created by this class
-    super(LinkTest, self).cleanup()
-    self.snd = None
-    self.rcv = None
+        assert self.snd.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+        assert self.rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
 
-  def tearDown(self):
-    self.cleanup()
-    gc.collect()
-    assert not gc.garbage, gc.garbage
+        cond = Condition("blah:bleh", "this is a description", {symbol("foo"): "bar"})
+        self.snd.condition = cond
+        self.snd.close()
 
-  def test_open_close(self):
-    assert self.snd.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
-    assert self.rcv.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
+        self.pump()
 
-    self.snd.open()
+        assert self.snd.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
+        assert self.rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED
 
-    assert self.snd.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_UNINIT
-    assert self.rcv.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
+        rcond = self.rcv.remote_condition
+        assert rcond == cond, (rcond, cond)
 
-    self.pump()
+    def test_settle_mode(self):
+        self.snd.snd_settle_mode = Link.SND_UNSETTLED
+        assert self.snd.snd_settle_mode == Link.SND_UNSETTLED
+        self.rcv.rcv_settle_mode = Link.RCV_SECOND
+        assert self.rcv.rcv_settle_mode == Link.RCV_SECOND
 
-    assert self.snd.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_UNINIT
-    assert self.rcv.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_ACTIVE
+        assert self.snd.remote_rcv_settle_mode != Link.RCV_SECOND
+        assert self.rcv.remote_snd_settle_mode != Link.SND_UNSETTLED
 
-    self.rcv.open()
+        self.snd.open()
+        self.rcv.open()
+        self.pump()
 
-    assert self.snd.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_UNINIT
-    assert self.rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+        assert self.snd.remote_rcv_settle_mode == Link.RCV_SECOND
+        assert self.rcv.remote_snd_settle_mode == Link.SND_UNSETTLED
 
-    self.pump()
+    def test_max_message_size(self):
+        assert self.snd.max_message_size == 0
+        assert self.rcv.remote_max_message_size == 0
+        self.snd.max_message_size = 13579
+        self.snd.open()
+        self.rcv.open()
+        self.pump()
+        assert self.rcv.remote_max_message_size == 13579
+
+    def test_properties(self):
+        sender_props = {symbol('key1'): 'value1',
+                        symbol('key2'): 'value2'}
+        self.snd.properties = sender_props
+        self.snd.open()
+        self.rcv.open()
+        self.pump()
 
-    assert self.snd.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-    assert self.rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-
-    self.snd.close()
+        assert self.rcv.remote_properties == sender_props, (self.rcv.remote_properties, sender_props)
+        assert self.snd.remote_properties == None, (self.snd.remote_properties, None)
+
+    def test_cleanup(self):
+        snd, rcv = self.link("test-link")
+        snd.open()
+        rcv.open()
+        self.pump()
+        assert rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+        snd.close()
+        snd.free()
+        del snd
+        gc.collect()
+        self.pump()
+        assert rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED
 
-    assert self.snd.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
-    assert self.rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-
-    self.pump()
-
-    assert self.snd.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
-    assert self.rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED
-
-    self.rcv.close()
-
-    assert self.snd.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
-    assert self.rcv.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
-
-    self.pump()
-
-    assert self.snd.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
-    assert self.rcv.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
-
-  def test_simultaneous_open_close(self):
-    assert self.snd.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
-    assert self.rcv.state == Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_UNINIT
-
-    self.snd.open()
-    self.rcv.open()
-
-    assert self.snd.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_UNINIT
-    assert self.rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_UNINIT
-
-    self.pump()
-
-    assert self.snd.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-    assert self.rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-
-    self.snd.close()
-    self.rcv.close()
-
-    assert self.snd.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
-    assert self.rcv.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
-
-    self.pump()
-
-    assert self.snd.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
-    assert self.rcv.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_CLOSED
-
-  def test_multiple(self):
-    rcv = self.snd.session.receiver("second-rcv")
-    assert rcv.name == "second-rcv"
-    self.snd.open()
-    rcv.open()
-    self.pump()
-    c2 = self.rcv.session.connection
-    l = c2.link_head(Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_ACTIVE)
-    while l:
-      l.open()
-      l = l.next(Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_ACTIVE)
-    self.pump()
-
-    assert self.snd
-    assert rcv
-    self.snd.close()
-    rcv.close()
-    ssn = rcv.session
-    conn = ssn.connection
-    ssn.close()
-    conn.close()
-    self.pump()
-
-  def test_closing_session(self):
-    self.snd.open()
-    self.rcv.open()
-    ssn1 = self.snd.session
-    self.pump()
-    ssn1.close()
-    self.pump()
-    self.snd.close()
-    self.pump()
-
-  def test_closing_connection(self):
-    self.snd.open()
-    self.rcv.open()
-    ssn1 = self.snd.session
-    c1 = ssn1.connection
-    self.pump()
-    c1.close()
-    self.pump()
-    self.snd.close()
-    self.pump()
-
-  def assertEqualTermini(self, t1, t2):
-    assert t1.type == t2.type, (t1.type, t2.type)
-    assert t1.address == t2.address, (t1.address, t2.address)
-    assert t1.durability == t2.durability, (t1.durability, t2.durability)
-    assert t1.expiry_policy == t2.expiry_policy, (t1.expiry_policy, t2.expiry_policy)
-    assert t1.timeout == t2.timeout, (t1.timeout, t2.timeout)
-    assert t1.dynamic == t2.dynamic, (t1.dynamic, t2.dynamic)
-    for attr in ["properties", "capabilities", "outcomes", "filter"]:
-      d1 = getattr(t1, attr)
-      d2 = getattr(t2, attr)
-      assert d1.format() == d2.format(), (attr, d1.format(), d2.format())
-
-  def _test_source_target(self, config_source, config_target):
-    if config_source is None:
-      self.snd.source.type = Terminus.UNSPECIFIED
-    else:
-      config_source(self.snd.source)
-    if config_target is None:
-      self.snd.target.type = Terminus.UNSPECIFIED
-    else:
-      config_target(self.snd.target)
-    self.snd.open()
-    self.pump()
-    self.assertEqualTermini(self.rcv.remote_source, self.snd.source)
-    self.assertEqualTermini(self.rcv.remote_target, self.snd.target)
-    self.rcv.target.copy(self.rcv.remote_target)
-    self.rcv.source.copy(self.rcv.remote_source)
-    self.rcv.open()
-    self.pump()
-    self.assertEqualTermini(self.snd.remote_target, self.snd.target)
-    self.assertEqualTermini(self.snd.remote_source, self.snd.source)
-
-  def test_source_target(self):
-    self._test_source_target(TerminusConfig(address="source"),
-                             TerminusConfig(address="target"))
-
-  def test_source(self):
-    self._test_source_target(TerminusConfig(address="source"), None)
-
-  def test_target(self):
-    self._test_source_target(None, TerminusConfig(address="target"))
-
-  def test_coordinator(self):
-    caps = Array(UNDESCRIBED, Data.SYMBOL, symbol("amqp:local-transactions"))
-    self._test_source_target(None, TerminusConfig(type=Terminus.COORDINATOR,
-                                                  capabilities=caps))
-
-  def test_source_target_full(self):
-    self._test_source_target(TerminusConfig(address="source",
-                                            timeout=3,
-                                            dist_mode=Terminus.DIST_MODE_MOVE,
-                                            filter=[("int", 1), ("symbol", "two"), ("string", "three")],
-                                            capabilities=["one", "two", "three"]),
-                             TerminusConfig(address="source",
-                                            timeout=7,
-                                            capabilities=None))
-  def test_distribution_mode(self):
-    self._test_source_target(TerminusConfig(address="source",
-                                            dist_mode=Terminus.DIST_MODE_COPY),
-                             TerminusConfig(address="target"))
-    assert self.rcv.remote_source.distribution_mode == Terminus.DIST_MODE_COPY
-    assert self.rcv.remote_target.distribution_mode == Terminus.DIST_MODE_UNSPECIFIED
-
-  def test_dynamic_link(self):
-    self._test_source_target(TerminusConfig(address=None, dynamic=True), None)
-    assert self.rcv.remote_source.dynamic
-    assert self.rcv.remote_source.address is None
-
-  def test_condition(self):
-    self.snd.open()
-    self.rcv.open()
-    self.pump()
-
-    assert self.snd.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-    assert self.rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-
-    cond = Condition("blah:bleh", "this is a description", {symbol("foo"): "bar"})
-    self.snd.condition = cond
-    self.snd.close()
-
-    self.pump()
-
-    assert self.snd.state == Endpoint.LOCAL_CLOSED | Endpoint.REMOTE_ACTIVE
-    assert self.rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED
-
-    rcond = self.rcv.remote_condition
-    assert rcond == cond, (rcond, cond)
-
-  def test_settle_mode(self):
-    self.snd.snd_settle_mode = Link.SND_UNSETTLED
-    assert self.snd.snd_settle_mode == Link.SND_UNSETTLED
-    self.rcv.rcv_settle_mode = Link.RCV_SECOND
-    assert self.rcv.rcv_settle_mode == Link.RCV_SECOND
-
-    assert self.snd.remote_rcv_settle_mode != Link.RCV_SECOND
-    assert self.rcv.remote_snd_settle_mode != Link.SND_UNSETTLED
-
-    self.snd.open()
-    self.rcv.open()
-    self.pump()
-
-    assert self.snd.remote_rcv_settle_mode == Link.RCV_SECOND
-    assert self.rcv.remote_snd_settle_mode == Link.SND_UNSETTLED
-
-  def test_max_message_size(self):
-    assert self.snd.max_message_size == 0
-    assert self.rcv.remote_max_message_size == 0
-    self.snd.max_message_size = 13579
-    self.snd.open()
-    self.rcv.open()
-    self.pump()
-    assert self.rcv.remote_max_message_size == 13579
-
-  def test_properties(self):
-      sender_props = {symbol('key1'): 'value1',
-                      symbol('key2'): 'value2'}
-      self.snd.properties = sender_props
-      self.snd.open()
-      self.rcv.open()
-      self.pump()
-
-      assert self.rcv.remote_properties == sender_props, (self.rcv.remote_properties, sender_props)
-      assert self.snd.remote_properties == None, (self.snd.remote_properties, None)
-
-  def test_cleanup(self):
-    snd, rcv = self.link("test-link")
-    snd.open()
-    rcv.open()
-    self.pump()
-    assert rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-    snd.close()
-    snd.free()
-    del snd
-    gc.collect()
-    self.pump()
-    assert rcv.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED
 
 class TerminusConfig:
 
-  def __init__(self, type=None, address=None, timeout=None, durability=None,
-               filter=None, capabilities=None, dynamic=False, dist_mode=None):
-    self.address = address
-    self.timeout = timeout
-    self.durability = durability
-    self.filter = filter
-    self.capabilities = capabilities
-    self.dynamic = dynamic
-    self.dist_mode = dist_mode
-    self.type = type
-
-  def __call__(self, terminus):
-    if self.type is not None:
-      terminus.type = self.type
-    if self.address is not None:
-      terminus.address = self.address
-    if self.timeout is not None:
-      terminus.timeout = self.timeout
-    if self.durability is not None:
-      terminus.durability = self.durability
-    if self.capabilities is not None:
-      terminus.capabilities.put_array(False, Data.SYMBOL)
-      terminus.capabilities.enter()
-      for c in self.capabilities:
-        terminus.capabilities.put_symbol(c)
-    if self.filter is not None:
-      terminus.filter.put_map()
-      terminus.filter.enter()
-      for (t, v) in self.filter:
-        setter = getattr(terminus.filter, "put_%s" % t)
-        setter(v)
-    if self.dynamic:
-      terminus.dynamic = True
-    if self.dist_mode is not None:
-      terminus.distribution_mode = self.dist_mode
+    def __init__(self, type=None, address=None, timeout=None, durability=None,
+                 filter=None, capabilities=None, dynamic=False, dist_mode=None):
+        self.address = address
+        self.timeout = timeout
+        self.durability = durability
+        self.filter = filter
+        self.capabilities = capabilities
+        self.dynamic = dynamic
+        self.dist_mode = dist_mode
+        self.type = type
+
+    def __call__(self, terminus):
+        if self.type is not None:
+            terminus.type = self.type
+        if self.address is not None:
+            terminus.address = self.address
+        if self.timeout is not None:
+            terminus.timeout = self.timeout
+        if self.durability is not None:
+            terminus.durability = self.durability
+        if self.capabilities is not None:
+            terminus.capabilities.put_array(False, Data.SYMBOL)
+            terminus.capabilities.enter()
+            for c in self.capabilities:
+                terminus.capabilities.put_symbol(c)
+        if self.filter is not None:
+            terminus.filter.put_map()
+            terminus.filter.enter()
+            for (t, v) in self.filter:
+                setter = getattr(terminus.filter, "put_%s" % t)
+                setter(v)
+        if self.dynamic:
+            terminus.dynamic = True
+        if self.dist_mode is not None:
+            terminus.distribution_mode = self.dist_mode
+
 
 class TransferTest(Test):
 
-  def setUp(self):
-    gc.enable()
-    self.snd, self.rcv = self.link("test-link")
-    self.c1 = self.snd.session.connection
-    self.c2 = self.rcv.session.connection
-    self.snd.open()
-    self.rcv.open()
-    self.pump()
-
-  def cleanup(self):
-    # release resources created by this class
-    super(TransferTest, self).cleanup()
-    self.c1 = None
-    self.c2 = None
-    self.snd = None
-    self.rcv = None
-
-  def tearDown(self):
-    self.cleanup()
-    gc.collect()
-    assert not gc.garbage
-
-  def test_work_queue(self):
-    assert self.c1.work_head is None
-    self.snd.delivery("tag")
-    assert self.c1.work_head is None
-    self.rcv.flow(1)
-    self.pump()
-    d = self.c1.work_head
-    assert d is not None
-    tag = d.tag
-    assert tag == "tag", tag
-    assert d.writable
-
-    n = self.snd.send(b"this is a test")
-    assert self.snd.advance()
-    assert self.c1.work_head is None
-
-    self.pump()
-
-    d = self.c2.work_head
-    assert d.tag == "tag"
-    assert d.readable
-
-  def test_multiframe(self):
-    self.rcv.flow(1)
-    self.snd.delivery("tag")
-    msg = b"this is a test"
-    n = self.snd.send(msg)
-    assert n == len(msg)
-
-    self.pump()
-
-    d = self.rcv.current
-    assert d
-    assert d.tag == "tag", repr(d.tag)
-    assert d.readable
-
-    binary = self.rcv.recv(1024)
-    assert binary == msg, (binary, msg)
-
-    binary = self.rcv.recv(1024)
-    assert binary == b""
-
-    msg = b"this is more"
-    n = self.snd.send(msg)
-    assert n == len(msg)
-    assert self.snd.advance()
-
-    self.pump()
-
-    binary = self.rcv.recv(1024)
-    assert binary == msg, (binary, msg)
-
-    binary = self.rcv.recv(1024)
-    assert binary is None
-
-  def test_multiframe_abort(self):
-    self.rcv.flow(1)
-    sd = self.snd.delivery("tag")
-    msg = b"this is a test"
-    n = self.snd.send(msg)
-    assert n == len(msg)
-
-    self.pump()
-
-    binary = self.rcv.recv(1024)
-    assert binary == msg, (binary, msg)
-
-    msg = b"this is more.  Error if not discarded."
-    n = self.snd.send(msg)
-    assert n == len(msg)
-    sd.abort()
-    assert sd.aborted
-
-    # Confirm abort discards the sender's buffered content, i.e. no data in generated transfer frame.
-    # We want:
-    # @transfer(20) [handle=0, delivery-id=0, delivery-tag=b"tag", message-format=0, settled=true, aborted=true]
-    wanted = b"\x00\x00\x00%\x02\x00\x00\x00\x00S\x14\xd0\x00\x00\x00\x15\x00\x00\x00\nR\x00R\x00\xa0\x03tagR\x00A@@@@A"
-    t = self.snd.transport
-    wire_bytes = t.peek(1024)
-    assert wanted == wire_bytes
-
-    self.pump()
-    assert self.rcv.current.aborted
-
-  def test_multiframe_last_empty(self):
-    self.rcv.flow(1)
-    sd = self.snd.delivery("tag")
-    msg_p1 = b"this is a test"
-    n = self.snd.send(msg_p1)
-    assert n == len(msg_p1)
-
-    self.pump()
-
-    assert len(msg_p1) == self.rcv.current.pending
-    assert self.rcv.current.partial
-    msg_p2 = b"this is more."
-    n = self.snd.send(msg_p2)
-    assert n == len(msg_p2)
-
-    self.pump()
-
-    msg = msg_p1 + msg_p2
-    assert len(msg) == self.rcv.current.pending
-    assert self.rcv.current.partial
-    # Advance.  Should send empty xfer frame with more flag false.
-    assert self.snd.advance()
-
-    self.pump()
-
-    assert len(msg) == self.rcv.current.pending
-    assert not self.rcv.current.partial
-    binary = self.rcv.recv(self.rcv.current.pending)
-    assert binary == msg
-
-  def test_disposition(self):
-    self.rcv.flow(1)
-
-    self.pump()
-
-    sd = self.snd.delivery("tag")
-    msg = b"this is a test"
-    n = self.snd.send(msg)
-    assert n == len(msg)
-    assert self.snd.advance()
-
-    self.pump()
-
-    rd = self.rcv.current
-    assert rd is not None
-    assert rd.tag == sd.tag
-    rmsg = self.rcv.recv(1024)
-    assert rmsg == msg
-    rd.update(Delivery.ACCEPTED)
-
-    self.pump()
-
-    rdisp = sd.remote_state
-    ldisp = rd.local_state
-    assert rdisp == ldisp == Delivery.ACCEPTED, (rdisp, ldisp)
-    assert sd.updated
-
-    sd.update(Delivery.ACCEPTED)
-
-    self.pump()
-
-    assert sd.local_state == rd.remote_state == Delivery.ACCEPTED
-    sd.settle()
-
-  def test_delivery_id_ordering(self):
-    self.rcv.flow(1024)
-    self.pump(buffer_size=64*1024)
-
-    #fill up delivery buffer on sender
-    for m in range(1024):
-      sd = self.snd.delivery("tag%s" % m)
-      msg = ("message %s" % m).encode('ascii')
-      n = self.snd.send(msg)
-      assert n == len(msg)
-      assert self.snd.advance()
-
-    self.pump(buffer_size=64*1024)
-
-    #receive a session-windows worth of messages and accept them
-    for m in range(1024):
-      rd = self.rcv.current
-      assert rd is not None, m
-      assert rd.tag == ("tag%s" % m), (rd.tag, m)
-      msg = self.rcv.recv(1024)
-      assert msg == ("message %s" % m).encode('ascii'), (msg, m)
-      rd.update(Delivery.ACCEPTED)
-      rd.settle()
-
-    self.pump(buffer_size=64*1024)
-
-    #add some new deliveries
-    for m in range(1024, 1450):
-      sd = self.snd.delivery("tag%s" % m)
-      msg = ("message %s" % m).encode('ascii')
-      n = self.snd.send(msg)
-      assert n == len(msg)
-      assert self.snd.advance()
-
-    #handle all disposition changes to sent messages
-    d = self.c1.work_head
-    while d:
-      next_d = d.work_next
-      if d.updated:
-        d.update(Delivery.ACCEPTED)
-        d.settle()
-      d = next_d
-
-    #submit some more deliveries
-    for m in range(1450, 1500):
-      sd = self.snd.delivery("tag%s" % m)
-      msg = ("message %s" % m).encode('ascii')
-      n = self.snd.send(msg)
-      assert n == len(msg)
-      assert self.snd.advance()
-
-    self.pump(buffer_size=64*1024)
-    self.rcv.flow(1024)
-    self.pump(buffer_size=64*1024)
-
-    #verify remaining messages can be received and accepted
-    for m in range(1024, 1500):
-      rd = self.rcv.current
-      assert rd is not None, m
-      assert rd.tag == ("tag%s" % m), (rd.tag, m)
-      msg = self.rcv.recv(1024)
-      assert msg == ("message %s" % m).encode('ascii'), (msg, m)
-      rd.update(Delivery.ACCEPTED)
-      rd.settle()
-
-  def test_cleanup(self):
-    self.rcv.flow(10)
-    self.pump()
-
-    for x in range(10):
-        self.snd.delivery("tag%d" % x)
+    def setUp(self):
+        gc.enable()
+        self.snd, self.rcv = self.link("test-link")
+        self.c1 = self.snd.session.connection
+        self.c2 = self.rcv.session.connection
+        self.snd.open()
+        self.rcv.open()
+        self.pump()
+
+    def cleanup(self):
+        # release resources created by this class
+        super(TransferTest, self).cleanup()
+        self.c1 = None
+        self.c2 = None
+        self.snd = None
+        self.rcv = None
+
+    def tearDown(self):
+        self.cleanup()
+        gc.collect()
+        assert not gc.garbage
+
+    def test_work_queue(self):
+        assert self.c1.work_head is None
+        self.snd.delivery("tag")
+        assert self.c1.work_head is None
+        self.rcv.flow(1)
+        self.pump()
+        d = self.c1.work_head
+        assert d is not None
+        tag = d.tag
+        assert tag == "tag", tag
+        assert d.writable
+
+        n = self.snd.send(b"this is a test")
+        assert self.snd.advance()
+        assert self.c1.work_head is None
+
+        self.pump()
+
+        d = self.c2.work_head
+        assert d.tag == "tag"
+        assert d.readable
+
+    def test_multiframe(self):
+        self.rcv.flow(1)
+        self.snd.delivery("tag")
         msg = b"this is a test"
         n = self.snd.send(msg)
         assert n == len(msg)
+
+        self.pump()
+
+        d = self.rcv.current
+        assert d
+        assert d.tag == "tag", repr(d.tag)
+        assert d.readable
+
+        binary = self.rcv.recv(1024)
+        assert binary == msg, (binary, msg)
+
+        binary = self.rcv.recv(1024)
+        assert binary == b""
+
+        msg = b"this is more"
+        n = self.snd.send(msg)
+        assert n == len(msg)
         assert self.snd.advance()
-    self.snd.close()
-    self.snd.free()
-    self.snd = None
-    gc.collect()
 
-    self.pump()
+        self.pump()
+
+        binary = self.rcv.recv(1024)
+        assert binary == msg, (binary, msg)
+
+        binary = self.rcv.recv(1024)
+        assert binary is None
+
+    def test_multiframe_abort(self):
+        self.rcv.flow(1)
+        sd = self.snd.delivery("tag")
+        msg = b"this is a test"
+        n = self.snd.send(msg)
+        assert n == len(msg)
+
+        self.pump()
+
+        binary = self.rcv.recv(1024)
+        assert binary == msg, (binary, msg)
+
+        msg = b"this is more.  Error if not discarded."
+        n = self.snd.send(msg)
+        assert n == len(msg)
+        sd.abort()
+        assert sd.aborted
+
+        # Confirm abort discards the sender's buffered content, i.e. no data in generated transfer frame.
+        # We want:
+        # @transfer(20) [handle=0, delivery-id=0, delivery-tag=b"tag", message-format=0, settled=true, aborted=true]
+        wanted = b"\x00\x00\x00%\x02\x00\x00\x00\x00S\x14\xd0\x00\x00\x00\x15\x00\x00\x00\nR\x00R\x00\xa0\x03tagR\x00A@@@@A"
+        t = self.snd.transport
+        wire_bytes = t.peek(1024)
+        assert wanted == wire_bytes
+
+        self.pump()
+        assert self.rcv.current.aborted
+
+    def test_multiframe_last_empty(self):
+        self.rcv.flow(1)
+        sd = self.snd.delivery("tag")
+        msg_p1 = b"this is a test"
+        n = self.snd.send(msg_p1)
+        assert n == len(msg_p1)
+
+        self.pump()
+
+        assert len(msg_p1) == self.rcv.current.pending
+        assert self.rcv.current.partial
+        msg_p2 = b"this is more."
+        n = self.snd.send(msg_p2)
+        assert n == len(msg_p2)
+
+        self.pump()
+
+        msg = msg_p1 + msg_p2
+        assert len(msg) == self.rcv.current.pending
+        assert self.rcv.current.partial
+        # Advance.  Should send empty xfer frame with more flag false.
+        assert self.snd.advance()
+
+        self.pump()
+
+        assert len(msg) == self.rcv.current.pending
+        assert not self.rcv.current.partial
+        binary = self.rcv.recv(self.rcv.current.pending)
+        assert binary == msg
+
+    def test_disposition(self):
+        self.rcv.flow(1)
+
+        self.pump()
+
+        sd = self.snd.delivery("tag")
+        msg = b"this is a test"
+        n = self.snd.send(msg)
+        assert n == len(msg)
+        assert self.snd.advance()
+
+        self.pump()
 
-    for x in range(10):
         rd = self.rcv.current
         assert rd is not None
-        assert rd.tag == "tag%d" % x
+        assert rd.tag == sd.tag
         rmsg = self.rcv.recv(1024)
-        assert self.rcv.advance()
         assert rmsg == msg
-        # close of snd should've settled:
-        assert rd.settled
-        rd.settle()
+        rd.update(Delivery.ACCEPTED)
+
+        self.pump()
+
+        rdisp = sd.remote_state
+        ldisp = rd.local_state
+        assert rdisp == ldisp == Delivery.ACCEPTED, (rdisp, ldisp)
+        assert sd.updated
+
+        sd.update(Delivery.ACCEPTED)
+
+        self.pump()
+
+        assert sd.local_state == rd.remote_state == Delivery.ACCEPTED
+        sd.settle()
+
+    def test_delivery_id_ordering(self):
+        self.rcv.flow(1024)
+        self.pump(buffer_size=64*1024)
+
+        # fill up delivery buffer on sender
+        for m in range(1024):
+            sd = self.snd.delivery("tag%s" % m)
+            msg = ("message %s" % m).encode('ascii')
+            n = self.snd.send(msg)
+            assert n == len(msg)
+            assert self.snd.advance()
+
+        self.pump(buffer_size=64*1024)
+
+        # receive a session-windows worth of messages and accept them
+        for m in range(1024):
+            rd = self.rcv.current
+            assert rd is not None, m
+            assert rd.tag == ("tag%s" % m), (rd.tag, m)
+            msg = self.rcv.recv(1024)
+            assert msg == ("message %s" % m).encode('ascii'), (msg, m)
+            rd.update(Delivery.ACCEPTED)
+            rd.settle()
+
+        self.pump(buffer_size=64*1024)
+
+        # add some new deliveries
+        for m in range(1024, 1450):
+            sd = self.snd.delivery("tag%s" % m)
+            msg = ("message %s" % m).encode('ascii')
+            n = self.snd.send(msg)
+            assert n == len(msg)
+            assert self.snd.advance()
+
+        # handle all disposition changes to sent messages
+        d = self.c1.work_head
+        while d:
+            next_d = d.work_next
+            if d.updated:
+                d.update(Delivery.ACCEPTED)
+                d.settle()
+            d = next_d
+
+        # submit some more deliveries
+        for m in range(1450, 1500):
+            sd = self.snd.delivery("tag%s" % m)
+            msg = ("message %s" % m).encode('ascii')
+            n = self.snd.send(msg)
+            assert n == len(msg)
+            assert self.snd.advance()
+
+        self.pump(buffer_size=64*1024)
+        self.rcv.flow(1024)
+        self.pump(buffer_size=64*1024)
+
+        # verify remaining messages can be received and accepted
+        for m in range(1024, 1500):
+            rd = self.rcv.current
+            assert rd is not None, m
+            assert rd.tag == ("tag%s" % m), (rd.tag, m)
+            msg = self.rcv.recv(1024)
+            assert msg == ("message %s" % m).encode('ascii'), (msg, m)
+            rd.update(Delivery.ACCEPTED)
+            rd.settle()
+
+    def test_cleanup(self):
+        self.rcv.flow(10)
+        self.pump()
+
+        for x in range(10):
+            self.snd.delivery("tag%d" % x)
+            msg = b"this is a test"
+            n = self.snd.send(msg)
+            assert n == len(msg)
+            assert self.snd.advance()
+        self.snd.close()
+        self.snd.free()
+        self.snd = None
+        gc.collect()
+
+        self.pump()
+
+        for x in range(10):
+            rd = self.rcv.current
+            assert rd is not None
+            assert rd.tag == "tag%d" % x
+            rmsg = self.rcv.recv(1024)
+            assert self.rcv.advance()
+            assert rmsg == msg
+            # close of snd should've settled:
+            assert rd.settled
+            rd.settle()
+
 
 class MaxFrameTransferTest(Test):
 
-  def setUp(self):
-    pass
-
-  def cleanup(self):
-    # release resources created by this class
-    super(MaxFrameTransferTest, self).cleanup()
-    self.c1 = None
-    self.c2 = None
-    self.snd = None
-    self.rcv = None
-
-  def tearDown(self):
-    self.cleanup()
-
-  def message(self, size):
-    parts = []
-    for i in range(size):
-      parts.append(str(i))
-    return "/".join(parts)[:size].encode("utf-8")
-
-  def testMinFrame(self):
-    """
-    Configure receiver to support minimum max-frame as defined by AMQP-1.0.
-    Verify transfer of messages larger than 512.
-    """
-    self.snd, self.rcv = self.link("test-link", max_frame=[0,512])
-    self.c1 = self.snd.session.connection
-    self.c2 = self.rcv.session.connection
-    self.snd.open()
-    self.rcv.open()
-    self.pump()
-    assert self.rcv.session.connection.transport.max_frame_size == 512
-    assert self.snd.session.connection.transport.remote_max_frame_size == 512
-
-    self.rcv.flow(1)
-    self.snd.delivery("tag")
-    msg = self.message(513)
-    n = self.snd.send(msg)
-    assert n == len(msg)
-    assert self.snd.advance()
-
-    self.pump()
-
-    binary = self.rcv.recv(513)
-    assert binary == msg
-
-    binary = self.rcv.recv(1024)
-    assert binary == None
-
-  def testOddFrame(self):
-    """
-    Test an odd sized max limit with data that will require multiple frames to
-    be transfered.
-    """
-    self.snd, self.rcv = self.link("test-link", max_frame=[0,521])
-    self.c1 = self.snd.session.connection
-    self.c2 = self.rcv.session.connection
-    self.snd.open()
-    self.rcv.open()
-    self.pump()
-    assert self.rcv.session.connection.transport.max_frame_size == 521
-    assert self.snd.session.connection.transport.remote_max_frame_size == 521
-
-    self.rcv.flow(2)
-    self.snd.delivery("tag")
-    msg = ("X" * 1699).encode('utf-8')
-    n = self.snd.send(msg)
-    assert n == len(msg)
-    assert self.snd.advance()
-
-    self.pump()
-
-    binary = self.rcv.recv(1699)
-    assert binary == msg
-
-    binary = self.rcv.recv(1024)
-    assert binary == None
-
-    self.rcv.advance()
-
-    self.snd.delivery("gat")
-    msg = self.message(1426)
-    n = self.snd.send(msg)
-    assert n == len(msg)
-    assert self.snd.advance()
-
-    self.pump()
-
-    binary = self.rcv.recv(1426)
-    assert binary == msg
-
-    self.pump()
-
-    binary = self.rcv.recv(1024)
-    assert binary == None
-
-  def testSendQueuedMultiFrameMessages(self, sendSingleFrameMsg = False):
-    """
-    Test that multiple queued messages on the same link
-    with multi-frame content are sent correctly. Use an
-    odd max frame size, send enough data to use many.
-    """
-    self.snd, self.rcv = self.link("test-link", max_frame=[0,517])
-    self.c1 = self.snd.session.connection
-    self.c2 = self.rcv.session.connection
-    self.snd.open()
-    self.rcv.open()
-    self.pump()
-    assert self.rcv.session.connection.transport.max_frame_size == 517
-    assert self.snd.session.connection.transport.remote_max_frame_size == 517
-
-    self.rcv.flow(5)
-
-    self.pump()
-
-    # Send a delivery with 5 frames, all bytes as X1234
-    self.snd.delivery("tag")
-    msg = ("X1234" * 425).encode('utf-8')
-    assert 2125 == len(msg)
-    n = self.snd.send(msg)
-    assert n == len(msg)
-    assert self.snd.advance()
-
-    # Send a delivery with 5 frames, all bytes as Y5678
-    self.snd.delivery("tag2")
-    msg2 = ("Y5678" * 425).encode('utf-8')
-    assert 2125 == len(msg2)
-    n = self.snd.send(msg2)
-    assert n == len(msg2)
-    assert self.snd.advance()
-
-    self.pump()
-
-    if sendSingleFrameMsg:
-        # Send a delivery with 1 frame
-        self.snd.delivery("tag3")
-        msg3 = ("Z").encode('utf-8')
-        assert 1 == len(msg3)
-        n = self.snd.send(msg3)
-        assert n == len(msg3)
+    def setUp(self):
+        pass
+
+    def cleanup(self):
+        # release resources created by this class
+        super(MaxFrameTransferTest, self).cleanup()
+        self.c1 = None
+        self.c2 = None
+        self.snd = None
+        self.rcv = None
+
+    def tearDown(self):
+        self.cleanup()
+
+    def message(self, size):
+        parts = []
+        for i in range(size):
+            parts.append(str(i))
+        return "/".join(parts)[:size].encode("utf-8")
+
+    def testMinFrame(self):
+        """
+        Configure receiver to support minimum max-frame as defined by AMQP-1.0.
+        Verify transfer of messages larger than 512.
+        """
+        self.snd, self.rcv = self.link("test-link", max_frame=[0, 512])
+        self.c1 = self.snd.session.connection
+        self.c2 = self.rcv.session.connection
+        self.snd.open()
+        self.rcv.open()
+        self.pump()
+        assert self.rcv.session.connection.transport.max_frame_size == 512
+        assert self.snd.session.connection.transport.remote_max_frame_size == 512
+
+        self.rcv.flow(1)
+        self.snd.delivery("tag")
+        msg = self.message(513)
+        n = self.snd.send(msg)
+        assert n == len(msg)
         assert self.snd.advance()
+
         self.pump()
 
-    binary = self.rcv.recv(5000)
-    self.assertEqual(binary, msg)
+        binary = self.rcv.recv(513)
+        assert binary == msg
+
+        binary = self.rcv.recv(1024)
+        assert binary == None
+
+    def testOddFrame(self):
+        """
+        Test an odd sized max limit with data that will require multiple frames to
+        be transfered.
+        """
+        self.snd, self.rcv = self.link("test-link", max_frame=[0, 521])
+        self.c1 = self.snd.session.connection
+        self.c2 = self.rcv.session.connection
+        self.snd.open()
+        self.rcv.open()
+        self.pump()
+        assert self.rcv.session.connection.transport.max_frame_size == 521
+        assert self.snd.session.connection.transport.remote_max_frame_size == 521
+
+        self.rcv.flow(2)
+        self.snd.delivery("tag")
+        msg = ("X" * 1699).encode('utf-8')
+        n = self.snd.send(msg)
+        assert n == len(msg)
+        assert self.snd.advance()
 
-    self.rcv.advance()
+        self.pump()
 
-    binary2 = self.rcv.recv(5000)
-    self.assertEqual(binary2, msg2)
+        binary = self.rcv.recv(1699)
+        assert binary == msg
 
-    self.rcv.advance()
+        binary = self.rcv.recv(1024)
+        assert binary == None
 
-    if sendSingleFrameMsg:
-        binary3 = self.rcv.recv(5000)
-        self.assertEqual(binary3, msg3)
         self.rcv.advance()
 
-    self.pump()
-
-  def testSendQueuedMultiFrameMessagesThenSingleFrameMessage(self):
-    self.testSendQueuedMultiFrameMessages(sendSingleFrameMsg = True)
-
-  def testBigMessage(self):
-    """
-    Test transferring a big message.
-    """
-    self.snd, self.rcv = self.link("test-link")
-    self.c1 = self.snd.session.connection
-    self.c2 = self.rcv.session.connection
-    self.snd.open()
-    self.rcv.open()
-    self.pump()
-
-    self.rcv.flow(2)
-    self.snd.delivery("tag")
-    msg = self.message(1024*256)
-    n = self.snd.send(msg)
-    assert n == len(msg)
-    assert self.snd.advance()
-
-    self.pump()
-
-    binary = self.rcv.recv(1024*256)
-    assert binary == msg
-
-    binary = self.rcv.recv(1024)
-    assert binary == None
-
-  def testMaxFrameAbort(self):
-    self.snd, self.rcv = self.link("test-link", max_frame=[0,512])
-    self.c1 = self.snd.session.connection
-    self.c2 = self.rcv.session.connection
-    self.snd.open()
-    self.rcv.open()
-    self.rcv.flow(1)
-    sndt = self.snd.transport
-    dblfrmbytes = ("0123456789" * 52).encode('utf-8')
-    assert 520 == len(dblfrmbytes)
-    self.pump()
-
-    # Part 1: abort a delivery that would generate two frames - before they are generated.
-    # Expect that no output is generated and credit is unaffected.
-    assert self.snd.credit == 1
-    sd = self.snd.delivery("tag_0")
-    n = self.snd.send(dblfrmbytes)
-    assert n == len(dblfrmbytes)
-    sd.abort()
-    generated = sndt.peek(2048)
-    assert generated == b""
-    assert self.snd.credit == 1
-
-    # Part 2: abort a streaming delivery whose last content would generate two frames.
-    # First send some un-aborted data across the wire.
-    sd = self.snd.delivery("tag_1")
-    n = self.snd.send(dblfrmbytes)
-    assert n == len(dblfrmbytes)
-    self.pump()
-    binary = self.rcv.recv(2048)
-    assert binary == dblfrmbytes, (binary, dblfrmbytes)
-    # Now send more data spanning two frames and immediately abort.
-    # Unlike part 1, an abort frame is required to sync with peer.
-    n = self.snd.send(dblfrmbytes)
-    assert n == len(dblfrmbytes)
-    sd.abort()
-    assert sd.aborted
-    # Expect a single abort transfer frame with no content.  One credit is consumed.
-    # @transfer(20) [handle=0, delivery-id=0, delivery-tag=b"tag_1", message-format=0, settled=true, aborted=true]
-    wanted = b"\x00\x00\x00\x27\x02\x00\x00\x00\x00S\x14\xd0\x00\x00\x00\x17\x00\x00\x00\nR\x00R\x00\xa0\x05tag_1R\x00A@@@@A"
-    t = self.snd.transport
-    wire_bytes = t.peek(2048)
-    assert wanted == wire_bytes
-    assert self.snd.credit == 0
-    self.pump()
-    assert self.rcv.current.aborted
-    # Confirm no lingering transfers by closing the link.
-    self.snd.close()
-    # Expect just the detach frame.
-    # @detach(22) [handle=0, closed=true]
-    wanted = b"\x00\x00\x00\x17\x02\x00\x00\x00\x00S\x16\xd0\x00\x00\x00\x07\x00\x00\x00\x02R\x00A"
-    wire_bytes = t.peek(2048)
-    assert wanted == wire_bytes
+        self.snd.delivery("gat")
+        msg = self.message(1426)
+        n = self.snd.send(msg)
+        assert n == len(msg)
+        assert self.snd.advance()
+
+        self.pump()
+
+        binary = self.rcv.recv(1426)
+        assert binary == msg
+
+        self.pump()
+
+        binary = self.rcv.recv(1024)
+        assert binary == None
+
+    def testSendQueuedMultiFrameMessages(self, sendSingleFrameMsg=False):
+        """
+        Test that multiple queued messages on the same link
+        with multi-frame content are sent correctly. Use an
+        odd max frame size, send enough data to use many.
+        """
+        self.snd, self.rcv = self.link("test-link", max_frame=[0, 517])
+        self.c1 = self.snd.session.connection
+        self.c2 = self.rcv.session.connection
+        self.snd.open()
+        self.rcv.open()
+        self.pump()
+        assert self.rcv.session.connection.transport.max_frame_size == 517
+        assert self.snd.session.connection.transport.remote_max_frame_size == 517
+
+        self.rcv.flow(5)
+
+        self.pump()
+
+        # Send a delivery with 5 frames, all bytes as X1234
+        self.snd.delivery("tag")
+        msg = ("X1234" * 425).encode('utf-8')
+        assert 2125 == len(msg)
+        n = self.snd.send(msg)
+        assert n == len(msg)
+        assert self.snd.advance()
+
+        # Send a delivery with 5 frames, all bytes as Y5678
+        self.snd.delivery("tag2")
+        msg2 = ("Y5678" * 425).encode('utf-8')
+        assert 2125 == len(msg2)
+        n = self.snd.send(msg2)
+        assert n == len(msg2)
+        assert self.snd.advance()
+
+        self.pump()
+
+        if sendSingleFrameMsg:
+            # Send a delivery with 1 frame
+            self.snd.delivery("tag3")
+            msg3 = ("Z").encode('utf-8')
+            assert 1 == len(msg3)
+            n = self.snd.send(msg3)
+            assert n == len(msg3)
+            assert self.snd.advance()
+            self.pump()
+
+        binary = self.rcv.recv(5000)
+        self.assertEqual(binary, msg)
+
+        self.rcv.advance()
+
+        binary2 = self.rcv.recv(5000)
+        self.assertEqual(binary2, msg2)
+
+        self.rcv.advance()
+
+        if sendSingleFrameMsg:
+            binary3 = self.rcv.recv(5000)
+            self.assertEqual(binary3, msg3)
+            self.rcv.advance()
+
+        self.pump()
+
+    def testSendQueuedMultiFrameMessagesThenSingleFrameMessage(self):
+        self.testSendQueuedMultiFrameMessages(sendSingleFrameMsg=True)
+
+    def testBigMessage(self):
+        """
+        Test transferring a big message.
+        """
+        self.snd, self.rcv = self.link("test-link")
+        self.c1 = self.snd.session.connection
+        self.c2 = self.rcv.session.connection
+        self.snd.open()
+        self.rcv.open()
+        self.pump()
+
+        self.rcv.flow(2)
+        self.snd.delivery("tag")
+        msg = self.message(1024*256)
+        n = self.snd.send(msg)
+        assert n == len(msg)
+        assert self.snd.advance()
+
+        self.pump()
+
+        binary = self.rcv.recv(1024*256)
+        assert binary == msg
+
+        binary = self.rcv.recv(1024)
+        assert binary == None
+
+    def testMaxFrameAbort(self):
+        self.snd, self.rcv = self.link("test-link", max_frame=[0, 512])
+        self.c1 = self.snd.session.connection
+        self.c2 = self.rcv.session.connection
+        self.snd.open()
+        self.rcv.open()
+        self.rcv.flow(1)
+        sndt = self.snd.transport
+        dblfrmbytes = ("0123456789" * 52).encode('utf-8')
+        assert 520 == len(dblfrmbytes)
+        self.pump()
+
+        # Part 1: abort a delivery that would generate two frames - before they are generated.
+        # Expect that no output is generated and credit is unaffected.
+        assert self.snd.credit == 1
+        sd = self.snd.delivery("tag_0")
+        n = self.snd.send(dblfrmbytes)
+        assert n == len(dblfrmbytes)
+        sd.abort()
+        generated = sndt.peek(2048)
+        assert generated == b""
+        assert self.snd.credit == 1
+
+        # Part 2: abort a streaming delivery whose last content would generate two frames.
+        # First send some un-aborted data across the wire.
+        sd = self.snd.delivery("tag_1")
+        n = self.snd.send(dblfrmbytes)
+        assert n == len(dblfrmbytes)
+        self.pump()
+        binary = self.rcv.recv(2048)
+        assert binary == dblfrmbytes, (binary, dblfrmbytes)
+        # Now send more data spanning two frames and immediately abort.
+        # Unlike part 1, an abort frame is required to sync with peer.
+        n = self.snd.send(dblfrmbytes)
+        assert n == len(dblfrmbytes)
+        sd.abort()
+        assert sd.aborted
+        # Expect a single abort transfer frame with no content.  One credit is consumed.
+        # @transfer(20) [handle=0, delivery-id=0, delivery-tag=b"tag_1", message-format=0, settled=true, aborted=true]
+        wanted = b"\x00\x00\x00\x27\x02\x00\x00\x00\x00S\x14\xd0\x00\x00\x00\x17\x00\x00\x00\nR\x00R\x00\xa0\x05tag_1R\x00A@@@@A"
+        t = self.snd.transport
+        wire_bytes = t.peek(2048)
+        assert wanted == wire_bytes
+        assert self.snd.credit == 0
+        self.pump()
+        assert self.rcv.current.aborted
+        # Confirm no lingering transfers by closing the link.
+        self.snd.close()
+        # Expect just the detach frame.
+        # @detach(22) [handle=0, closed=true]
+        wanted = b"\x00\x00\x00\x17\x02\x00\x00\x00\x00S\x16\xd0\x00\x00\x00\x07\x00\x00\x00\x02R\x00A"
+        wire_bytes = t.peek(2048)
+        assert wanted == wire_bytes
 
 
 class IdleTimeoutTest(Test):
 
-  def setUp(self):
-    pass
-
-  def cleanup(self):
-    # release resources created by this class
-    super(IdleTimeoutTest, self).cleanup()
-    self.snd = None
-    self.rcv = None
-    self.c1 = None
-    self.c2 = None
-
-  def tearDown(self):
-    self.cleanup()
-
-  def message(self, size):
-    parts = []
-    for i in range(size):
-      parts.append(str(i))
-    return "/".join(parts)[:size]
-
-  def testGetSet(self):
-    """
-    Verify the configuration and negotiation of the idle timeout.
-    """
-
-    self.snd, self.rcv = self.link("test-link", idle_timeout=[1.0,2.0])
-    self.c1 = self.snd.session.connection
-    self.c2 = self.rcv.session.connection
-    self.snd.open()
-    self.rcv.open()
-    self.pump()
-    # proton advertises 1/2 the configured timeout to the peer:
-    assert self.rcv.session.connection.transport.idle_timeout == 2.0
-    assert self.rcv.session.connection.transport.remote_idle_timeout == 0.5
-    assert self.snd.session.connection.transport.idle_timeout == 1.0
-    assert self.snd.session.connection.transport.remote_idle_timeout == 1.0
-
-  def testTimeout(self):
-    """
-    Verify the AMQP Connection idle timeout.
-    """
-
-    # snd will timeout the Connection if no frame is received within 1000 ticks
-    self.snd, self.rcv = self.link("test-link", idle_timeout=[1.0,0])
-    self.c1 = self.snd.session.connection
-    self.c2 = self.rcv.session.connection
-    self.snd.open()
-    self.rcv.open()
-    self.pump()
-
-    t_snd = self.snd.session.connection.transport
-    t_rcv = self.rcv.session.connection.transport
-    assert t_rcv.idle_timeout == 0.0
-    # proton advertises 1/2 the timeout (see spec)
-    assert t_rcv.remote_idle_timeout == 0.5
-    assert t_snd.idle_timeout == 1.0
-    assert t_snd.remote_idle_timeout == 0.0
-
-    sndr_frames_in = t_snd.frames_input
-    rcvr_frames_out = t_rcv.frames_output
-
-    # at t+1msec, nothing should happen:
-    clock = 0.001
-    assert t_snd.tick(clock) == 1.001, "deadline for remote timeout"
-    assert t_rcv.tick(clock) == 0.251,  "deadline to send keepalive"
-    self.pump()
-    assert sndr_frames_in == t_snd.frames_input, "unexpected received frame"
-
-    # at one tick from expected idle frame send, nothing should happen:
-    clock = 0.250
-    assert t_snd.tick(clock) == 1.001, "deadline for remote timeout"
-    assert t_rcv.tick(clock) == 0.251,  "deadline to send keepalive"
-    self.pump()
-    assert sndr_frames_in == t_snd.frames_input, "unexpected received frame"
-
-    # this should cause rcvr to expire and send a keepalive
-    clock = 0.251
-    assert t_snd.tick(clock) == 1.001, "deadline for remote timeout"
-    assert t_rcv.tick(clock) == 0.501, "deadline to send keepalive"
-    self.pump()
-    sndr_frames_in += 1
-    rcvr_frames_out += 1
-    assert sndr_frames_in == t_snd.frames_input, "unexpected received frame"
-    assert rcvr_frames_out == t_rcv.frames_output, "unexpected frame"
-
-    # since a keepalive was received, sndr will rebase its clock against this tick:
-    # and the receiver should not change its deadline
-    clock = 0.498
-    assert t_snd.tick(clock) == 1.498, "deadline for remote timeout"
-    assert t_rcv.tick(clock) == 0.501, "deadline to send keepalive"
-    self.pump()
-    assert sndr_frames_in == t_snd.frames_input, "unexpected received frame"
-
-    # now expire sndr
-    clock = 1.499
-    t_snd.tick(clock)
-    self.pump()
-    assert self.c2.state & Endpoint.REMOTE_CLOSED
-    assert self.c2.remote_condition.name == "amqp:resource-limit-exceeded"
+    def setUp(self):
+        pass
+
+    def cleanup(self):
+        # release resources created by this class
+        super(IdleTimeoutTest, self).cleanup()
+        self.snd = None
+        self.rcv = None
+        self.c1 = None
+        self.c2 = None
+
+    def tearDown(self):
+        self.cleanup()
+
+    def message(self, size):
+        parts = []
+        for i in range(size):
+            parts.append(str(i))
+        return "/".join(parts)[:size]
+
+    def testGetSet(self):
+        """
+        Verify the configuration and negotiation of the idle timeout.
+        """
+
+        self.snd, self.rcv = self.link("test-link", idle_timeout=[1.0, 2.0])
+        self.c1 = self.snd.session.connection
+        self.c2 = self.rcv.session.connection
+        self.snd.open()
+        self.rcv.open()
+        self.pump()
+        # proton advertises 1/2 the configured timeout to the peer:
+        assert self.rcv.session.connection.transport.idle_timeout == 2.0
+        assert self.rcv.session.connection.transport.remote_idle_timeout == 0.5
+        assert self.snd.session.connection.transport.idle_timeout == 1.0
+        assert self.snd.session.connection.transport.remote_idle_timeout == 1.0
+
+    def testTimeout(self):
+        """
+        Verify the AMQP Connection idle timeout.
+        """
+
+        # snd will timeout the Connection if no frame is received within 1000 ticks
+        self.snd, self.rcv = self.link("test-link", idle_timeout=[1.0, 0])
+        self.c1 = self.snd.session.connection
+        self.c2 = self.rcv.session.connection
+        self.snd.open()
+        self.rcv.open()
+        self.pump()
+
+        t_snd = self.snd.session.connection.transport
+        t_rcv = self.rcv.session.connection.transport
+        assert t_rcv.idle_timeout == 0.0
+        # proton advertises 1/2 the timeout (see spec)
+        assert t_rcv.remote_idle_timeout == 0.5
+        assert t_snd.idle_timeout == 1.0
+        assert t_snd.remote_idle_timeout == 0.0
+
+        sndr_frames_in = t_snd.frames_input
+        rcvr_frames_out = t_rcv.frames_output
+
+        # at t+1msec, nothing should happen:
+        clock = 0.001
+        assert t_snd.tick(clock) == 1.001, "deadline for remote timeout"
+        assert t_rcv.tick(clock) == 0.251,  "deadline to send keepalive"
+        self.pump()
+        assert sndr_frames_in == t_snd.frames_input, "unexpected received frame"
+
+        # at one tick from expected idle frame send, nothing should happen:
+        clock = 0.250
+        assert t_snd.tick(clock) == 1.001, "deadline for remote timeout"
+        assert t_rcv.tick(clock) == 0.251,  "deadline to send keepalive"
+        self.pump()
+        assert sndr_frames_in == t_snd.frames_input, "unexpected received frame"
+
+        # this should cause rcvr to expire and send a keepalive
+        clock = 0.251
+        assert t_snd.tick(clock) == 1.001, "deadline for remote timeout"
+        assert t_rcv.tick(clock) == 0.501, "deadline to send keepalive"
+        self.pump()
+        sndr_frames_in += 1
+        rcvr_frames_out += 1
+        assert sndr_frames_in == t_snd.frames_input, "unexpected received frame"
+        assert rcvr_frames_out == t_rcv.frames_output, "unexpected frame"
+
+        # since a keepalive was received, sndr will rebase its clock against this tick:
+        # and the receiver should not change its deadline
+        clock = 0.498
+        assert t_snd.tick(clock) == 1.498, "deadline for remote timeout"
+        assert t_rcv.tick(clock) == 0.501, "deadline to send keepalive"
+        self.pump()
+        assert sndr_frames_in == t_snd.frames_input, "unexpected received frame"
+
+        # now expire sndr
+        clock = 1.499
+        t_snd.tick(clock)
+        self.pump()
+        assert self.c2.state & Endpoint.REMOTE_CLOSED
+        assert self.c2.remote_condition.name == "amqp:resource-limit-exceeded"
+
 
 class CreditTest(Test):
 
-  def setUp(self):
-    self.snd, self.rcv = self.link("test-link", max_frame=(16*1024, 16*1024))
-    self.c1 = self.snd.session.connection
-    self.c2 = self.rcv.session.connection
-    self.snd.open()
-    self.rcv.open()
-    self.pump()
-
-  def cleanup(self):
-    # release resources created by this class
-    super(CreditTest, self).cleanup()
-    self.c1 = None
-    self.snd = None
-    self.c2 = None
-    self.rcv2 = None
-    self.snd2 = None
-
-  def tearDown(self):
-    self.cleanup()
-
-  def testCreditSender(self, count=1024):
-    credit = self.snd.credit
-    assert credit == 0, credit
-    self.rcv.flow(10)
-    self.pump()
-    credit = self.snd.credit
-    assert credit == 10, credit
-
-    self.rcv.flow(count)
-    self.pump()
-    credit = self.snd.credit
-    assert credit == 10 + count, credit
-
-  def testCreditReceiver(self):
-    self.rcv.flow(10)
-    self.pump()
-    assert self.rcv.credit == 10, self.rcv.credit
-
-    d = self.snd.delivery("tag")
-    assert d
-    assert self.snd.advance()
-    self.pump()
-    assert self.rcv.credit == 10, self.rcv.credit
-    assert self.rcv.queued == 1, self.rcv.queued
-    c = self.rcv.current
-    assert c.tag == "tag", c.tag
-    assert self.rcv.advance()
-    assert self.rcv.credit == 9, self.rcv.credit
-    assert self.rcv.queued == 0, self.rcv.queued
-
-  def _testBufferingOnClose(self, a, b):
-    for i in range(10):
-      d = self.snd.delivery("tag-%s" % i)
-      assert d
-      d.settle()
-    self.pump()
-    assert self.snd.queued == 10
-
-    endpoints = {"connection": (self.c1, self.c2),
-                 "session": (self.snd.session, self.rcv.session),
-                 "link": (self.snd, self.rcv)}
-
-    local_a, remote_a = endpoints[a]
-    local_b, remote_b = endpoints[b]
-
-    remote_b.close()
-    self.pump()
-    assert local_b.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED
-    local_a.close()
-    self.pump()
-    assert remote_a.state & Endpoint.REMOTE_CLOSED
-    assert self.snd.queued == 10
-
-  def testBufferingOnCloseLinkLink(self):
-    self._testBufferingOnClose("link", "link")
-
-  def testBufferingOnCloseLinkSession(self):
-    self._testBufferingOnClose("link", "session")
-
-  def testBufferingOnCloseLinkConnection(self):
-    self._testBufferingOnClose("link", "connection")
-
-  def testBufferingOnCloseSessionLink(self):
-    self._testBufferingOnClose("session", "link")
-
-  def testBufferingOnCloseSessionSession(self):
-    self._testBufferingOnClose("session", "session")
-
-  def testBufferingOnCloseSessionConnection(self):
-    self._testBufferingOnClose("session", "connection")
-
-  def testBufferingOnCloseConnectionLink(self):
-    self._testBufferingOnClose("connection", "link")
-
-  def testBufferingOnCloseConnectionSession(self):
-    self._testBufferingOnClose("connection", "session")
-
-  def testBufferingOnCloseConnectionConnection(self):
-    self._testBufferingOnClose("connection", "connection")
-
-  def testFullDrain(self):
-    assert self.rcv.credit == 0
-    assert self.snd.credit == 0
-    self.rcv.drain(10)
-    assert self.rcv.draining()
-    assert self.rcv.credit == 10
-    assert self.snd.credit == 0
-    self.pump()
-    assert self.rcv.credit == 10
-    assert self.snd.credit == 10
-    assert self.rcv.draining()
-    self.snd.drained()
-    assert self.rcv.credit == 10
-    assert self.snd.credit == 0
-    assert self.rcv.draining()
-    self.pump()
-    assert self.rcv.credit == 0
-    assert self.snd.credit == 0
-    assert not self.rcv.draining()
-    drained = self.rcv.drained()
-    assert drained == 10, drained
-
-  def testPartialDrain(self):
-    self.rcv.drain(2)
-    assert self.rcv.draining()
-    self.pump()
-
-    d = self.snd.delivery("tag")
-    assert d
-    assert self.snd.advance()
-    self.snd.drained()
-    assert self.rcv.draining()
-    self.pump()
-    assert not self.rcv.draining()
-
-    c = self.rcv.current
-    assert self.rcv.queued == 1, self.rcv.queued
-    assert c.tag == d.tag, c.tag
-    assert self.rcv.advance()
-    assert not self.rcv.current
-    assert self.rcv.credit == 0, self.rcv.credit
-    assert not self.rcv.draining()
-    drained = self.rcv.drained()
-    assert drained == 1, drained
-
-  def testDrainFlow(self):
-    assert self.rcv.credit == 0
-    assert self.snd.credit == 0
-    self.rcv.drain(10)
-    assert self.rcv.credit == 10
-    assert self.snd.credit == 0
-    self.pump()
-    assert self.rcv.credit == 10
-    assert self.snd.credit == 10
-    self.snd.drained()
-    assert self.rcv.credit == 10
-    assert self.snd.credit == 0
-    self.pump()
-    assert self.rcv.credit == 0
-    assert self.snd.credit == 0
-    self.rcv.flow(10)
-    assert self.rcv.credit == 10
-    assert self.snd.credit == 0
-    self.pump()
-    assert self.rcv.credit == 10
-    assert self.snd.credit == 10
-    self.snd.drained()
-    assert self.rcv.credit == 10
-    assert self.snd.credit == 10
-    self.pump()
-    assert self.rcv.credit == 10
-    assert self.snd.credit == 10
-    drained = self.rcv.drained()
-    assert drained == 10, drained
-
-  def testNegative(self):
-    assert self.snd.credit == 0
-    d = self.snd.delivery("tag")
-    assert d
-    assert self.snd.advance()
-    self.pump()
-
-    assert self.rcv.credit == 0
-    assert self.rcv.queued == 0
-
-    self.rcv.flow(1)
-    assert self.rcv.credit == 1
-    assert self.rcv.queued == 0
-    self.pump()
-    assert self.rcv.credit == 1
-    assert self.rcv.queued == 1, self.rcv.queued
-
-    c = self.rcv.current
-    assert c
-    assert c.tag == "tag"
-    assert self.rcv.advance()
-    assert self.rcv.credit == 0
-    assert self.rcv.queued == 0
-
-  def testDrainZero(self):
-    assert self.snd.credit == 0
-    assert self.rcv.credit == 0
-    assert self.rcv.queued == 0
-    drained = self.rcv.drained()
-    assert drained == 0
-
-    self.rcv.flow(10)
-    self.pump()
-    assert self.snd.credit == 10
-    assert self.rcv.credit == 10
-    assert self.rcv.queued == 0
-
-    self.snd.drained()
-    self.pump()
-    assert self.snd.credit == 10
-    assert self.rcv.credit == 10
-    assert self.rcv.queued == 0
-    drained = self.rcv.drained()
-    assert drained == 0
-
-    self.rcv.drain(0)
-    assert self.snd.credit == 10
-    assert self.rcv.credit == 10
-    assert self.rcv.queued == 0
-
-    self.pump()
-
-    assert self.snd.credit == 10
-    assert self.rcv.credit == 10
-    assert self.rcv.queued == 0
-
-    self.snd.drained()
-    assert self.snd.credit == 0
-    assert self.rcv.credit == 10
-    assert self.rcv.queued == 0
-    drained = self.rcv.drained()
-    assert drained == 0
-    self.pump()
-
-    assert self.snd.credit == 0
-    assert self.rcv.credit == 0
-    assert self.rcv.queued == 0
-    drained = self.rcv.drained()
-    assert drained == 10
-
-
-  def testDrainOrder(self):
-    """ Verify drain/drained works regardless of ordering.  See PROTON-401
-    """
-    assert self.snd.credit == 0
-    assert self.rcv.credit == 0
-    assert self.rcv.queued == 0
-
-    #self.rcv.session.connection.transport.trace(Transport.TRACE_FRM)
-    #self.snd.session.connection.transport.trace(Transport.TRACE_FRM)
-
-    ## verify that a sender that has reached the drain state will respond
-    ## promptly to a drain issued by the peer.
-    self.rcv.flow(10)
-    self.pump()
-    assert self.snd.credit == 10, self.snd.credit
-    assert self.rcv.credit == 10, self.rcv.credit
-
-    sd = self.snd.delivery("tagA")
-    assert sd
-    n = self.snd.send(b"A")
-    assert n == 1
-    self.pump()
-    self.snd.advance()
-
-    # done sending, so signal that we are drained:
-    self.snd.drained()
-    self.pump()
-    assert self.snd.credit == 9, self.snd.credit
-    assert self.rcv.credit == 10, self.rcv.credit
-
-    self.rcv.drain(0)
-    self.pump()
-    assert self.snd.credit == 9, self.snd.credit
-    assert self.rcv.credit == 10, self.rcv.credit
-
-    data = self.rcv.recv(10)
-    assert data == b"A", data
-    self.rcv.advance()
-    self.pump()
-    assert self.snd.credit == 9, self.snd.credit
-    assert self.rcv.credit == 9, self.rcv.credit
-
-    self.snd.drained()
-    self.pump()
-    assert self.snd.credit == 0, self.snd.credit
-    assert self.rcv.credit == 0, self.rcv.credit
-
-    # verify that a drain requested by the peer is not "acknowledged" until
-    # after the sender has completed sending its pending messages
-
-    self.rcv.flow(10)
-    self.pump()
-    assert self.snd.credit == 10, self.snd.credit
-    assert self.rcv.credit == 10, self.rcv.credit
-
-    sd = self.snd.delivery("tagB")
-    assert sd
-    n = self.snd.send(b"B")
-    assert n == 1
-    self.snd.advance()
-    self.pump()
-    assert self.snd.credit == 9, self.snd.credit
-    assert self.rcv.credit == 10, self.rcv.credit
-
-    self.rcv.drain(0)
-    self.pump()
-    assert self.snd.credit == 9, self.snd.credit
-    assert self.rcv.credit == 10, self.rcv.credit
-
-    sd = self.snd.delivery("tagC")
-    assert sd
-    n = self.snd.send(b"C")
-    assert n == 1
-    self.snd.advance()
-    self.pump()
-    assert self.snd.credit == 8, self.snd.credit
-    assert self.rcv.credit == 10, self.rcv.credit
-
-    # now that the sender has finished sending everything, it can signal
-    # drained
-    self.snd.drained()
-    self.pump()
-    assert self.snd.credit == 0, self.snd.credit
-    assert self.rcv.credit == 2, self.rcv.credit
-
-    data = self.rcv.recv(10)
-    assert data == b"B", data
-    self.rcv.advance()
-    data = self.rcv.recv(10)
-    assert data == b"C", data
-    self.rcv.advance()
-    self.pump()
-    assert self.snd.credit == 0, self.snd.credit
-    assert self.rcv.credit == 0, self.rcv.credit
-
-
-  def testPushback(self, count=10):
-    assert self.snd.credit == 0
-    assert self.rcv.credit == 0
-
-    self.rcv.flow(count)
-    self.pump()
-
-    for i in range(count):
-      d = self.snd.delivery("tag%s" % i)
-      assert d
-      self.snd.advance()
-
-    assert self.snd.queued == count
-    assert self.rcv.queued == 0
-    self.pump()
-    assert self.snd.queued == 0
-    assert self.rcv.queued == count
-
-    d = self.snd.delivery("extra")
-    self.snd.advance()
-
-    assert self.snd.queued == 1
-    assert self.rcv.queued == count
-    self.pump()
-    assert self.snd.queued == 1
-    assert self.rcv.queued == count
-
-  def testHeadOfLineBlocking(self):
-      self.snd2 = self.snd.session.sender("link-2")
-      self.rcv2 = self.rcv.session.receiver("link-2")
-      self.snd2.open()
-      self.rcv2.open()
-      self.pump()
-      assert self.snd2.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-      assert self.rcv2.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
-
-      self.rcv.flow(5)
-      self.rcv2.flow(10)
-      self.pump()
-
-      assert self.snd.credit == 5
-      assert self.snd2.credit == 10
-
-      for i in range(10):
-          tag = "test %d" % i
-          self.snd.delivery( tag )
-          self.snd.send( tag.encode("ascii") )
-          assert self.snd.advance()
-          self.snd2.delivery( tag )
-          self.snd2.send( tag.encode("ascii") )
-          assert self.snd2.advance()
-
-      self.pump()
-
-      for i in range(5):
-          b = self.rcv.recv( 512 )
-          assert self.rcv.advance()
-          b = self.rcv2.recv( 512 )
-          assert self.rcv2.advance()
-
-      for i in range(5):
-          b = self.rcv2.recv( 512 )
-          assert self.rcv2.advance()
+    def setUp(self):
+        self.snd, self.rcv = self.link("test-link", max_frame=(16*1024, 16*1024))
+        self.c1 = self.snd.session.connection
+        self.c2 = self.rcv.session.connection
+        self.snd.open()
+        self.rcv.open()
+        self.pump()
+
+    def cleanup(self):
+        # release resources created by this class
+        super(CreditTest, self).cleanup()
+        self.c1 = None
+        self.snd = None
+        self.c2 = None
+        self.rcv2 = None
+        self.snd2 = None
+
+    def tearDown(self):
+        self.cleanup()
+
+    def testCreditSender(self, count=1024):
+        credit = self.snd.credit
+        assert credit == 0, credit
+        self.rcv.flow(10)
+        self.pump()
+        credit = self.snd.credit
+        assert credit == 10, credit
+
+        self.rcv.flow(count)
+        self.pump()
+        credit = self.snd.credit
+        assert credit == 10 + count, credit
+
+    def testCreditReceiver(self):
+        self.rcv.flow(10)
+        self.pump()
+        assert self.rcv.credit == 10, self.rcv.credit
+
+        d = self.snd.delivery("tag")
+        assert d
+        assert self.snd.advance()
+        self.pump()
+        assert self.rcv.credit == 10, self.rcv.credit
+        assert self.rcv.queued == 1, self.rcv.queued
+        c = self.rcv.current
+        assert c.tag == "tag", c.tag
+        assert self.rcv.advance()
+        assert self.rcv.credit == 9, self.rcv.credit
+        assert self.rcv.queued == 0, self.rcv.queued
+
+    def _testBufferingOnClose(self, a, b):
+        for i in range(10):
+            d = self.snd.delivery("tag-%s" % i)
+            assert d
+            d.settle()
+        self.pump()
+        assert self.snd.queued == 10
 
+        endpoints = {"connection": (self.c1, self.c2),
+                     "session": (self.snd.session, self.rcv.session),
+                     "link": (self.snd, self.rcv)}
+
+        local_a, remote_a = endpoints[a]
+        local_b, remote_b = endpoints[b]
+
+        remote_b.close()
+        self.pump()
+        assert local_b.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED
+        local_a.close()
+        self.pump()
+        assert remote_a.state & Endpoint.REMOTE_CLOSED
+        assert self.snd.queued == 10
+
+    def testBufferingOnCloseLinkLink(self):
+        self._testBufferingOnClose("link", "link")
+
+    def testBufferingOnCloseLinkSession(self):
+        self._testBufferingOnClose("link", "session")
+
+    def testBufferingOnCloseLinkConnection(self):
+        self._testBufferingOnClose("link", "connection")
+
+    def testBufferingOnCloseSessionLink(self):
+        self._testBufferingOnClose("session", "link")
+
+    def testBufferingOnCloseSessionSession(self):
+        self._testBufferingOnClose("session", "session")
+
+    def testBufferingOnCloseSessionConnection(self):
+        self._testBufferingOnClose("session", "connection")
+
+    def testBufferingOnCloseConnectionLink(self):
+        self._testBufferingOnClose("connection", "link")
+
+    def testBufferingOnCloseConnectionSession(self):
+        self._testBufferingOnClose("connection", "session")
+
+    def testBufferingOnCloseConnectionConnection(self):
+        self._testBufferingOnClose("connection", "connection")
+
+    def testFullDrain(self):
+        assert self.rcv.credit == 0
+        assert self.snd.credit == 0
+        self.rcv.drain(10)
+        assert self.rcv.draining()
+        assert self.rcv.credit == 10
+        assert self.snd.credit == 0
+        self.pump()
+        assert self.rcv.credit == 10
+        assert self.snd.credit == 10
+        assert self.rcv.draining()
+        self.snd.drained()
+        assert self.rcv.credit == 10
+        assert self.snd.credit == 0
+        assert self.rcv.draining()
+        self.pump()
+        assert self.rcv.credit == 0
+        assert self.snd.credit == 0
+        assert not self.rcv.draining()
+        drained = self.rcv.drained()
+        assert drained == 10, drained
+
+    def testPartialDrain(self):
+        self.rcv.drain(2)
+        assert self.rcv.draining()
+        self.pump()
+
+        d = self.snd.delivery("tag")
+        assert d
+        assert self.snd.advance()
+        self.snd.drained()
+        assert self.rcv.draining()
+        self.pump()
+        assert not self.rcv.draining()
+
+        c = self.rcv.current
+        assert self.rcv.queued == 1, self.rcv.queued
+        assert c.tag == d.tag, c.tag
+        assert self.rcv.advance()
+        assert not self.rcv.current
+        assert self.rcv.credit == 0, self.rcv.credit
+        assert not self.rcv.draining()
+        drained = self.rcv.drained()
+        assert drained == 1, drained
+
+    def testDrainFlow(self):
+        assert self.rcv.credit == 0
+        assert self.snd.credit == 0
+        self.rcv.drain(10)
+        assert self.rcv.credit == 10
+        assert self.snd.credit == 0
+        self.pump()
+        assert self.rcv.credit == 10
+        assert self.snd.credit == 10
+        self.snd.drained()
+        assert self.rcv.credit == 10
+        assert self.snd.credit == 0
+        self.pump()
+        assert self.rcv.credit == 0
+        assert self.snd.credit == 0
+        self.rcv.flow(10)
+        assert self.rcv.credit == 10
+        assert self.snd.credit == 0
+        self.pump()
+        assert self.rcv.credit == 10
+        assert self.snd.credit == 10
+        self.snd.drained()
+        assert self.rcv.credit == 10
+        assert self.snd.credit == 10
+        self.pump()
+        assert self.rcv.credit == 10
+        assert self.snd.credit == 10
+        drained = self.rcv.drained()
+        assert drained == 10, drained
+
+    def testNegative(self):
+        assert self.snd.credit == 0
+        d = self.snd.delivery("tag")
+        assert d
+        assert self.snd.advance()
+        self.pump()
+
+        assert self.rcv.credit == 0
+        assert self.rcv.queued == 0
+
+        self.rcv.flow(1)
+        assert self.rcv.credit == 1
+        assert self.rcv.queued == 0
+        self.pump()
+        assert self.rcv.credit == 1
+        assert self.rcv.queued == 1, self.rcv.queued
+
+        c = self.rcv.current
+        assert c
+        assert c.tag == "tag"
+        assert self.rcv.advance()
+        assert self.rcv.credit == 0
+        assert self.rcv.queued == 0
+
+    def testDrainZero(self):
+        assert self.snd.credit == 0
+        assert self.rcv.credit == 0
+        assert self.rcv.queued == 0
+        drained = self.rcv.drained()
+        assert drained == 0
+
+        self.rcv.flow(10)
+        self.pump()
+        assert self.snd.credit == 10
+        assert self.rcv.credit == 10
+        assert self.rcv.queued == 0
+
+        self.snd.drained()
+        self.pump()
+        assert self.snd.credit == 10
+        assert self.rcv.credit == 10
+        assert self.rcv.queued == 0
+        drained = self.rcv.drained()
+        assert drained == 0
+
+        self.rcv.drain(0)
+        assert self.snd.credit == 10
+        assert self.rcv.credit == 10
+        assert self.rcv.queued == 0
+
+        self.pump()
+
+        assert self.snd.credit == 10
+        assert self.rcv.credit == 10
+        assert self.rcv.queued == 0
+
+        self.snd.drained()
+        assert self.snd.credit == 0
+        assert self.rcv.credit == 10
+        assert self.rcv.queued == 0
+        drained = self.rcv.drained()
+        assert drained == 0
+        self.pump()
+
+        assert self.snd.credit == 0
+        assert self.rcv.credit == 0
+        assert self.rcv.queued == 0
+        drained = self.rcv.drained()
+        assert drained == 10
+
+    def testDrainOrder(self):
+        """ Verify drain/drained works regardless of ordering.  See PROTON-401
+        """
+        assert self.snd.credit == 0
+        assert self.rcv.credit == 0
+        assert self.rcv.queued == 0
+
+        # self.rcv.session.connection.transport.trace(Transport.TRACE_FRM)
+        # self.snd.session.connection.transport.trace(Transport.TRACE_FRM)
+
+        # verify that a sender that has reached the drain state will respond
+        # promptly to a drain issued by the peer.
+        self.rcv.flow(10)
+        self.pump()
+        assert self.snd.credit == 10, self.snd.credit
+        assert self.rcv.credit == 10, self.rcv.credit
+
+        sd = self.snd.delivery("tagA")
+        assert sd
+        n = self.snd.send(b"A")
+        assert n == 1
+        self.pump()
+        self.snd.advance()
+
+        # done sending, so signal that we are drained:
+        self.snd.drained()
+        self.pump()
+        assert self.snd.credit == 9, self.snd.credit
+        assert self.rcv.credit == 10, self.rcv.credit
+
+        self.rcv.drain(0)
+        self.pump()
+        assert self.snd.credit == 9, self.snd.credit
+        assert self.rcv.credit == 10, self.rcv.credit
+
+        data = self.rcv.recv(10)
+        assert data == b"A", data
+        self.rcv.advance()
+        self.pump()
+        assert self.snd.credit == 9, self.snd.credit
+        assert self.rcv.credit == 9, self.rcv.credit
+
+        self.snd.drained()
+        self.pump()
+        assert self.snd.credit == 0, self.snd.credit
+        assert self.rcv.credit == 0, self.rcv.credit
+
+        # verify that a drain requested by the peer is not "acknowledged" until
+        # after the sender has completed sending its pending messages
+
+        self.rcv.flow(10)
+        self.pump()
+        assert self.snd.credit == 10, self.snd.credit
+        assert self.rcv.credit == 10, self.rcv.credit
+
+        sd = self.snd.delivery("tagB")
+        assert sd
+        n = self.snd.send(b"B")
+        assert n == 1
+        self.snd.advance()
+        self.pump()
+        assert self.snd.credit == 9, self.snd.credit
+        assert self.rcv.credit == 10, self.rcv.credit
+
+        self.rcv.drain(0)
+        self.pump()
+        assert self.snd.credit == 9, self.snd.credit
+        assert self.rcv.credit == 10, self.rcv.credit
+
+        sd = self.snd.delivery("tagC")
+        assert sd
+        n = self.snd.send(b"C")
+        assert n == 1
+        self.snd.advance()
+        self.pump()
+        assert self.snd.credit == 8, self.snd.credit
+        assert self.rcv.credit == 10, self.rcv.credit
+
+        # now that the sender has finished sending everything, it can signal
+        # drained
+        self.snd.drained()
+        self.pump()
+        assert self.snd.credit == 0, self.snd.credit
+        assert self.rcv.credit == 2, self.rcv.credit
+
+        data = self.rcv.recv(10)
+        assert data == b"B", data
+        self.rcv.advance()
+        data = self.rcv.recv(10)
+        assert data == b"C", data
+        self.rcv.advance()
+        self.pump()
+        assert self.snd.credit == 0, self.snd.credit
+        assert self.rcv.credit == 0, self.rcv.credit
+
+    def testPushback(self, count=10):
+        assert self.snd.credit == 0
+        assert self.rcv.credit == 0
+
+        self.rcv.flow(count)
+        self.pump()
+
+        for i in range(count):
+            d = self.snd.delivery("tag%s" % i)
+            assert d
+            self.snd.advance()
+
+        assert self.snd.queued == count
+        assert self.rcv.queued == 0
+        self.pump()
+        assert self.snd.queued == 0
+        assert self.rcv.queued == count
+
+        d = self.snd.delivery("extra")
+        self.snd.advance()
+
+        assert self.snd.queued == 1
+        assert self.rcv.queued == count
+        self.pump()
+        assert self.snd.queued == 1
+        assert self.rcv.queued == count
+
+    def testHeadOfLineBlocking(self):
+        self.snd2 = self.snd.session.sender("link-2")
+        self.rcv2 = self.rcv.session.receiver("link-2")
+        self.snd2.open()
+        self.rcv2.open()
+        self.pump()
+        assert self.snd2.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+        assert self.rcv2.state == Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE
+
+        self.rcv.flow(5)
+        self.rcv2.flow(10)
+        self.pump()
+
+        assert self.snd.credit == 5
+        assert self.snd2.credit == 10
+
+        for i in range(10):
+            tag = "test %d" % i
+            self.snd.delivery(tag)
+            self.snd.send(tag.encode("ascii"))
+            assert self.snd.advance()
+            self.snd2.delivery(tag)
+            self.snd2.send(tag.encode("ascii"))
+            assert self.snd2.advance()
+
+        self.pump()
+
+        for i in range(5):
+            b = self.rcv.recv(512)
+            assert self.rcv.advance()
+            b = self.rcv2.recv(512)
+            assert self.rcv2.advance()
+
+        for i in range(5):
+            b = self.rcv2.recv(512)
+            assert self.rcv2.advance()
 
 
 class SessionCreditTest(Test):
 
-  def tearDown(self):
-    self.cleanup()
-
-  def testBuffering(self, count=32, size=1024, capacity=16*1024, max_frame=1024):
-    snd, rcv = self.link("test-link", max_frame=(max_frame, max_frame))
-    rcv.session.incoming_capacity = capacity
-    snd.open()
-    rcv.open()
-    rcv.flow(count)
-    self.pump()
-
-    assert count > 0
-
-    total_bytes = count * size
-
-    assert snd.session.outgoing_bytes == 0, snd.session.outgoing_bytes
-    assert rcv.session.incoming_bytes == 0, rcv.session.incoming_bytes
-    assert snd.queued == 0, snd.queued
-    assert rcv.queued == 0, rcv.queued
-
-    data = bytes(bytearray(size))
-    idx = 0
-    while snd.credit:
-      d = snd.delivery("tag%s" % idx)
-      assert d
-      n = snd.send(data)
-      assert n == size, (n, size)
-      assert snd.advance()
-      self.pump()
-      idx += 1
-
-    assert idx == count, (idx, count)
-
-    assert snd.session.outgoing_bytes < total_bytes, (snd.session.outgoing_bytes, total_bytes)
-    assert rcv.session.incoming_bytes < capacity, (rcv.session.incoming_bytes, capacity)
-    assert snd.session.outgoing_bytes + rcv.session.incoming_bytes == total_bytes, \
-        (snd.session.outgoing_bytes, rcv.session.incoming_bytes, total_bytes)
-    if snd.session.outgoing_bytes > 0:
-      available = rcv.session.incoming_capacity - rcv.session.incoming_bytes
-      assert available < max_frame, (available, max_frame)
-
-    for i in range(count):
-      d = rcv.current
-      assert d, i
-      pending = d.pending
-      before = rcv.session.incoming_bytes
-      assert rcv.advance()
-      after = rcv.session.incoming_bytes
-      assert before - after == pending, (before, after, pending)
-      snd_before = snd.session.incoming_bytes
-      self.pump()
-      snd_after = snd.session.incoming_bytes
-
-      assert rcv.session.incoming_bytes < capacity
-      if snd_before > 0:
-        assert capacity - after <= max_frame
-        assert snd_before > snd_after
-      if snd_after > 0:
-        available = rcv.session.incoming_capacity - rcv.session.incoming_bytes
-        assert available < max_frame, available
-
-  def testBufferingSize16(self):
-    self.testBuffering(size=16)
-
-  def testBufferingSize256(self):
-    self.testBuffering(size=256)
-
-  def testBufferingSize512(self):
-    self.testBuffering(size=512)
-
-  def testBufferingSize2048(self):
-    self.testBuffering(size=2048)
-
-  def testBufferingSize1025(self):
-    self.testBuffering(size=1025)
-
-  def testBufferingSize1023(self):
-    self.testBuffering(size=1023)
-
-  def testBufferingSize989(self):
-    self.testBuffering(size=989)
-
-  def testBufferingSize1059(self):
-    self.testBuffering(size=1059)
-
-  def testCreditWithBuffering(self):
-    snd, rcv = self.link("test-link", max_frame=(1024, 1024))
-    rcv.session.incoming_capacity = 64*1024
-    snd.open()
-    rcv.open()
-    rcv.flow(128)
-    self.pump()
-
-    assert snd.credit == 128, snd.credit
-    assert rcv.queued == 0, rcv.queued
-
-    idx = 0
-    while snd.credit:
-      d = snd.delivery("tag%s" % idx)
-      snd.send(("x"*1024).encode('ascii'))
-      assert d
-      assert snd.advance()
-      self.pump()
-      idx += 1
-
-    assert idx == 128, idx
-    assert rcv.queued < 128, rcv.queued
-
-    rcv.flow(1)
-    self.pump()
-    assert snd.credit == 1, snd.credit
+    def tearDown(self):
+        self.cleanup()
+
+    def testBuffering(self, count=32, size=1024, capacity=16*1024, max_frame=1024):
+        snd, rcv = self.link("test-link", max_frame=(max_frame, max_frame))
+        rcv.session.incoming_capacity = capacity
+        snd.open()
+        rcv.open()
+        rcv.flow(count)
+        self.pump()
+
+        assert count > 0
+
+        total_bytes = count * size
+
+        assert snd.session.outgoing_bytes == 0, snd.session.outgoing_bytes
+        assert rcv.session.incoming_bytes == 0, rcv.session.incoming_bytes
+        assert snd.queued == 0, snd.queued
+        assert rcv.queued == 0, rcv.queued
+
+        data = bytes(bytearray(size))
+        idx = 0
+        while snd.credit:
+            d = snd.delivery("tag%s" % idx)
+            assert d
+            n = snd.send(data)
+            assert n == size, (n, size)
+            assert snd.advance()
+            self.pump()
+            idx += 1
+
+        assert idx == count, (idx, count)
+
+        assert snd.session.outgoing_bytes < total_bytes, (snd.session.outgoing_bytes, total_bytes)
+        assert rcv.session.incoming_bytes < capacity, (rcv.session.incoming_bytes, capacity)
+        assert snd.session.outgoing_bytes + rcv.session.incoming_bytes == total_bytes, \
+            (snd.session.outgoing_bytes, rcv.session.incoming_bytes, total_bytes)
+        if snd.session.outgoing_bytes > 0:
+            available = rcv.session.incoming_capacity - rcv.session.incoming_bytes
+            assert available < max_frame, (available, max_frame)
+
+        for i in range(count):
+            d = rcv.current
+            assert d, i
+            pending = d.pending
+            before = rcv.session.incoming_bytes
+            assert rcv.advance()
+            after = rcv.session.incoming_bytes
+            assert before - after == pending, (before, after, pending)
+            snd_before = snd.session.incoming_bytes
+            self.pump()
+            snd_after = snd.session.incoming_bytes
+
+            assert rcv.session.incoming_bytes < capacity
+            if snd_before > 0:
+                assert capacity - after <= max_frame
+                assert snd_before > snd_after
+            if snd_after > 0:
+                available = rcv.session.incoming_capacity - rcv.session.incoming_bytes
+                assert available < max_frame, available
+
+    def testBufferingSize16(self):
+        self.testBuffering(size=16)
+
+    def testBufferingSize256(self):
+        self.testBuffering(size=256)
+
+    def testBufferingSize512(self):
+        self.testBuffering(size=512)
+
+    def testBufferingSize2048(self):
+        self.testBuffering(size=2048)
+
+    def testBufferingSize1025(self):
+        self.testBuffering(size=1025)
+
+    def testBufferingSize1023(self):
+        self.testBuffering(size=1023)
+
+    def testBufferingSize989(self):
+        self.testBuffering(size=989)
+
+    def testBufferingSize1059(self):
+        self.testBuffering(size=1059)
+
+    def testCreditWithBuffering(self):
+        snd, rcv = self.link("test-link", max_frame=(1024, 1024))
+        rcv.session.incoming_capacity = 64*1024
+        snd.open()
+        rcv.open()
+        rcv.flow(128)
+        self.pump()
+
+        assert snd.credit == 128, snd.credit
+        assert rcv.queued == 0, rcv.queued
+
+        idx = 0
+        while snd.credit:
+            d = snd.delivery("tag%s" % idx)
+            snd.send(("x"*1024).encode('ascii'))
+            assert d
+            assert snd.advance()
+            self.pump()
+            idx += 1
+
+        assert idx == 128, idx
+        assert rcv.queued < 128, rcv.queued
+
+        rcv.flow(1)
+        self.pump()
+        assert snd.credit == 1, snd.credit
+
 
 class SettlementTest(Test):
 
-  def setUp(self):
-    self.snd, self.rcv = self.link("test-link")
-    self.c1 = self.snd.session.connection
-    self.c2 = self.rcv.session.connection
-    self.snd.open()
-    self.rcv.open()
-    self.pump()
-
-  def cleanup(self):
-    # release resources created by this class
-    super(SettlementTest, self).cleanup()
-    self.c1 = None
-    self.snd = None
-    self.c2 = None
-    self.rcv2 = None
-    self.snd2 = None
-
-  def tearDown(self):
-    self.cleanup()
-
-  def testSettleCurrent(self):
-    self.rcv.flow(10)
-    self.pump()
-
-    assert self.snd.credit == 10, self.snd.credit
-    d = self.snd.delivery("tag")
-    e = self.snd.delivery("tag2")
-    assert d
-    assert e
-    c = self.snd.current
-    assert c.tag == "tag", c.tag
-    c.settle()
-    c = self.snd.current
-    assert c.tag == "tag2", c.tag
-    c.settle()
-    c = self.snd.current
-    assert not c
-    self.pump()
-
-    c = self.rcv.current
-    assert c
-    assert c.tag == "tag", c.tag
-    assert c.settled
-    c.settle()
-    c = self.rcv.current
-    assert c
-    assert c.tag == "tag2", c.tag
-    assert c.settled
-    c.settle()
-    c = self.rcv.current
-    assert not c
-
-  def testUnsettled(self):
-    self.rcv.flow(10)
-    self.pump()
-
-    assert self.snd.unsettled == 0, self.snd.unsettled
-    assert self.rcv.unsettled == 0, self.rcv.unsettled
-
-    d = self.snd.delivery("tag")
-    assert d
-    assert self.snd.unsettled == 1, self.snd.unsettled
-    assert self.rcv.unsettled == 0, self.rcv.unsettled
-    assert self.snd.advance()
-    self.pump()
-
-    assert self.snd.unsettled == 1, self.snd.unsettled
-    assert self.rcv.unsettled == 1, self.rcv.unsettled
-
-    c = self.rcv.current
-    assert c
-    c.settle()
-
-    assert self.snd.unsettled == 1, self.snd.unsettled
-    assert self.rcv.unsettled == 0, self.rcv.unsettled
-
-  def testMultipleUnsettled(self, count=1024, size=1024):
-    self.rcv.flow(count)
-    self.pump()
-
-    assert self.snd.unsettled == 0, self.snd.unsettled
-    assert self.rcv.unsettled == 0, self.rcv.unsettled
-
-    unsettled = []
-
-    for i in range(count):
-      sd = self.snd.delivery("tag%s" % i)
-      assert sd
-      n = self.snd.send(("x"*size).encode('ascii'))
-      assert n == size, n
-      assert self.snd.advance()
-      self.pump()
-
-      rd = self.rcv.current
-      assert rd, "did not receive delivery %s" % i
-      n = rd.pending
-      b = self.rcv.recv(n)
-      assert len(b) == n, (b, n)
-      rd.update(Delivery.ACCEPTED)
-      assert self.rcv.advance()
-      self.pump()
-      unsettled.append(rd)
-
-    assert self.rcv.unsettled == count
-
-    for rd in unsettled:
-      rd.settle()
-
-  def testMultipleUnsettled2K1K(self):
-    self.testMultipleUnsettled(2048, 1024)
-
-  def testMultipleUnsettled4K1K(self):
-    self.testMultipleUnsettled(4096, 1024)
-
-  def testMultipleUnsettled1K2K(self):
-    self.testMultipleUnsettled(1024, 2048)
-
-  def testMultipleUnsettled2K2K(self):
-    self.testMultipleUnsettled(2048, 2048)
-
-  def testMultipleUnsettled4K2K(self):
-    self.testMultipleUnsettled(4096, 2048)
+    def setUp(self):
+        self.snd, self.rcv = self.link("test-link")
+        self.c1 = self.snd.session.connection
+        self.c2 = self.rcv.session.connection
+        self.snd.open()
+        self.rcv.open()
+        self.pump()
+
+    def cleanup(self):
+        # release resources created by this class
+        super(SettlementTest, self).cleanup()
+        self.c1 = None
+        self.snd = None
+        self.c2 = None
+        self.rcv2 = None
+        self.snd2 = None
+
+    def tearDown(self):
+        self.cleanup()
+
+    def testSettleCurrent(self):
+        self.rcv.flow(10)
+        self.pump()
+
+        assert self.snd.credit == 10, self.snd.credit
+        d = self.snd.delivery("tag")
+        e = self.snd.delivery("tag2")
+        assert d
+        assert e
+        c = self.snd.current
+        assert c.tag == "tag", c.tag
+        c.settle()
+        c = self.snd.current
+        assert c.tag == "tag2", c.tag
+        c.settle()
+        c = self.snd.current
+        assert not c
+        self.pump()
+
+        c = self.rcv.current
+        assert c
+        assert c.tag == "tag", c.tag
+        assert c.settled
+        c.settle()
+        c = self.rcv.current
+        assert c
+        assert c.tag == "tag2", c.tag
+        assert c.settled
+        c.settle()
+        c = self.rcv.current
+        assert not c
+
+    def testUnsettled(self):
+        self.rcv.flow(10)
+        self.pump()
+
+        assert self.snd.unsettled == 0, self.snd.unsettled
+        assert self.rcv.unsettled == 0, self.rcv.unsettled
+
+        d = self.snd.delivery("tag")
+        assert d
+        assert self.snd.unsettled == 1, self.snd.unsettled
+        assert self.rcv.unsettled == 0, self.rcv.unsettled
+        assert self.snd.advance()
+        self.pump()
+
+        assert self.snd.unsettled == 1, self.snd.unsettled
+        assert self.rcv.unsettled == 1, self.rcv.unsettled
+
+        c = self.rcv.current
+        assert c
+        c.settle()
+
+        assert self.snd.unsettled == 1, self.snd.unsettled
+        assert self.rcv.unsettled == 0, self.rcv.unsettled
+
+    def testMultipleUnsettled(self, count=1024, size=1024):
+        self.rcv.flow(count)
+        self.pump()
+
+        assert self.snd.unsettled == 0, self.snd.unsettled
+        assert self.rcv.unsettled == 0, self.rcv.unsettled
+
+        unsettled = []
+
+        for i in range(count):
+            sd = self.snd.delivery("tag%s" % i)
+            assert sd
+            n = self.snd.send(("x"*size).encode('ascii'))
+            assert n == size, n
+            assert self.snd.advance()
+            self.pump()
+
+            rd = self.rcv.current
+            assert rd, "did not receive delivery %s" % i
+            n = rd.pending
+            b = self.rcv.recv(n)
+            assert len(b) == n, (b, n)
+            rd.update(Delivery.ACCEPTED)
+            assert self.rcv.advance()
+            self.pump()
+            unsettled.append(rd)
+
+        assert self.rcv.unsettled == count
+
+        for rd in unsettled:
+            rd.settle()
+
+    def testMultipleUnsettled2K1K(self):
+        self.testMultipleUnsettled(2048, 1024)
+
+    def testMultipleUnsettled4K1K(self):
+        self.testMultipleUnsettled(4096, 1024)
+
+    def testMultipleUnsettled1K2K(self):
+        self.testMultipleUnsettled(1024, 2048)
+
+    def testMultipleUnsettled2K2K(self):
+        self.testMultipleUnsettled(2048, 2048)
+
+    def testMultipleUnsettled4K2K(self):
+        self.testMultipleUnsettled(4096, 2048)
+
 
 class PipelineTest(Test):
 
-  def setUp(self):
-    self.c1, self.c2 = self.connection()
-
-  def cleanup(self):
-    # release resources created by this class
-    super(PipelineTest, self).cleanup()
-    self.c1 = None
-    self.c2 = None
-
-  def tearDown(self):
-    self.cleanup()
-
-  def test(self):
-    ssn = self.c1.session()
-    snd = ssn.sender("sender")
-    self.c1.open()
-    ssn.open()
-    snd.open()
-
-    for i in range(10):
-      t = "delivery-%s" % i
-      d = snd.delivery(t)
-      snd.send(t.encode('ascii'))
-      d.settle()
-
-    snd.close()
-    ssn.close()
-    self.c1.close()
-
-    self.pump()
-
-    state = self.c2.state
-    assert state == (Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_ACTIVE), "%x" % state
-    ssn2 = self.c2.session_head(Endpoint.LOCAL_UNINIT)
-    assert ssn2
-    state == ssn2.state
-    assert state == (Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_ACTIVE), "%x" % state
-    rcv = self.c2.link_head(Endpoint.LOCAL_UNINIT)
-    assert rcv
-    state = rcv.state
-    assert state == (Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_ACTIVE), "%x" % state
-
-    self.c2.open()
-    ssn2.open()
-    rcv.open()
-    rcv.flow(10)
-    assert rcv.queued == 0, rcv.queued
-
-    self.pump()
-
-    assert rcv.queued == 10, rcv.queued
-    state = rcv.state
-    assert state == (Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED), "%x" % state
-    state = ssn2.state
-    assert state == (Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED), "%x" % state
-    state = self.c2.state
-    assert state == (Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED), "%x" % state
-
-    for i in range(rcv.queued):
-      d = rcv.current
-      assert d
-      assert d.tag == "delivery-%s" % i
-      d.settle()
-
-    assert rcv.queued == 0, rcv.queued
+    def setUp(self):
+        self.c1, self.c2 = self.connection()
+
+    def cleanup(self):
+        # release resources created by this class
+        super(PipelineTest, self).cleanup()
+        self.c1 = None
+        self.c2 = None
+
+    def tearDown(self):
+        self.cleanup()
+
+    def test(self):
+        ssn = self.c1.session()
+        snd = ssn.sender("sender")
+        self.c1.open()
+        ssn.open()
+        snd.open()
+
+        for i in range(10):
+            t = "delivery-%s" % i
+            d = snd.delivery(t)
+            snd.send(t.encode('ascii'))
+            d.settle()
+
+        snd.close()
+        ssn.close()
+        self.c1.close()
+
+        self.pump()
+
+        state = self.c2.state
+        assert state == (Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_ACTIVE), "%x" % state
+        ssn2 = self.c2.session_head(Endpoint.LOCAL_UNINIT)
+        assert ssn2
+        state == ssn2.state
+        assert state == (Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_ACTIVE), "%x" % state
+        rcv = self.c2.link_head(Endpoint.LOCAL_UNINIT)
+        assert rcv
+        state = rcv.state
+        assert state == (Endpoint.LOCAL_UNINIT | Endpoint.REMOTE_ACTIVE), "%x" % state
+
+        self.c2.open()
+        ssn2.open()
+        rcv.open()
+        rcv.flow(10)
+        assert rcv.queued == 0, rcv.queued
+
+        self.pump()
+
+        assert rcv.queued == 10, rcv.queued
+        state = rcv.state
+        assert state == (Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED), "%x" % state
+        state = ssn2.state
+        assert state == (Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED), "%x" % state
+        state = self.c2.state
+        assert state == (Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_CLOSED), "%x" % state
+
+        for i in range(rcv.queued):
+            d = rcv.current
+            assert d
+            assert d.tag == "delivery-%s" % i
+            d.settle()
+
+        assert rcv.queued == 0, rcv.queued
 
 
 class ServerTest(Test):
 
-  def testKeepalive(self):
-    """ Verify that idle frames are sent to keep a Connection alive
-    """
-    idle_timeout = self.delay
-    server = common.TestServer()
-    server.start()
-
-    class Program:
-
-      def on_reactor_init(self, event):
-        self.conn = event.reactor.connection()
-        self.conn.hostname = "%s:%s" % (server.host, server.port)
-        self.conn.open()
-        self.old_count = None
-        event.reactor.schedule(3 * idle_timeout, self)
-
-      def on_connection_bound(self, event):
-        event.transport.idle_timeout = idle_timeout
-
-      def on_connection_remote_open(self, event):
-        self.old_count = event.transport.frames_input
-
-      def on_timer_task(self, event):
-        assert self.conn.state == (Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE), "Connection terminated"
-        assert self.conn.transport.frames_input > self.old_count, "No idle frames received"
-        self.conn.close()
-
-    Container(Program()).run()
-    server.stop()
-
-  def testIdleTimeout(self):
-    """ Verify that a Connection is terminated properly when Idle frames do not
-    arrive in a timely manner.
-    """
-    idle_timeout = self.delay
-    server = common.TestServer(idle_timeout=idle_timeout)
-    server.start()
-
-    class Program:
-
-      def on_reactor_init(self, event):
-        self.conn = event.reactor.connection()
-        self.conn.hostname = "%s:%s" % (server.host, server.port)
-        self.conn.open()
-        self.remote_condition = None
-        self.old_count = None
-        # verify the connection stays up even if we don't explicitly send stuff
-        # wait up to 3x the idle timeout
-        event.reactor.schedule(3 * idle_timeout, self)
-
-      def on_connection_bound(self, event):
-        self.transport = event.transport
-
-      def on_connection_remote_open(self, event):
-        self.old_count = event.transport.frames_output
-
-      def on_connection_remote_close(self, event):
-        assert self.conn.remote_condition
-        assert self.conn.remote_condition.name == "amqp:resource-limit-exceeded"
-        self.remote_condition = self.conn.remote_condition
-
-      def on_timer_task(self, event):
-        assert self.conn.state == (Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE), "Connection terminated"
-        assert self.conn.transport.frames_output > self.old_count, "No idle frames sent"
-
-        # now wait to explicitly cause the other side to expire:
-        suspend_time = 3 * idle_timeout
-        if os.name=="nt":
-          # On windows, the full delay gets too close to the graceful/hard close tipping point
-          suspend_time = 2.5 * idle_timeout
-        sleep(suspend_time)
-
-    p = Program()
-    Container(p).run()
-    assert p.remote_condition
-    assert p.remote_condition.name == "amqp:resource-limit-exceeded"
-    server.stop()
+    def testKeepalive(self):
+        """ Verify that idle frames are sent to keep a Connection alive
+        """
+        idle_timeout = self.delay
+        server = common.TestServer()
+        server.start()
+
+        class Program:
+
+            def on_reactor_init(self, event):
+                self.conn = event.reactor.connection()
+                self.conn.hostname = "%s:%s" % (server.host, server.port)
+                self.conn.open()
+                self.old_count = None
+                event.reactor.schedule(3 * idle_timeout, self)
+
+            def on_connection_bound(self, event):
+                event.transport.idle_timeout = idle_timeout
+
+            def on_connection_remote_open(self, event):
+                self.old_count = event.transport.frames_input
+
+            def on_timer_task(self, event):
+                assert self.conn.state == (Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE), "Connection terminated"
+                assert self.conn.transport.frames_input > self.old_count, "No idle frames received"
+                self.conn.close()
+
+        Container(Program()).run()
+        server.stop()
+
+    def testIdleTimeout(self):
+        """ Verify that a Connection is terminated properly when Idle frames do not
+        arrive in a timely manner.
+        """
+        idle_timeout = self.delay
+        server = common.TestServer(idle_timeout=idle_timeout)
+        server.start()
+
+        class Program:
+
+            def on_reactor_init(self, event):
+                self.conn = event.reactor.connection()
+                self.conn.hostname = "%s:%s" % (server.host, server.port)
+                self.conn.open()
+                self.remote_condition = None
+                self.old_count = None
+                # verify the connection stays up even if we don't explicitly send stuff
+                # wait up to 3x the idle timeout
+                event.reactor.schedule(3 * idle_timeout, self)
+
+            def on_connection_bound(self, event):
+                self.transport = event.transport
+
+            def on_connection_remote_open(self, event):
+                self.old_count = event.transport.frames_output
+
+            def on_connection_remote_close(self, event):
+                assert self.conn.remote_condition
+                assert self.conn.remote_condition.name == "amqp:resource-limit-exceeded"
+                self.remote_condition = self.conn.remote_condition
+
+            def on_timer_task(self, event):
+                assert self.conn.state == (Endpoint.LOCAL_ACTIVE | Endpoint.REMOTE_ACTIVE), "Connection terminated"
+                assert self.conn.transport.frames_output > self.old_count, "No idle frames sent"
+
+                # now wait to explicitly cause the other side to expire:
+                suspend_time = 3 * idle_timeout
+                if os.name == "nt":
+                    # On windows, the full delay gets too close to the graceful/hard close tipping point
+                    suspend_time = 2.5 * idle_timeout
+                sleep(suspend_time)
+
+        p = Program()
+        Container(p).run()
+        assert p.remote_condition
+        assert p.remote_condition.name == "amqp:resource-limit-exceeded"
+        server.stop()
+
 
 class NoValue:
 
-  def __init__(self):
-    pass
+    def __init__(self):
+        pass
 
-  def apply(self, dlv):
-    pass
+    def apply(self, dlv):
+        pass
+
+    def check(self, dlv):
+        assert dlv.data == None
+        assert dlv.section_number == 0
+        assert dlv.section_offset == 0
+        assert dlv.condition == None
+        assert dlv.failed == False
+        assert dlv.undeliverable == False
+        assert dlv.annotations == None
 
-  def check(self, dlv):
-    assert dlv.data == None
-    assert dlv.section_number == 0
-    assert dlv.section_offset == 0
-    assert dlv.condition == None
-    assert dlv.failed == False
-    assert dlv.undeliverable == False
-    assert dlv.annotations == None
 
 class RejectValue:
-  def __init__(self, condition):
-    self.condition = condition
+    def __init__(self, condition):
+        self.condition = condition
+
+    def apply(self, dlv):
+        dlv.condition = self.condition
 
-  def apply(self, dlv):
-    dlv.condition = self.condition
+    def check(self, dlv):
+        assert dlv.data == None, dlv.data
+        assert dlv.section_number == 0
+        assert dlv.section_offset == 0
+        assert dlv.condition == self.condition, (dlv.condition, self.condition)
+        assert dlv.failed == False
+        assert dlv.undeliverable == False
+        assert dlv.annotations == None
 
-  def check(self, dlv):
-    assert dlv.data == None, dlv.data
-    assert dlv.section_number == 0
-    assert dlv.section_offset == 0
-    assert dlv.condition == self.condition, (dlv.condition, self.condition)
-    assert dlv.failed == False
-    assert dlv.undeliverable == False
-    assert dlv.annotations == None
 
 class ReceivedValue:
-  def __init__(self, section_number, section_offset):
-    self.section_number = section_number
-    self.section_offset = section_offset
-
-  def apply(self, dlv):
-    dlv.section_number = self.section_number
-    dlv.section_offset = self.section_offset
-
-  def check(self, dlv):
-    assert dlv.data == None, dlv.data
-    assert dlv.section_number == self.section_number, (dlv.section_number, self.section_number)
-    assert dlv.section_offset == self.section_offset
-    assert dlv.condition == None
-    assert dlv.failed == False
-    assert dlv.undeliverable == False
-    assert dlv.annotations == None
+    def __init__(self, section_number, section_offset):
+        self.section_number = section_number
+        self.section_offset = section_offset
+
+    def apply(self, dlv):
+        dlv.section_number = self.section_number
+        dlv.section_offset = self.section_offset
+
+    def check(self, dlv):
+        assert dlv.data == None, dlv.data
+        assert dlv.section_number == self.section_number, (dlv.section_number, self.section_number)
+        assert dlv.section_offset == self.section_offset
+        assert dlv.condition == None
+        assert dlv.failed == False
+        assert dlv.undeliverable == False
+        assert dlv.annotations == None
+
 
 class ModifiedValue:
-  def __init__(self, failed, undeliverable, annotations):
-    self.failed = failed
-    self.undeliverable = undeliverable
-    self.annotations = annotations
-
-  def apply(self, dlv):
-    dlv.failed = self.failed
-    dlv.undeliverable = self.undeliverable
-    dlv.annotations = self.annotations
-
-  def check(self, dlv):
-    assert dlv.data == None, dlv.data
-    assert dlv.section_number == 0
-    assert dlv.section_offset == 0
-    assert dlv.condition == None
-    assert dlv.failed == self.failed
-    assert dlv.undeliverable == self.undeliverable
-    assert dlv.annotations == self.annotations, (dlv.annotations, self.annotations)
+    def __init__(self, failed, undeliverable, annotations):
+        self.failed = failed
+        self.undeliverable = undeliverable
+        self.annotations = annotations
+
+    def apply(self, dlv):
+        dlv.failed = self.failed
+        dlv.undeliverable = self.undeliverable
+        dlv.annotations = self.annotations
+
+    def check(self, dlv):
+        assert dlv.data == None, dlv.data
+        assert dlv.section_number == 0
+        assert dlv.section_offset == 0
+        assert dlv.condition == None
+        assert dlv.failed == self.failed
+        assert dlv.undeliverable == self.undeliverable
+        assert dlv.annotations == self.annotations, (dlv.annotations, self.annotations)
+
 
 class CustomValue:
-  def __init__(self, data):
-    self.data = data
+    def __init__(self, data):
+        self.data = data
+
+    def apply(self, dlv):
+        dlv.data = self.data
 
-  def apply(self, dlv):
-    dlv.data = self.data
+    def check(self, dlv):
+        assert dlv.data == self.data, (dlv.data, self.data)
+        assert dlv.section_number == 0
+        assert dlv.section_offset == 0
+        assert dlv.condition == None
+        assert dlv.failed == False
+        assert dlv.undeliverable == False
+        assert dlv.annotations == None
 
-  def check(self, dlv):
-    assert dlv.data == self.data, (dlv.data, self.data)
-    assert dlv.section_number == 0
-    assert dlv.section_offset == 0
-    assert dlv.condition == None
-    assert dlv.failed == False
-    assert dlv.undeliverable == False
-    assert dlv.annotations == None
 
 class DeliveryTest(Test):
 
-  def tearDown(self):
-    self.cleanup()
+    def tearDown(self):
+        self.cleanup()
 
-  def testDisposition(self, count=1, tag="tag%i", type=Delivery.ACCEPTED, value=NoValue()):
-    snd, rcv = self.link("test-link")
-    snd.open()
-    rcv.open()
+    def testDisposition(self, count=1, tag="tag%i", type=Delivery.ACCEPTED, value=NoValue()):
+        snd, rcv = self.link("test-link")
+        snd.open()
+        rcv.open()
 
-    snd_deliveries = []
-    for i in range(count):
-      d = snd.delivery(tag % i)
-      snd_deliveries.append(d)
-      snd.advance()
+        snd_deliveries = []
+        for i in range(count):
+            d = snd.delivery(tag % i)
+            snd_deliveries.append(d)
+            snd.advance()
 
-    rcv.flow(count)
-    self.pump()
+        rcv.flow(count)
+        self.pump()
+
+        rcv_deliveries = []
+        for i in range(count):
+            d = rcv.current
+            assert d.tag == (tag % i)
+            rcv_deliveries.append(d)
+            rcv.advance()
 
-    rcv_deliveries = []
-    for i in range(count):
-      d = rcv.current
-      assert d.tag == (tag % i)
-      rcv_deliveries.append(d)
-      rcv.advance()
+        for d in rcv_deliveries:
+            value.apply(d.local)
+            d.update(type)
 
-    for d in rcv_deliveries:
-      value.apply(d.local)
-      d.update(type)
+        self.pump()
 
-    self.pump()
+        for d in snd_deliveries:
+            assert d.remote_state == type
+            assert d.remote.type == type
+            value.check(d.remote)
+            value.apply(d.local)
+            d.update(type)
 
-    for d in snd_deliveries:
-      assert d.remote_state == type
-      assert d.remote.type == type
-      value.check(d.remote)
-      value.apply(d.local)
-      d.update(type)
+        self.pump()
 
-    self.pump()
+        for d in rcv_deliveries:
+            assert d.remote_state == type
+            assert d.remote.type == type
+            value.check(d.remote)
 
-    for d in rcv_deliveries:
-      assert d.remote_state == type
-      assert d.remote.type == type
-      value.check(d.remote)
+        for d in snd_deliveries:
+            d.settle()
 
-    for d in snd_deliveries:
-      d.settle()
+        self.pump()
 
-    self.pump()
+        for d in rcv_deliveries:
+            assert d.settled, d.settled
+            d.settle()
 
-    for d in rcv_deliveries:
-      assert d.settled, d.settled
-      d.settle()
+    def testReceived(self):
+        self.testDisposition(type=Disposition.RECEIVED, value=ReceivedValue(1, 2))
 
-  def testReceived(self):
-    self.testDisposition(type=Disposition.RECEIVED, value=ReceivedValue(1, 2))
+    def testRejected(self):
+        self.testDisposition(type=Disposition.REJECTED, value=RejectValue(Condition(symbol("foo"))))
 
-  def testRejected(self):
-    self.testDisposition(type=Disposition.REJECTED, value=RejectValue(Condition(symbol("foo"))))
+    def testReleased(self):
+        self.testDisposition(type=Disposition.RELEASED)
 
-  def testReleased(self):
-    self.testDisposition(type=Disposition.RELEASED)
+    def testModified(self):
+        self.testDisposition(type=Disposition.MODIFIED,
+                             value=ModifiedValue(failed=True, undeliverable=True,
+                                                 annotations={"key": "value"}))
 
-  def testModified(self):
-    self.testDisposition(type=Disposition.MODIFIED,
-                         value=ModifiedValue(failed=True, undeliverable=True,
-                                             annotations={"key": "value"}))
+    def testCustom(self):
+        self.testDisposition(type=0x12345, value=CustomValue([1, 2, 3]))
 
-  def testCustom(self):
-    self.testDisposition(type=0x12345, value=CustomValue([1, 2, 3]))
 
 class CollectorTest(Test):
 
-  def setUp(self):
-    self.collector = Collector()
-
-  def drain(self):
-    result = []
-    while True:
-      e = self.collector.peek()
-      if e:
-        result.append(e)
-        self.collector.pop()
-      else:
-        break
-    return result
-
-  def expect(self, *types):
-    return self.expect_oneof(types)
-
-  def expect_oneof(self, *sequences):
-    events = self.drain()
-    types = tuple([e.type for e in events])
-
-    for alternative in sequences:
-      if types == alternative:
-        if len(events) == 1:
-          return events[0]
-        elif len(events) > 1:
-          return events
-        else:
-          return
+    def setUp(self):
+        self.collector = Collector()
+
+    def drain(self):
+        result = []
+        while True:
+            e = self.collector.peek()
+            if e:
+                result.append(e)
+                self.collector.pop()
+            else:
+                break
+        return result
+
+    def expect(self, *types):
+        return self.expect_oneof(types)
+
+    def expect_oneof(self, *sequences):
+        events = self.drain()
+        types = tuple([e.type for e in events])
+
+        for alternative in sequences:
+            if types == alternative:
+                if len(events) == 1:
+                    return events[0]
+                elif len(events) > 1:
+                    return events
+                else:
+                    return
 
-    assert False, "actual events %s did not match any of the expected sequences: %s" % (events, sequences)
+        assert False, "actual events %s did not match any of the expected sequences: %s" % (events, sequences)
+
+    def expect_until(self, *types):
+        events = self.drain()
+        etypes = tuple([e.type for e in events[-len(types):]])
+        assert etypes == types, "actual events %s did not end in expect sequence: %s" % (events, types)
 
-  def expect_until(self, *types):
-    events = self.drain()
-    etypes = tuple([e.type for e in events[-len(types):]])
-    assert etypes == types, "actual events %s did not end in expect sequence: %s" % (events, types)
 
 class EventTest(CollectorTest):
 
-  def tearDown(self):
-    self.cleanup()
-
-  def testEndpointEvents(self):
-    c1, c2 = self.connection()
-    c1.collect(self.collector)
-    self.expect(Event.CONNECTION_INIT)
-    self.pump()
-    self.expect()
-    c2.open()
-    self.pump()
-    self.expect(Event.CONNECTION_REMOTE_OPEN)
-    self.pump()
-    self.expect()
-
-    ssn = c2.session()
-    snd = ssn.sender("sender")
-    ssn.open()
-    snd.open()
-
-    self.expect()
-    self.pump()
-    self.expect(Event.SESSION_INIT, Event.SESSION_REMOTE_OPEN,
-                Event.LINK_INIT, Event.LINK_REMOTE_OPEN)
-
-    c1.open()
-    ssn2 = c1.session()
-    ssn2.open()
-    rcv = ssn2.receiver("receiver")
-    rcv.open()
-    self.pump()
-    self.expect(Event.CONNECTION_LOCAL_OPEN, Event.TRANSPORT,
-                Event.SESSION_INIT, Event.SESSION_LOCAL_OPEN,
-                Event.TRANSPORT, Event.LINK_INIT, Event.LINK_LOCAL_OPEN,
-                Event.TRANSPORT)
-
-    rcv.close()
-    self.expect(Event.LINK_LOCAL_CLOSE, Event.TRANSPORT)
-    self.pump()
-    rcv.free()
-    del rcv
-    self.expect(Event.LINK_FINAL)
-    ssn2.free()
-    del ssn2
-    self.pump()
-    c1.free()
-    c1.transport.unbind()
-    self.expect_oneof((Event.SESSION_FINAL, Event.LINK_FINAL, Event.SESSION_FINAL,
-                       Event.CONNECTION_UNBOUND, Event.CONNECTION_FINAL),
-                      (Event.CONNECTION_UNBOUND, Event.SESSION_FINAL, Event.LINK_FINAL,
-                       Event.SESSION_FINAL, Event.CONNECTION_FINAL))
-
-  def testConnectionINIT_FINAL(self):
-    c = Connection()
-    c.collect(self.collector)
-    self.expect(Event.CONNECTION_INIT)
-    c.free()
-    self.expect(Event.CONNECTION_FINAL)
-
-  def testSessionINIT_FINAL(self):
-    c = Connection()
-    c.collect(self.collector)
-    self.expect(Event.CONNECTION_INIT)
-    s = c.session()
-    self.expect(Event.SESSION_INIT)
-    s.free()
-    self.expect(Event.SESSION_FINAL)
-    c.free()
-    self.expect(Event.CONNECTION_FINAL)
-
-  def testLinkINIT_FINAL(self):
-    c = Connection()
-    c.collect(self.collector)
-    self.expect(Event.CONNECTION_INIT)
-    s = c.session()
-    self.expect(Event.SESSION_INIT)
-    r = s.receiver("asdf")
-    self.expect(Event.LINK_INIT)
-    r.free()
-    self.expect(Event.LINK_FINAL)
-    c.free()
-    self.expect(Event.SESSION_FINAL, Event.CONNECTION_FINAL)
-
-  def testFlowEvents(self):
-    snd, rcv = self.link("test-link")
-    snd.session.connection.collect(self.collector)
-    rcv.open()
-    rcv.flow(10)
-    self.pump()
-    self.expect(Event.CONNECTION_INIT, Event.SESSION_INIT,
-                Event.LINK_INIT, Event.LINK_REMOTE_OPEN, Event.LINK_FLOW)
-    rcv.flow(10)
-    self.pump()
-    self.expect(Event.LINK_FLOW)
-    return snd, rcv
-
-  def testDeliveryEvents(self):
-    snd, rcv = self.link("test-link")
-    rcv.session.connection.collect(self.collector)
-    rcv.open()
-    rcv.flow(10)
-    self.pump()
-    self.expect(Event.CONNECTION_INIT, Event.SESSION_INIT,
-                Event.LINK_INIT, Event.LINK_LOCAL_OPEN, Event.TRANSPORT)
-    snd.delivery("delivery")
-    snd.send(b"Hello World!")
-    snd.advance()
-    self.pump()
-    self.expect()
-    snd.open()
-    self.pump()
-    self.expect(Event.LINK_REMOTE_OPEN, Event.DELIVERY)
-    rcv.session.connection.transport.unbind()
-    rcv.session.connection.free()
-    self.expect(Event.CONNECTION_UNBOUND, Event.TRANSPORT, Event.LINK_FINAL,
-                Event.SESSION_FINAL, Event.CONNECTION_FINAL)
-
-  def testDeliveryEventsDisp(self):
-    snd, rcv = self.testFlowEvents()
-    snd.open()
-    dlv = snd.delivery("delivery")
-    snd.send(b"Hello World!")
-    assert snd.advance()
-    self.expect(Event.LINK_LOCAL_OPEN, Event.TRANSPORT)
-    self.pump()
-    self.expect(Event.LINK_FLOW)
-    rdlv = rcv.current
-    assert rdlv != None
-    assert rdlv.tag == "delivery"
-    rdlv.update(Delivery.ACCEPTED)
-    self.pump()
-    event = self.expect(Event.DELIVERY)
-    assert event.context == dlv, (dlv, event.context)
-
-  def testConnectionBOUND_UNBOUND(self):
-    c = Connection()
-    c.collect(self.collector)
-    self.expect(Event.CONNECTION_INIT)
-    t = Transport()
-    t.bind(c)
-    self.expect(Event.CONNECTION_BOUND)
-    t.unbind()
-    self.expect(Event.CONNECTION_UNBOUND, Event.TRANSPORT)
-
-  def testTransportERROR_CLOSE(self):
-    c = Connection()
-    c.collect(self.collector)
-    self.expect(Event.CONNECTION_INIT)
-    t = Transport()
-    t.bind(c)
-    self.expect(Event.CONNECTION_BOUND)
-    assert t.condition is None
-    t.push(b"asdf")
-    self.expect(Event.TRANSPORT_ERROR, Event.TRANSPORT_TAIL_CLOSED)
-    assert t.condition is not None
-    assert t.condition.name == "amqp:connection:framing-error"
-    assert "AMQP protocol header" in t.condition.description
-    p = t.pending()
-    assert p > 0
-    t.pop(p)
-    self.expect(Event.TRANSPORT_HEAD_CLOSED, Event.TRANSPORT_CLOSED)
-
-  def testTransportCLOSED(self):
-    c = Connection()
-    c.collect(self.collector)
-    self.expect(Event.CONNECTION_INIT)
-    t = Transport()
-    t.bind(c)
-    c.open()
-
-    self.expect(Event.CONNECTION_BOUND, Event.CONNECTION_LOCAL_OPEN, Event.TRANSPORT)
-
-    c2 = Connection()
-    t2 = Transport()
-    t2.bind(c2)
-    c2.open()
-    c2.close()
-
-    pump(t, t2)
-
-    self.expect(Event.CONNECTION_REMOTE_OPEN, Event.CONNECTION_REMOTE_CLOSE,
-                Event.TRANSPORT_TAIL_CLOSED)
-
-    c.close()
-
-    pump(t, t2)
-
-    self.expect(Event.CONNECTION_LOCAL_CLOSE, Event.TRANSPORT,
-                Event.TRANSPORT_HEAD_CLOSED, Event.TRANSPORT_CLOSED)
-
-  def testLinkDetach(self):
-    c1 = Connection()
-    c1.collect(self.collector)
-    t1 = Transport()
-    t1.bind(c1)
-    c1.open()
-    s1 = c1.session()
-    s1.open()
-    l1 = s1.sender("asdf")
-    l1.open()
-    l1.detach()
-    self.expect_until(Event.LINK_LOCAL_DETACH, Event.TRANSPORT)
-
-    c2 = Connection()
-    c2.collect(self.collector)
-    t2 = Transport()
-    t2.bind(c2)
-
-    pump(t1, t2)
-
-    self.expect_until(Event.LINK_REMOTE_DETACH)
+    def tearDown(self):
+        self.cleanup()
 
-class PeerTest(CollectorTest):
+    def testEndpointEvents(self):
+        c1, c2 = self.connection()
+        c1.collect(self.collector)
+        self.expect(Event.CONNECTION_INIT)
+        self.pump()
+        self.expect()
+        c2.open()
+        self.pump()
+        self.expect(Event.CONNECTION_REMOTE_OPEN)
+        self.pump()
+        self.expect()
 
-  def setUp(self):
-    CollectorTest.setUp(self)
-    self.connection = Connection()
-    self.connection.collect(self.collector)
-    self.transport = Transport()
-    self.transport.bind(self.connection)
-    self.peer = Connection()
-    self.peer_transport = Transport()
-    self.peer_transport.bind(self.peer)
-    self.peer_transport.trace(Transport.TRACE_OFF)
+        ssn = c2.session()
+        snd = ssn.sender("sender")
+        ssn.open()
+        snd.open()
 
-  def pump(self):
-    pump(self.transport, self.peer_transport)
+        self.expect()
+        self.pump()
+        self.expect(Event.SESSION_INIT, Event.SESSION_REMOTE_OPEN,
+                    Event.LINK_INIT, Event.LINK_REMOTE_OPEN)
+
+        c1.open()
+        ssn2 = c1.session()
+        ssn2.open()
+        rcv = ssn2.receiver("receiver")
+        rcv.open()
+        self.pump()
+        self.expect(Event.CONNECTION_LOCAL_OPEN, Event.TRANSPORT,
+                    Event.SESSION_INIT, Event.SESSION_LOCAL_OPEN,
+                    Event.TRANSPORT, Event.LINK_INIT, Event.LINK_LOCAL_OPEN,
+                    Event.TRANSPORT)
 
-class TeardownLeakTest(PeerTest):
+        rcv.close()
+        self.expect(Event.LINK_LOCAL_CLOSE, Event.TRANSPORT)
+        self.pump()
+        rcv.free()
+        del rcv
+        self.expect(Event.LINK_FINAL)
+        ssn2.free()
+        del ssn2
+        self.pump()
+        c1.free()
+        c1.transport.unbind()
+        self.expect_oneof((Event.SESSION_FINAL, Event.LINK_FINAL, Event.SESSION_FINAL,
+                           Event.CONNECTION_UNBOUND, Event.CONNECTION_FINAL),
+                          (Event.CONNECTION_UNBOUND, Event.SESSION_FINAL, Event.LINK_FINAL,
+                           Event.SESSION_FINAL, Event.CONNECTION_FINAL))
+
+    def testConnectionINIT_FINAL(self):
+        c = Connection()
+        c.collect(self.collector)
+        self.expect(Event.CONNECTION_INIT)
+        c.free()
+        self.expect(Event.CONNECTION_FINAL)
+
+    def testSessionINIT_FINAL(self):
+        c = Connection()
+        c.collect(self.collector)
+        self.expect(Event.CONNECTION_INIT)
+        s = c.session()
+        self.expect(Event.SESSION_INIT)
+        s.free()
+        self.expect(Event.SESSION_FINAL)
+        c.free()
+        self.expect(Event.CONNECTION_FINAL)
+
+    def testLinkINIT_FINAL(self):
+        c = Connection()
+        c.collect(self.collector)
+        self.expect(Event.CONNECTION_INIT)
+        s = c.session()
+        self.expect(Event.SESSION_INIT)
+        r = s.receiver("asdf")
+        self.expect(Event.LINK_INIT)
+        r.free()
+        self.expect(Event.LINK_FINAL)
+        c.free()
+        self.expect(Event.SESSION_FINAL, Event.CONNECTION_FINAL)
+
+    def testFlowEvents(self):
+        snd, rcv = self.link("test-link")
+        snd.session.connection.collect(self.collector)
+        rcv.open()
+        rcv.flow(10)
+        self.pump()
+        self.expect(Event.CONNECTION_INIT, Event.SESSION_INIT,
+                    Event.LINK_INIT, Event.LINK_REMOTE_OPEN, Event.LINK_FLOW)
+        rcv.flow(10)
+        self.pump()
+        self.expect(Event.LINK_FLOW)
+        return snd, rcv
+
+    def testDeliveryEvents(self):
+        snd, rcv = self.link("test-link")
+        rcv.session.connection.collect(self.collector)
+        rcv.open()
+        rcv.flow(10)
+        self.pump()
+        self.expect(Event.CONNECTION_INIT, Event.SESSION_INIT,
+                    Event.LINK_INIT, Event.LINK_LOCAL_OPEN, Event.TRANSPORT)
+        snd.delivery("delivery")
+        snd.send(b"Hello World!")
+        snd.advance()
+        self.pump()
+        self.expect()
+        snd.open()
+        self.pump()
+        self.expect(Event.LINK_REMOTE_OPEN, Event.DELIVERY)
+        rcv.session.connection.transport.unbind()
+        rcv.session.connection.free()
+        self.expect(Event.CONNECTION_UNBOUND, Event.TRANSPORT, Event.LINK_FINAL,
+                    Event.SESSION_FINAL, Event.CONNECTION_FINAL)
+
+    def testDeliveryEventsDisp(self):
+        snd, rcv = self.testFlowEvents()
+        snd.open()
+        dlv = snd.delivery("delivery")
+        snd.send(b"Hello World!")
+        assert snd.advance()
+        self.expect(Event.LINK_LOCAL_OPEN, Event.TRANSPORT)
+        self.pump()
+        self.expect(Event.LINK_FLOW)
+        rdlv = rcv.current
+        assert rdlv != None
+        assert rdlv.tag == "delivery"
+        rdlv.update(Delivery.ACCEPTED)
+        self.pump()
+        event = self.expect(Event.DELIVERY)
+        assert event.context == dlv, (dlv, event.context)
+
+    def testConnectionBOUND_UNBOUND(self):
+        c = Connection()
+        c.collect(self.collector)
+        self.expect(Event.CONNECTION_INIT)
+        t = Transport()
+        t.bind(c)
+        self.expect(Event.CONNECTION_BOUND)
+        t.unbind()
+        self.expect(Event.CONNECTION_UNBOUND, Event.TRANSPORT)
+
+    def testTransportERROR_CLOSE(self):
+        c = Connection()
+        c.collect(self.collector)
+        self.expect(Event.CONNECTION_INIT)
+        t = Transport()
+        t.bind(c)
+        self.expect(Event.CONNECTION_BOUND)
+        assert t.condition is None
+        t.push(b"asdf")
+        self.expect(Event.TRANSPORT_ERROR, Event.TRANSPORT_TAIL_CLOSED)
+        assert t.condition is not None
+        assert t.condition.name == "amqp:connection:framing-error"
+        assert "AMQP protocol header" in t.condition.description
+        p = t.pending()
+        assert p > 0
+        t.pop(p)
+        self.expect(Event.TRANSPORT_HEAD_CLOSED, Event.TRANSPORT_CLOSED)
+
+    def testTransportCLOSED(self):
+        c = Connection()
+        c.collect(self.collector)
+        self.expect(Event.CONNECTION_INIT)
+        t = Transport()
+        t.bind(c)
+        c.open()
+
+        self.expect(Event.CONNECTION_BOUND, Event.CONNECTION_LOCAL_OPEN, Event.TRANSPORT)
+
+        c2 = Connection()
+        t2 = Transport()
+        t2.bind(c2)
+        c2.open()
+        c2.close()
+
+        pump(t, t2)
+
+        self.expect(Event.CONNECTION_REMOTE_OPEN, Event.CONNECTION_REMOTE_CLOSE,
+                    Event.TRANSPORT_TAIL_CLOSED)
+
+        c.close()
+
+        pump(t, t2)
+
+        self.expect(Event.CONNECTION_LOCAL_CLOSE, Event.TRANSPORT,
+                    Event.TRANSPORT_HEAD_CLOSED, Event.TRANSPORT_CLOSED)
+
+    def testLinkDetach(self):
+        c1 = Connection()
+        c1.collect(self.collector)
+        t1 = Transport()
+        t1.bind(c1)
+        c1.open()
+        s1 = c1.session()
+        s1.open()
+        l1 = s1.sender("asdf")
+        l1.open()
+        l1.detach()
+        self.expect_until(Event.LINK_LOCAL_DETACH, Event.TRANSPORT)
+
+        c2 = Connection()
+        c2.collect(self.collector)
+        t2 = Transport()
+        t2.bind(c2)
+
+        pump(t1, t2)
+
+        self.expect_until(Event.LINK_REMOTE_DETACH)
+
+
+class PeerTest(CollectorTest):
+
+    def setUp(self):
+        CollectorTest.setUp(self)
+        self.connection = Connection()
+        self.connection.collect(self.collector)
+        self.transport = Transport()
+        self.transport.bind(self.connection)
+        self.peer = Connection()
+        self.peer_transport = Transport()
+        self.peer_transport.bind(self.peer)
+        self.peer_transport.trace(Transport.TRACE_OFF)
+
+    def pump(self):
+        pump(self.transport, self.peer_transport)
 
-  def doLeak(self, local, remote):
-    self.connection.open()
-    self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND,
-                Event.CONNECTION_LOCAL_OPEN, Event.TRANSPORT)
 
-    ssn = self.connection.session()
-    ssn.open()
-    self.expect(Event.SESSION_INIT, Event.SESSION_LOCAL_OPEN, Event.TRANSPORT)
+class TeardownLeakTest(PeerTest):
 
-    snd = ssn.sender("sender")
-    snd.open()
-    self.expect(Event.LINK_INIT, Event.LINK_LOCAL_OPEN, Event.TRANSPORT)
+    def doLeak(self, local, remote):
+        self.connection.open()
+        self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND,
+                    Event.CONNECTION_LOCAL_OPEN, Event.TRANSPORT)
 
+        ssn = self.connection.session()
+        ssn.open()
+        self.expect(Event.SESSION_INIT, Event.SESSION_LOCAL_OPEN, Event.TRANSPORT)
 
-    self.pump()
+        snd = ssn.sender("sender")
+        snd.open()
+        self.expect(Event.LINK_INIT, Event.LINK_LOCAL_OPEN, Event.TRANSPORT)
 
-    self.peer.open()
-    self.peer.session_head(0).open()
-    self.peer.link_head(0).open()
+        self.pump()
 
-    self.pump()
-    self.expect_oneof((Event.CONNECTION_REMOTE_OPEN, Event.SESSION_REMOTE_OPEN,
-                       Event.LINK_REMOTE_OPEN, Event.LINK_FLOW),
-                      (Event.CONNECTION_REMOTE_OPEN, Event.SESSION_REMOTE_OPEN,
-                       Event.LINK_REMOTE_OPEN))
+        self.peer.open()
+        self.peer.session_head(0).open()
+        self.peer.link_head(0).open()
 
-    if local:
-      snd.close() # ha!!
-      self.expect(Event.LINK_LOCAL_CLOSE, Event.TRANSPORT)
-    ssn.close()
-    self.expect(Event.SESSION_LOCAL_CLOSE, Event.TRANSPORT)
-    self.connection.close()
-    self.expect(Event.CONNECTION_LOCAL_CLOSE, Event.TRANSPORT)
+        self.pump()
+        self.expect_oneof((Event.CONNECTION_REMOTE_OPEN, Event.SESSION_REMOTE_OPEN,
+                           Event.LINK_REMOTE_OPEN, Event.LINK_FLOW),
+                          (Event.CONNECTION_REMOTE_OPEN, Event.SESSION_REMOTE_OPEN,
+                           Event.LINK_REMOTE_OPEN))
+
+        if local:
+            snd.close()  # ha!!
+            self.expect(Event.LINK_LOCAL_CLOSE, Event.TRANSPORT)
+        ssn.close()
+        self.expect(Event.SESSION_LOCAL_CLOSE, Event.TRANSPORT)
+        self.connection.close()
+        self.expect(Event.CONNECTION_LOCAL_CLOSE, Event.TRANSPORT)
+
+        if remote:
+            self.peer.link_head(0).close()  # ha!!
+        self.peer.session_head(0).close()
+        self.peer.close()
 
-    if remote:
-      self.peer.link_head(0).close() # ha!!
-    self.peer.session_head(0).close()
-    self.peer.close()
+        self.pump()
 
-    self.pump()
+        if remote:
+            self.expect(Event.TRANSPORT_HEAD_CLOSED, Event.LINK_REMOTE_CLOSE,
+                        Event.SESSION_REMOTE_CLOSE, Event.CONNECTION_REMOTE_CLOSE,
+                        Event.TRANSPORT_TAIL_CLOSED, Event.TRANSPORT_CLOSED)
+        else:
+            self.expect(Event.TRANSPORT_HEAD_CLOSED, Event.SESSION_REMOTE_CLOSE,
+                        Event.CONNECTION_REMOTE_CLOSE, Event.TRANSPORT_TAIL_CLOSED,
+                        Event.TRANSPORT_CLOSED)
 
-    if remote:
-      self.expect(Event.TRANSPORT_HEAD_CLOSED, Event.LINK_REMOTE_CLOSE,
-                  Event.SESSION_REMOTE_CLOSE, Event.CONNECTION_REMOTE_CLOSE,
-                  Event.TRANSPORT_TAIL_CLOSED, Event.TRANSPORT_CLOSED)
-    else:
-      self.expect(Event.TRANSPORT_HEAD_CLOSED, Event.SESSION_REMOTE_CLOSE,
-                  Event.CONNECTION_REMOTE_CLOSE, Event.TRANSPORT_TAIL_CLOSED,
-                  Event.TRANSPORT_CLOSED)
+        self.connection.free()
+        self.expect(Event.LINK_FINAL, Event.SESSION_FINAL)
+        self.transport.unbind()
 
-    self.connection.free()
-    self.expect(Event.LINK_FINAL, Event.SESSION_FINAL)
-    self.transport.unbind()
+        self.expect(Event.CONNECTION_UNBOUND, Event.CONNECTION_FINAL)
 
-    self.expect(Event.CONNECTION_UNBOUND, Event.CONNECTION_FINAL)
+    def testLocalRemoteLeak(self):
+        self.doLeak(True, True)
 
-  def testLocalRemoteLeak(self):
-    self.doLeak(True, True)
+    def testLocalLeak(self):
+        self.doLeak(True, False)
 
-  def testLocalLeak(self):
-    self.doLeak(True, False)
+    def testRemoteLeak(self):
+        self.doLeak(False, True)
 
-  def testRemoteLeak(self):
-    self.doLeak(False, True)
+    def testLeak(self):
+        self.doLeak(False, False)
 
-  def testLeak(self):
-    self.doLeak(False, False)
 
 class IdleTimeoutEventTest(PeerTest):
 
-  def half_pump(self):
-    p = self.transport.pending()
-    if p>0:
-      self.transport.pop(p)
-
-  def testTimeoutWithZombieServer(self, expectOpenCloseFrames=True):
-    self.transport.idle_timeout = self.delay
-    self.connection.open()
-    self.half_pump()
-    t = time()
-    self.transport.tick(t)
-    self.transport.tick(t + self.delay*4)
-    self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND,
-                Event.CONNECTION_LOCAL_OPEN, Event.TRANSPORT,
-                Event.TRANSPORT_ERROR, Event.TRANSPORT_TAIL_CLOSED)
-    assert self.transport.capacity() < 0
-    if expectOpenCloseFrames:
-      assert self.transport.pending() > 0
-    self.half_pump()
-    self.expect(Event.TRANSPORT_HEAD_CLOSED, Event.TRANSPORT_CLOSED)
-    assert self.transport.pending() < 0
-
-  def testTimeoutWithZombieServerAndSASL(self):
-    sasl = self.transport.sasl()
-    self.testTimeoutWithZombieServer(expectOpenCloseFrames=False)
+    def half_pump(self):
+        p = self.transport.pending()
+        if p > 0:
+            self.transport.pop(p)
+
+    def testTimeoutWithZombieServer(self, expectOpenCloseFrames=True):
+        self.transport.idle_timeout = self.delay
+        self.connection.open()
+        self.half_pump()
+        t = time()
+        self.transport.tick(t)
+        self.transport.tick(t + self.delay*4)
+        self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND,
+                    Event.CONNECTION_LOCAL_OPEN, Event.TRANSPORT,
+                    Event.TRANSPORT_ERROR, Event.TRANSPORT_TAIL_CLOSED)
+        assert self.transport.capacity() < 0
+        if expectOpenCloseFrames:
+            assert self.transport.pending() > 0
+        self.half_pump()
+        self.expect(Event.TRANSPORT_HEAD_CLOSED, Event.TRANSPORT_CLOSED)
+        assert self.transport.pending() < 0
+
+    def testTimeoutWithZombieServerAndSASL(self):
+        sasl = self.transport.sasl()
+        self.testTimeoutWithZombieServer(expectOpenCloseFrames=False)
+
 
 class DeliverySegFaultTest(Test):
 
-  def testDeliveryAfterUnbind(self):
-    conn = Connection()
-    t = Transport()
-    ssn = conn.session()
-    snd = ssn.sender("sender")
-    dlv = snd.delivery("tag")
-    dlv.settle()
-    del dlv
-    t.bind(conn)
-    t.unbind()
-    dlv = snd.delivery("tag")
+    def testDeliveryAfterUnbind(self):
+        conn = Connection()
+        t = Transport()
+        ssn = conn.session()
+        snd = ssn.sender("sender")
+        dlv = snd.delivery("tag")
+        dlv.settle()
+        del dlv
+        t.bind(conn)
+        t.unbind()
+        dlv = snd.delivery("tag")
+
 
 class SaslEventTest(CollectorTest):
 
-  def testAnonymousNoInitialResponse(self):
-    conn = Connection()
-    conn.collect(self.collector)
-    transport = Transport(Transport.SERVER)
-    transport.bind(conn)
-    self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND)
-
-    transport.push(b'AMQP\x03\x01\x00\x00\x00\x00\x00 \x02\x01\x00\x00\x00SA'
-                   b'\xd0\x00\x00\x00\x10\x00\x00\x00\x02\xa3\tANONYMOUS@'
-                   b'AMQP\x00\x01\x00\x00')
-    self.expect(Event.TRANSPORT)
-    for i in range(1024):
-      p = transport.pending()
-      self.drain()
-    p = transport.pending()
-    self.expect()
-
-  def testPipelinedServerReadFirst(self):
-    conn = Connection()
-    conn.collect(self.collector)
-    transport = Transport(Transport.CLIENT)
-    s = transport.sasl()
-    s.allowed_mechs("ANONYMOUS PLAIN")
-    transport.bind(conn)
-    self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND)
-    transport.push(
-        # SASL
-        b'AMQP\x03\x01\x00\x00'
-        # @sasl-mechanisms(64) [sasl-server-mechanisms=@PN_SYMBOL[:ANONYMOUS]]
-        b'\x00\x00\x00\x1c\x02\x01\x00\x00\x00S@\xc0\x0f\x01\xe0\x0c\x01\xa3\tANONYMOUS'
-        # @sasl-outcome(68) [code=0]
-        b'\x00\x00\x00\x10\x02\x01\x00\x00\x00SD\xc0\x03\x01P\x00'
-        # AMQP
-        b'AMQP\x00\x01\x00\x00'
+    def testAnonymousNoInitialResponse(self):
+        conn = Connection()
+        conn.collect(self.collector)
+        transport = Transport(Transport.SERVER)
+        transport.bind(conn)
+        self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND)
+
+        transport.push(b'AMQP\x03\x01\x00\x00\x00\x00\x00 \x02\x01\x00\x00\x00SA'
+                       b'\xd0\x00\x00\x00\x10\x00\x00\x00\x02\xa3\tANONYMOUS@'
+                       b'AMQP\x00\x01\x00\x00')
+        self.expect(Event.TRANSPORT)
+        for i in range(1024):
+            p = transport.pending()
+            self.drain()
+        p = transport.pending()
+        self.expect()
+
+    def testPipelinedServerReadFirst(self):
+        conn = Connection()
+        conn.collect(self.collector)
+        transport = Transport(Transport.CLIENT)
+        s = transport.sasl()
+        s.allowed_mechs("ANONYMOUS PLAIN")
+        transport.bind(conn)
+        self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND)
+        transport.push(
+            # SASL
+            b'AMQP\x03\x01\x00\x00'
+            # @sasl-mechanisms(64) [sasl-server-mechanisms=@PN_SYMBOL[:ANONYMOUS]]
+            b'\x00\x00\x00\x1c\x02\x01\x00\x00\x00S@\xc0\x0f\x01\xe0\x0c\x01\xa3\tANONYMOUS'
+            # @sasl-outcome(68) [code=0]
+            b'\x00\x00\x00\x10\x02\x01\x00\x00\x00SD\xc0\x03\x01P\x00'
+            # AMQP
+            b'AMQP\x00\x01\x00\x00'
         )
-    self.expect(Event.TRANSPORT)
-    p = transport.pending()
-    bytes = transport.peek(p)
-    transport.pop(p)
-
-    server = Transport(Transport.SERVER)
-    server.push(bytes)
-    assert s.outcome == SASL.OK
-    assert server.sasl().outcome == SASL.OK
-
-  def testPipelinedServerWriteFirst(self):
-    conn = Connection()
-    conn.collect(self.collector)
-    transport = Transport(Transport.CLIENT)
-    s = transport.sasl()
-    s.allowed_mechs("ANONYMOUS")
-    transport.bind(conn)
-    p = transport.pending()
-    bytes = transport.peek(p)
-    transport.pop(p)
-    self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND)
-    transport.push(
-        # SASL
-        b'AMQP\x03\x01\x00\x00'
-        # @sasl-mechanisms(64) [sasl-server-mechanisms=@PN_SYMBOL[:ANONYMOUS]]
-        b'\x00\x00\x00\x1c\x02\x01\x00\x00\x00S@\xc0\x0f\x01\xe0\x0c\x01\xa3\tANONYMOUS'
-        # @sasl-outcome(68) [code=0]
-        b'\x00\x00\x00\x10\x02\x01\x00\x00\x00SD\xc0\x03\x01P\x00'
-        # AMQP
-        b'AMQP\x00\x01\x00\x00'
+        self.expect(Event.TRANSPORT)
+        p = transport.pending()
+        bytes = transport.peek(p)
+        transport.pop(p)
+
+        server = Transport(Transport.SERVER)
+        server.push(bytes)
+        assert s.outcome == SASL.OK
+        assert server.sasl().outcome == SASL.OK
+
+    def testPipelinedServerWriteFirst(self):
+        conn = Connection()
+        conn.collect(self.collector)
+        transport = Transport(Transport.CLIENT)
+        s = transport.sasl()
+        s.allowed_mechs("ANONYMOUS")
+        transport.bind(conn)
+        p = transport.pending()
+        bytes = transport.peek(p)
+        transport.pop(p)
+        self.expect(Event.CONNECTION_INIT, Event.CONNECTION_BOUND)
+        transport.push(
+            # SASL
+            b'AMQP\x03\x01\x00\x00'
+            # @sasl-mechanisms(64) [sasl-server-mechanisms=@PN_SYMBOL[:ANONYMOUS]]
+            b'\x00\x00\x00\x1c\x02\x01\x00\x00\x00S@\xc0\x0f\x01\xe0\x0c\x01\xa3\tANONYMOUS'
+            # @sasl-outcome(68) [code=0]
+            b'\x00\x00\x00\x10\x02\x01\x00\x00\x00SD\xc0\x03\x01P\x00'
+            # AMQP
+            b'AMQP\x00\x01\x00\x00'
         )
-    self.expect(Event.TRANSPORT)
-    p = transport.pending()
-    bytes = transport.peek(p)
-    transport.pop(p)
-    assert s.outcome == SASL.OK
-    # XXX: the bytes above appear to be correct, but we don't get any
-    # sort of event indicating that the transport is authenticated
+        self.expect(Event.TRANSPORT)
+        p = transport.pending()
+        bytes = transport.peek(p)
+        transport.pop(p)
+        assert s.outcome == SASL.OK
+        # XXX: the bytes above appear to be correct, but we don't get any
+        # sort of event indicating that the transport is authenticated
diff --git a/python/tests/proton_tests/handler.py b/python/tests/proton_tests/handler.py
index 2324073..e8fdebd 100644
--- a/python/tests/proton_tests/handler.py
+++ b/python/tests/proton_tests/handler.py
@@ -19,7 +19,9 @@
 
 from __future__ import absolute_import
 
-import os, gc, traceback
+import os
+import gc
+import traceback
 
 from proton import *
 from proton.reactor import Container
@@ -28,95 +30,105 @@ from . import common
 
 CUSTOM = EventType("custom")
 
+
 class HandlerTest(common.Test):
-  def test_reactorHandlerCycling(self, n=0):
-
-    class CustomHandler(Handler):
-      UNSET = 999999999
-      def __init__(self):
-        self.offset = len(traceback.extract_stack())
-      def on_reactor_init(self, event):
-        self.depth = len(traceback.extract_stack())
-      def reset(self):
-        self.depth = self.UNSET
-      @property
-      def init_depth(self):
-        d = self.depth - self.offset
-        return d
-    custom = CustomHandler()
-
-    container = Container()
-    container.handler = custom
-    for i in range(n):
-      h = container.handler
-      container.handler = h
-    custom.reset()
-    container.run()
-    assert custom.init_depth < 50, "Unexpectedly long traceback for a simple handler"
-
-  def test_reactorHandlerCycling10k(self):
-    self.test_reactorHandlerCycling(10000)
-
-  def test_reactorHandlerCycling100(self):
-    self.test_reactorHandlerCycling(100)
-
-  def do_customEvent(self, reactor_handler, event_root):
-
-    class CustomHandler:
-      did_custom = False
-      did_init = False
-      def __init__(self, *handlers):
-        self.handlers = handlers
-      def on_reactor_init(self, event):
-        self.did_init = True
-      def on_custom(self, event):
-        self.did_custom = True
-
-    class CustomInvoker(CustomHandler):
-      def on_reactor_init(self, event):
-        h = event_root(event)
-        event.dispatch(h, CUSTOM)
-        self.did_init = True
-
-    child = CustomInvoker()
-    root = CustomHandler(child)
-
-    container = Container()
-
-    reactor_handler(container, root)
-    container.run()
-    assert root.did_init
-    assert child.did_init
-    assert root.did_custom
-    assert child.did_custom
-
-  def set_root(self, reactor, root):
-    reactor.handler = root
-  def add_root(self, reactor, root):
-    reactor.handler.add(root)
-  def append_root(self, reactor, root):
-    reactor.handler.handlers.append(root)
-
-  def event_root(self, event):
-    return event.handler
-
-  def event_reactor_handler(self, event):
-    return event.reactor.handler
-
-  def test_set_handler(self):
-    self.do_customEvent(self.set_root, self.event_reactor_handler)
-
-  def test_add_handler(self):
-    self.do_customEvent(self.add_root, self.event_reactor_handler)
-
-  def test_append_handler(self):
-    self.do_customEvent(self.append_root, self.event_reactor_handler)
-
-  def test_set_root(self):
-    self.do_customEvent(self.set_root, self.event_root)
-
-  def test_add_root(self):
-    self.do_customEvent(self.add_root, self.event_root)
-
-  def test_append_root(self):
-    self.do_customEvent(self.append_root, self.event_root)
+    def test_reactorHandlerCycling(self, n=0):
+
+        class CustomHandler(Handler):
+            UNSET = 999999999
+
+            def __init__(self):
+                self.offset = len(traceback.extract_stack())
+
+            def on_reactor_init(self, event):
+                self.depth = len(traceback.extract_stack())
+
+            def reset(self):
+                self.depth = self.UNSET
+
+            @property
+            def init_depth(self):
+                d = self.depth - self.offset
+                return d
+        custom = CustomHandler()
+
+        container = Container()
+        container.handler = custom
+        for i in range(n):
+            h = container.handler
+            container.handler = h
+        custom.reset()
+        container.run()
+        assert custom.init_depth < 50, "Unexpectedly long traceback for a simple handler"
+
+    def test_reactorHandlerCycling10k(self):
+        self.test_reactorHandlerCycling(10000)
+
+    def test_reactorHandlerCycling100(self):
+        self.test_reactorHandlerCycling(100)
+
+    def do_customEvent(self, reactor_handler, event_root):
+
+        class CustomHandler:
+            did_custom = False
+            did_init = False
+
+            def __init__(self, *handlers):
+                self.handlers = handlers
+
+            def on_reactor_init(self, event):
+                self.did_init = True
+
+            def on_custom(self, event):
+                self.did_custom = True
+
+        class CustomInvoker(CustomHandler):
+            def on_reactor_init(self, event):
+                h = event_root(event)
+                event.dispatch(h, CUSTOM)
+                self.did_init = True
+
+        child = CustomInvoker()
+        root = CustomHandler(child)
+
+        container = Container()
+
+        reactor_handler(container, root)
+        container.run()
+        assert root.did_init
+        assert child.did_init
+        assert root.did_custom
+        assert child.did_custom
+
+    def set_root(self, reactor, root):
+        reactor.handler = root
+
+    def add_root(self, reactor, root):
+        reactor.handler.add(root)
+
+    def append_root(self, reactor, root):
+        reactor.handler.handlers.append(root)
+
+    def event_root(self, event):
+        return event.handler
+
+    def event_reactor_handler(self, event):
+        return event.reactor.handler
+
+    def test_set_handler(self):
+        self.do_customEvent(self.set_root, self.event_reactor_handler)
+
+    def test_add_handler(self):
+        self.do_customEvent(self.add_root, self.event_reactor_handler)
+
+    def test_append_handler(self):
+        self.do_customEvent(self.append_root, self.event_reactor_handler)
+
+    def test_set_root(self):
+        self.do_customEvent(self.set_root, self.event_root)
+
+    def test_add_root(self):
+        self.do_customEvent(self.add_root, self.event_root)
+
+    def test_append_root(self):
+        self.do_customEvent(self.append_root, self.event_root)
diff --git a/python/tests/proton_tests/interop.py b/python/tests/proton_tests/interop.py
index 5ccbd2b..f57327b 100644
--- a/python/tests/proton_tests/interop.py
+++ b/python/tests/proton_tests/interop.py
@@ -35,7 +35,9 @@ def find_test_interop_dir():
         raise Exception("Cannot find tests/interop directory from "+__file__)
     return f
 
-test_interop_dir=find_test_interop_dir()
+
+test_interop_dir = find_test_interop_dir()
+
 
 class InteropTest(common.Test):
 
@@ -48,9 +50,11 @@ class InteropTest(common.Test):
 
     def get_data(self, name):
         filename = os.path.join(test_interop_dir, name+".amqp")
-        f = open(filename,"rb")
-        try: return f.read()
-        finally: f.close()
+        f = open(filename, "rb")
+        try:
+            return f.read()
+        finally:
+            f.close()
 
     def decode_data(self, encoded):
         buffer = encoded
@@ -78,10 +82,10 @@ class InteropTest(common.Test):
 
     def assert_next(self, type, value):
         next_type = self.data.next()
-        assert next_type == type, "Type mismatch: %s != %s"%(
+        assert next_type == type, "Type mismatch: %s != %s" % (
             Data.type_names[next_type], Data.type_names[type])
         next_value = self.data.get_object()
-        assert next_value == value, "Value mismatch: %s != %s"%(next_value, value)
+        assert next_value == value, "Value mismatch: %s != %s" % (next_value, value)
 
     def test_message(self):
         self.decode_message_file("message")
@@ -128,11 +132,11 @@ class InteropTest(common.Test):
 
     def test_described_array(self):
         self.decode_data_file("described_array")
-        self.assert_next(Data.ARRAY, Array("int-array", Data.INT, *range(0,10)))
+        self.assert_next(Data.ARRAY, Array("int-array", Data.INT, *range(0, 10)))
 
     def test_arrays(self):
         self.decode_data_file("arrays")
-        self.assert_next(Data.ARRAY, Array(UNDESCRIBED, Data.INT, *range(0,100)))
+        self.assert_next(Data.ARRAY, Array(UNDESCRIBED, Data.INT, *range(0, 100)))
         self.assert_next(Data.ARRAY, Array(UNDESCRIBED, Data.STRING, *["a", "b", "c"]))
         self.assert_next(Data.ARRAY, Array(UNDESCRIBED, Data.INT))
         assert self.data.next() is None
@@ -145,7 +149,7 @@ class InteropTest(common.Test):
 
     def test_maps(self):
         self.decode_data_file("maps")
-        self.assert_next(Data.MAP, {"one":1, "two":2, "three":3 })
-        self.assert_next(Data.MAP, {1:"one", 2:"two", 3:"three"})
+        self.assert_next(Data.MAP, {"one": 1, "two": 2, "three": 3})
+        self.assert_next(Data.MAP, {1: "one", 2: "two", 3: "three"})
         self.assert_next(Data.MAP, {})
         assert self.data.next() is None
diff --git a/python/tests/proton_tests/main.py b/python/tests/proton_tests/main.py
index e560cf1..c30f282 100644
--- a/python/tests/proton_tests/main.py
+++ b/python/tests/proton_tests/main.py
@@ -19,7 +19,14 @@
 
 # TODO: summarize, test harness preconditions (e.g. broker is alive)
 
-import optparse, os, struct, sys, time, traceback, types, cgi
+import optparse
+import os
+import struct
+import sys
+import time
+import traceback
+import types
+import cgi
 from fnmatch import fnmatchcase as match
 from logging import getLogger, StreamHandler, Formatter, Filter, \
     WARN, DEBUG, ERROR, INFO
@@ -32,11 +39,11 @@ else:
     CLASS_TYPES = (type, types.ClassType)
 
 levels = {
-  "DEBUG": DEBUG,
-  "INFO": INFO,
-  "WARN": WARN,
-  "ERROR": ERROR
-  }
+    "DEBUG": DEBUG,
+    "INFO": INFO,
+    "WARN": WARN,
+    "ERROR": ERROR
+}
 
 sorted_levels = [(v, k) for k, v in list(levels.items())]
 sorted_levels.sort()
@@ -80,13 +87,15 @@ parser.add_option("-j", "--javatrace", action="store_true", default=False,
                   help="Show the full java stack trace. This disables heuristics to eliminate the " +
                   "jython portion of java stack traces.")
 
+
 class Config:
 
-  def __init__(self):
-    self.defines = {}
-    self.log_file = None
-    self.log_level = WARN
-    self.log_categories = []
+    def __init__(self):
+        self.defines = {}
+        self.log_file = None
+        self.log_level = WARN
+        self.log_categories = []
+
 
 opts, args = parser.parse_args()
 
@@ -98,79 +107,86 @@ excludes = ["*__*__"]
 config = Config()
 list_only = opts.list
 for d in opts.defines:
-  try:
-    idx = d.index("=")
-    name = d[:idx]
-    value = d[idx+1:]
-    config.defines[name] = value
-  except ValueError:
-    config.defines[d] = None
+    try:
+        idx = d.index("=")
+        name = d[:idx]
+        value = d[idx+1:]
+        config.defines[name] = value
+    except ValueError:
+        config.defines[d] = None
 config.log_file = opts.log_file
 config.log_level = levels[opts.log_level.upper()]
 config.log_categories = opts.log_categories
 excludes.extend([v.strip() for v in opts.ignore])
 for v in opts.ignore_file:
-  f = open(v)
-  for line in f:
-    line = line.strip()
-    if line.startswith("#"):
-      continue
-    excludes.append(line)
-  f.close()
+    f = open(v)
+    for line in f:
+        line = line.strip()
+        if line.startswith("#"):
+            continue
+        excludes.append(line)
+    f.close()
 
 for a in args:
-  includes.append(a.strip())
+    includes.append(a.strip())
+
 
 def is_ignored(path):
-  for p in excludes:
-    if match(path, p):
-      return True
-  return False
+    for p in excludes:
+        if match(path, p):
+            return True
+    return False
+
 
 def is_included(path):
-  if is_ignored(path):
... 5953 lines suppressed ...


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]