[prev in list] [next in list] [prev in thread] [next in thread] 

List:       pyamf-commits
Subject:    [pyamf-commits] r75 - in branches/amf3-5/pyamf: . tests
From:       pyamf-commits () collab ! com (pyamf-commits () collab ! com)
Date:       2007-10-26 11:59:16
Message-ID: 20071026095907.E101D7BC069 () mail ! collab ! com
[Download RAW message or body]

Author: nick
Date: 2007-10-26 11:59:07 +0200 (Fri, 26 Oct 2007)
New Revision: 75

Modified:
   branches/amf3-5/pyamf/__init__.py
   branches/amf3-5/pyamf/amf0.py
   branches/amf3-5/pyamf/amf3.py
   branches/amf3-5/pyamf/tests/amf3.py
   branches/amf3-5/pyamf/util.py
Log:
Added a context arg to Parsers/Encoders Added ByteArray support & testsStarted the \
beginnings of class mapping

Modified: branches/amf3-5/pyamf/__init__.py
===================================================================
--- branches/amf3-5/pyamf/__init__.py	2007-10-25 11:53:11 UTC (rev 74)
+++ branches/amf3-5/pyamf/__init__.py	2007-10-26 09:59:07 UTC (rev 75)
@@ -84,6 +84,87 @@
     """
     pass
 
+class Context(object):
+    """
+    """
+    objects = []
+    strings = []
+    classes = []
+    class_cache = {}
+    class_defs = {}
+    
+    def clear(self):
+        self.objects = []
+        self.strings = []
+        self.classes = []
+        self.class_cache = {}
+        self.class_defs = {}
+
+    def getObject(self, ref):
+        """
+        Gets an object based on a reference ref
+        
+        Raises L{pyamf.ReferenceError} if the object could not be found
+        """
+        try:
+            return self.objects[ref]
+        except IndexError:
+            raise ReferenceError("Object reference %d not found" % ref)
+
+    def getObjectReference(self, obj):
+        try:
+            return self.objects.index(obj)
+        except ValueError:
+            raise ReferenceError("Reference for object %r not found" % obj)
+
+    def addObject(self, obj):
+        """
+        Gets a reference to obj, creating one if necessary
+        """
+        try:
+            return self.objects.index(obj)
+        except ValueError:
+            self.objects.append(obj)
+
+            return len(self.objects)
+
+    def getString(self, ref):
+        """
+        Gets a string based on a reference ref
+        
+        Raises L{pyamf.ReferenceError} if the string could not be found
+        """
+        try:
+            return self.strings[ref]
+        except IndexError:
+            raise ReferenceError("String reference %d not found" % ref)
+
+    def getStringReference(self, s):
+        try:
+            return self.strings.index(s)
+        except ValueError:
+            raise ReferenceError("Reference for string %r not found" % s)
+
+    def addString(self, s):
+        """
+        Creates a reference to s
+        """
+        try:
+            return self.strings.index(s)
+        except ValueError:
+            self.strings.append(s)
+
+            return len(self.strings)
+
+    def getClass(self, name):
+        """
+        Gets a class based on the name supplied
+        """
+        try:
+            return self.class_cache[name]
+        except KeyError:
+            pass
+
 class AMFMessageDecoder:
     
     def __init__(self, data):

Modified: branches/amf3-5/pyamf/amf0.py
===================================================================
--- branches/amf3-5/pyamf/amf0.py	2007-10-25 11:53:11 UTC (rev 74)
+++ branches/amf3-5/pyamf/amf0.py	2007-10-26 09:59:07 UTC (rev 75)
@@ -71,7 +71,6 @@
     """
     Parses an AMF0 stream
     """
-    obj_refs = []
     # XXX nick: Do we need to support ASTypes.MOVIECLIP here?
     type_map = {
         ASTypes.NUMBER: 'readNumber',
@@ -93,13 +92,18 @@
         ASTypes.AMF3: 'readAMF3'
     }
 
-    def __init__(self, data=None):
+    def __init__(self, data=None, context=None):
         # coersce data to BufferedByteStream
         if isinstance(data, util.BufferedByteStream):
             self.input = data
         else:
             self.input = util.BufferedByteStream(data)
 
+        if context == None:
+            self.context = pyamf.Context()
+        else:
+            self.context = context
+
     def readType(self):
         """
         Read and returns the next byte in the stream and determine its type.
@@ -147,11 +151,9 @@
 
     def readList(self):
         len = self.input.read_ulong()
-        obj = []
-        self.obj_refs.append(obj)
+        obj = [self.readElement() for i in xrange(len)]
 
-        obj.extend(self.readElement() for i in xrange(len))
-
+        self.context.addObject(obj)
         return obj
 
     def readTypedObject(self):
@@ -165,12 +167,14 @@
         from pyamf import amf3
 
         # XXX: Does the amf3 parser have access to the same references as amf0?
-        p = amf3.Parser(self.input)
+        p = amf3.Parser(self.input, self.context)
 
         return p.readElement()
 
     def readElement(self):
-        """Reads the data type."""
+        """
+        Reads an element from the data stream
+        """
         type = self.readType()
 
         try:
@@ -182,9 +186,12 @@
         return func()
 
     def readString(self):
+        """
+        Reads a string from the data stream
+        """
         len = self.input.read_ushort()
         return self.input.read_utf8_string(len)
-        
+
     def _readObject(self, obj):
         key = self.readString()
         while self.input.peek() != chr(ASTypes.OBJECTTERM):
@@ -202,17 +209,20 @@
         @rettype __builtin__.object
         """
         obj = {}
-        self.obj_refs.append(obj)
         self._readObject(obj)
 
+        self.context.addObject(obj)
+
         return obj
 
     def readReference(self):
         idx = self.input.read_ushort()
-        return self.obj_refs[idx]
+        return self.context.getObject(idx)
 
     def readDate(self):
-        """Reads a date.
+        """
+        Reads a date from the data stream
+        
         Date: 0x0B T7 T6 .. T0 Z1 Z2 T7 to T0 form a 64 bit Big Endian number
         that specifies the number of nanoseconds that have passed since
         1/1/1970 0:00 to the specified time. This format is UTC 1970. Z1 an
@@ -247,12 +257,16 @@
         ((types.InstanceType,types.ObjectType,), "writeObject"),
     ]
 
-    def __init__(self, output):
+    def __init__(self, output, context=None):
         """Constructs a new Encoder. output should be a writable
         file-like object."""
         self.output = output
-        self.obj_refs = []
 
+        if context == None:
+            self.context = pyamf.Context()
+        else:
+            self.context = context
+
     def writeType(self, type):
         """
         Writes the type to the stream. Raises ValueError if type is not
@@ -311,7 +325,7 @@
         self.output.write(s)
 
     def writeReference(self, o):
-        idx = self.obj_refs.index(o)
+        idx = self.context.getObjectReference(o)
 
         self.writeType(ASTypes.REFERENCE)
         self.output.write_ushort(idx)
@@ -349,10 +363,10 @@
         try:
             self.writeReference(o)
             return
-        except ValueError, e:
+        except pyamf.ReferenceError:
             pass
 
-        self.obj_refs.append(o)
+        self.context.addObject(o)
         self.writeType(ASTypes.OBJECT)
 
         # TODO: give objects a chance of controlling what we send

Modified: branches/amf3-5/pyamf/amf3.py
===================================================================
--- branches/amf3-5/pyamf/amf3.py	2007-10-25 11:53:11 UTC (rev 74)
+++ branches/amf3-5/pyamf/amf3.py	2007-10-26 09:59:07 UTC (rev 75)
@@ -27,7 +27,7 @@
 #
 # Resources:
 #   http://www.vanrijkom.org/archives/2005/06/amf_format.html
-#   http://osflash.org/documentation/amf/astypes
+#   http://osflash.org/documentation/amf3
 
 """AMF3 Implementation"""
 
@@ -60,7 +60,7 @@
 
 REFERENCE_BIT = 0x01
 
-class AMF3ObjectTypes:
+class ObjectEncoding:
     # Property list encoding.
     # The remaining integer-data represents the number of
     # class members that exist. The property names are read
@@ -85,32 +85,55 @@
     # Proxy object
     PROXY = 0x03
 
-    # Flex class mappings.
-    flex_mappings = [
-        # (RemotingMessage, "flex.messaging.messages.RemotingMessage"),
-        # (CommandMessage, "flex.messaging.messages.CommandMessage"),
-        # (AcknowledgeMessage, "flex.messaging.messages.AcknowledgeMessage"),
-        # (ErrorMessage, "flex.messaging.messages.ErrorMessage"),
-        # (ArrayCollection, "flex.messaging.io.ArrayCollection"),
-        # (ObjectProxy, "flex.messaging.io.ObjectProxy"),
-    ]
+class Bag(dict):
+    """
+    I supply a thin layer over the __builtin__.dict type to support
+    get/setattr calls
+    """
 
-class Bag(dict):
     def __init__(self, d={}):
         for k, v in d.items():
             self[k] = v
 
-    __setattr__ = dict.__setitem__
+    def __setattr__(self, name, value):
+        self[name] = value
 
+    def __getattr__(self, name):
+        return self[name]
+
+class ByteArray(str):
+    """
+    I am a file type object containing byte data from the AMF stream
+    """
+
+class ClassDefinition(object):
+    """
+    I contain meta relating to the class definition
+    """
+    attrs = []
+
+    def __init__(self, name, encoding):
+        self.name = name
+        self.encoding = encoding
+
+    def is_external(self):
+        return self.encoding == ObjectEncoding.EXTERNALIZABLE
+
+    def is_static(self):
+        return self.encoding == ObjectEncoding.STATIC
+
+    def is_dynamic(self):
+        return self.encoding == ObjectEncoding.DYNAMIC
+
+    external = property(is_external)
+    static = property(is_static)
+    dynamic = property(is_dynamic)
+
 class Parser(object):
     """
     Parses an AMF3 data stream
     """
 
-    obj_refs = []
-    str_refs = []
-    class_refs = []
-
     type_map = {
         ASTypes.UNDEFINED: 'readNull',
         ASTypes.NULL: 'readNull',
@@ -127,12 +150,17 @@
         ASTypes.BYTEARRAY: 'readByteArray',
     }
 
-    def __init__(self, data=None):
+    def __init__(self, data=None, context=None):
         if isinstance(data, util.BufferedByteStream):
             self.input = data
         else:
             self.input = util.BufferedByteStream(data)
 
+        if context == None:
+            context = pyamf.Context()
+
+        self.context = context
+
     def readType(self):
         """
         Read and returns the next byte in the stream and determine its type.
@@ -210,23 +238,21 @@
         length, is_reference = readLength()
 
         if use_references and is_reference:
-            try:
-                return self.str_refs[length]
-            except IndexError:
-                raise pyamf.ReferenceError("Unknown string reference %d" % length)
+            return self.context.getString(length)
 
         buf = self.input.read(length)
 
         try:
             # Try decoding as regular utf8 first since that will
             # cover most cases and is more efficient.
-            # XXX: I'm not sure if it's ok though.. will it always raise exception?
+            # XXX: I'm not sure if it's ok though..
+            # will it always raise exception?
             result = unicode(buf, "utf8")
         except UnicodeDecodeError:
             result = decode_utf8_modified(buf)
 
         if len(result) != 0 and use_references:
-            self.str_refs.append(result)
+            self.context.addString(result)
 
         return result
 
@@ -237,15 +263,13 @@
         ref = self.readInteger()
         
         if ref & REFERENCE_BIT == 0:
-            try:
-                return self.obj_refs[ref >> 1]
-            except IndexError:
-                raise pyamf.ReferenceError("Unknown date reference %d" % ref)
+            return self.context.getObject(ref >> 1)
 
         ms = self.input.read_double()
         result = datetime.datetime.fromtimestamp(ms / 100)
-        self.obj_refs.append(result)
 
+        self.context.addObject(result)
+
         return result
 
     def readArray(self):
@@ -264,7 +288,7 @@
         size = self.readInteger()
 
         if size & REFERENCE_BIT == 0:
-            return self.obj_refs[size >> 1]
+            return self.context.getObject(size >> 1)
 
         size >>= 1
 
@@ -292,7 +316,7 @@
                 el = self.readElement()
                 result[i] = el
 
-        self.obj_refs.append(result)
+        self.context.addObject(result)
 
         return result
 
@@ -303,67 +327,66 @@
         type = self.readInteger()
 
         if type & REFERENCE_BIT == 0:
-            return self.obj_refs[type >> 1]
+            return self.context.getObject(type >> 1)
 
-        class_ref = (type >> 1) & REFERENCE_BIT == 0
-
+        class_ref = type >> 1 & REFERENCE_BIT == 0
         type >>= 2
 
         if class_ref:
-            klass = self.class_refs[type]
+            class_def = self.class_refs[type]
         else:
-            klass = AMF3Class()
-            klass.name = self.readString()
-            klass.encoding = type & AMF3ObjectTypes.PROXY
-            klass.attrs = []
+            class_def = ClassDefinition(self.readString(), type & 0x03)
+            self.class_refs.append(class_def)
 
-        type >>= 1
+        type >>= 2
 
-        if klass.name:
-            # TODO : do some class mapping?
-            obj = AMF3Object(klass)
-        else:
-            obj = Bag()
+        klass = lookup_class(class_def, self)
+        obj = klass()
 
-        if not class_ref:
-            self.class_refs.append(klass)
-
-        if klass.encoding & AMF3ObjectTypes.EXTERNALIZABLE:
+        if class_def.external:
             # TODO: implement externalizeable interface here
             obj.__amf_externalized_data = self.readElement()
 
-        elif klass.encoding & AMF3ObjectTypes.DYNAMIC:
-            for i in range(type):
-                k = self.readString()
-                v = self.readElement()
-                print k, v
-                setattr(obj, k, v)
+        elif class_def.dynamic:
+            attr = self.readString()
 
-        elif klass.encoding & AMF3ObjectTypes.STATIC:
+            while attr != "":
+                if attr not in class_def.attrs:
+                    class_def.attrs.append(attr)
+
+                obj[attr] = self.readElement()
+                attr = self.readString()
+
+        elif class_def.static:
             if not class_ref:
-                klass.attrs = [self.readString() for i in range(type)]
+                class_def.attrs = [self.readString() for i in range(type)]
 
-            for attr in klass.attrs:
-                setattr(obj, attr, self.readElement())
+            for attr in class_def.attrs:
+                obj[attr] = self.readElement()
+        else:
+            raise pyamf.ParseError("Unknown object encoding")
 
-        self.obj_refs.append(obj)
+        self.context.addObject(obj)
 
         return obj
 
     def readByteArray(self):
+        """
+        Reads a string of data from the stream.
+        """
         length = self.readInteger()
-        return self.input.read(length >> 1)
 
+        return ByteArray(self.input.read(length >> 1))
+
 class Encoder(object):
 
-    obj_refs = []
-    str_refs = []
     type_map = [
         # Unsupported types go first
         ((types.BuiltinFunctionType, types.BuiltinMethodType,), "writeUnsupported"),
         ((bool,), "writeBoolean"),
         ((int,long), "writeInteger"),
         ((float,), "writeNumber"),
+        ((ByteArray,), "writeByteArray"),
         ((types.StringTypes,), "writeString"),
         ((util.ET._ElementInterface,), "writeXML"),
         ((types.DictType,), "writeDict"),
@@ -373,11 +396,16 @@
         ((types.InstanceType,types.ObjectType,), "writeObject"),
     ]
 
-    def __init__(self, output):
+    def __init__(self, output, context=None):
         """Constructs a new Encoder. output should be a writable
         file-like object."""
         self.output = output
 
+        if context == None:
+            context = pyamf.Context()
+
+        self.context = context
+
     def writeType(self, type):
         """
         Writes the type to the stream. Raises ValueError if type is not
@@ -411,14 +439,13 @@
         else:
             self.writeType(ASTypes.BOOL_FALSE)
 
-    def writeArray(self, a):
-        self.writeType(ASTypes.ARRAY)
-        self.output.write_ulong(len(a))
-
-        for data in a:
-            self.writeElement(data)
-
     def _writeInteger(self, n):
+        """
+        AMF Integers are encoded.
+        
+        See http://osflash.org/documentation/amf3/parsing_integers for more
+        info.
+        """
         bytes = []
 
         if n & 0xff000000 == 0:
@@ -437,10 +464,16 @@
         self.output.write_uchar(bytes[-1])
 
     def writeInteger(self, n):
+        """
+        Writes an integer to the data stream
+        """
         self.writeType(ASTypes.INTEGER)
         self._writeInteger(n)
 
     def writeNumber(self, n):
+        """
+        Writes a non integer to the data stream
+        """
         self.writeType(ASTypes.NUMBER)
         self.output.write_double(n)
 
@@ -448,27 +481,21 @@
         """
         Writes a raw string to the stream.
         """
-        s = encode_utf8_modified(n)[2:]
-        strlen = len(s)
-
-        if strlen == 0:
+        if len(n) == 0:
             self._writeInteger(REFERENCE_BIT)
 
             return
 
         try:
-            ref = self.str_refs.index(n)
-            use_ref = 1
-        except ValueError:
-            # add string reference
-            self.str_refs.append(n)
-            use_ref = 0
+            ref = self.context.getStringReference(n)
+            self._writeInteger(ref << 1)
 
-        if use_ref == 1:
-            self._writeInteger(ref << 1)
             return
+        except pyamf.ReferenceError:
+            self.context.addString(n)
 
-        self._writeInteger((strlen << 1) | REFERENCE_BIT)
+        s = encode_utf8_modified(n)[2:]
+        self._writeInteger((len(s) << 1) | REFERENCE_BIT)
 
         for ch in s:
             self.output.write_uchar(ord(ch))
@@ -490,21 +517,19 @@
         self.writeType(ASTypes.DATE)
 
         try:
-            ref = self.obj_refs.index(n)
-            use_ref = 1
-        except ValueError:
-            # add an object reference
-            self.obj_refs.append(n)
-            use_ref = 0
-
-        if use_ref == 1:
+            ref = self.context.getObjectReference(n)
             self._writeInteger(ref << 1)
-        else:
-            self._writeInteger(REFERENCE_BIT)
 
-            ms = time.mktime(n.timetuple())
-            self.output.write_double(ms * 100.0)
+            return
+        except pyamf.ReferenceError:
+            pass
 
+        self.context.addObject(n)
+        self._writeInteger(REFERENCE_BIT)
+
+        ms = time.mktime(n.timetuple())
+        self.output.write_double(ms * 100.0)
+
     def writeList(self, n):
         """
         Writes a list to the stream.
@@ -512,22 +537,20 @@
         self.writeType(ASTypes.ARRAY)
 
         try:
-            ref = self.obj_refs.index(n)
-            use_ref = 1
-        except ValueError:
-            # add an object reference
-            self.obj_refs.append(n)
-            use_ref = 0
-
-        if use_ref == 1:
+            ref = self.context.getObjectReference(n)
             self._writeInteger(ref << 1)
-        else:
-            self._writeInteger(len(n) << 1 | REFERENCE_BIT)
 
-            self.output.write_uchar(0x01)
-            for x in n:
-                self.writeElement(x)
+            return
+        except pyamf.ReferenceError:
+            pass
 
+        self.context.addObject(n)
+        self._writeInteger(len(n) << 1 | REFERENCE_BIT)
+
+        self.output.write_uchar(0x01)
+        for x in n:
+            self.writeElement(x)
+
     def writeDict(self, n):
         """
         Writes a dict to the stream.
@@ -535,18 +558,15 @@
         self.writeType(ASTypes.ARRAY)
 
         try:
-            ref = self.obj_refs.index(n)
-            use_ref = 1
-        except ValueError:
-            # add an object reference
-            self.obj_refs.append(n)
-            use_ref = 0
-
-        if use_ref == 1:
+            ref = self.context.getObjectReference(n)
             self._writeInteger(ref << 1)
 
             return
+        except pyamf.ReferenceError:
+            pass
 
+        self.context.addObject(n)
+
         # The AMF3 spec demands that all str based indicies be listed first
         keys = n.keys()
         int_keys = []
@@ -580,11 +600,12 @@
         self._writeInteger(len(int_keys) << 1 | REFERENCE_BIT)
 
         for x in str_keys:
-            # Design bug in Flash 9 that cannot read empty key strings
-            # see http://www.docuverse.com/blog/donpark/2007/05/14/flash-9-amf3-bug
+            # Design bug in AMF3 that cannot read/write empty key strings
+            # http://www.docuverse.com/blog/donpark/2007/05/14/flash-9-amf3-bug
             # for more info
             if x == '':
-                raise pyamf.EncodeError("dicts cannot contain empty string keys")
+                raise pyamf.EncodeError(
+                    "dicts cannot contain empty string keys")
 
             self._writeString(x)
             self.writeElement(n[x])
@@ -594,25 +615,42 @@
         for k in int_keys:
             self.writeElement(n[k])
 
-class AMF3Class:
+    def writeObject(self, n):
+        """
+        Writes an object to the stream.
+        """
+        try:
+            ref = self.context.getObjectReference(n)
+            self._writeInteger(ref << 1)
 
-    def __init__(self, name=None, encoding=None, attrs=None):
-        self.name = name
-        self.encoding = encoding
-        self.attrs = attrs
+            return
+        except pyamf.ReferenceError:
+            pass
 
-class AMF3Object:
+        self.context.addObject(n)
 
-    def __init__(self, class_=None):
-        self.__amf_class = class_
+    def writeByteArray(self, n):
+        """
+        Writes a L{ByteArray} to the data stream.
+        """
+        self.writeType(ASTypes.BYTEARRAY)
+        
+        try:
+            ref = self.context.getObjectReference(n)
+            self._writeInteger(ref << 1)
 
-    def __repr__(self):
-        return "<AMF3Object [%s] at 0x%08X>" % (
-            self.__amf_class and self.__amf_class.name or "no class",
-            id(self))
+            return
+        except pyamf.ReferenceError:
+            pass
 
-class AbstractMessage:
+        self.context.addObject(n)
+        self._writeInteger(len(n) << 1 | REFERENCE_BIT)
 
+        for ch in n:
+            self.output.write_uchar(ord(ch))
+
+class AbstractMessage(object):
+
     def __init__(self):
         # The body of the message.
         self.data = None
@@ -759,3 +797,18 @@
     utf16 = "".join([chr((c >> 8) & 0xff) + chr(c & 0xff) for c in utf16])
 
     return unicode(utf16, "utf_16_be")
+
+def lookup_class(cl, context):
+    """
+    Looks up a class in the context, based on the supplied ClassDefinition
+    
+    @return a callable.
+    """
+    if cl.klass:
+        return cl.klass
+
+    
+
+    print cl
+    
+    return Bag

Modified: branches/amf3-5/pyamf/tests/amf3.py
===================================================================
--- branches/amf3-5/pyamf/tests/amf3.py	2007-10-25 11:53:11 UTC (rev 74)
+++ branches/amf3-5/pyamf/tests/amf3.py	2007-10-26 09:59:07 UTC (rev 75)
@@ -54,8 +54,7 @@
         self.e = amf3.Encoder(self.buf)
 
     def _run(self, data):
-        self.e.str_refs = []
-        self.e.obj_refs = []
+        self.e.context.clear()
 
         e = EncoderTester(self.e, data)
         e.run(self)
@@ -155,6 +154,17 @@
 
         self.failUnlessRaises(pyamf.EncodeError, x)
 
+    def test_object(self):
+        class Object(object):
+            def __init__(self, di={}):
+                for n, v in di.items():
+                    setattr(self, n, v)
+
+        self._run([(Object({'baz': u'hello', 'foo': u'bar'}), '')])
+
+    def test_byte_array(self):
+        self._run([(amf3.ByteArray('hello'), '\x0c\x0bhello')])
+
 class ParserTestCase(unittest.TestCase):
     def setUp(self):
         self.buf = util.BufferedByteStream()
@@ -162,8 +172,7 @@
         self.parser.input = self.buf
 
     def _run(self, data):
-        self.parser.str_refs = []
-        self.parser.obj_refs = []
+        self.parser.context.clear()
         e = ParserTester(self.parser, data)
         e.run(self)
 
@@ -263,8 +272,6 @@
             '\x09\x09\x03\x62\x06\x00\x03\x64\x06\x02\x03\x61\x06\x04\x03\x63'
             '\x06\x06\x01\x04\x00\x04\x01\x04\x02\x04\x03')
             ])
-        self._run([({'': 1, 0: 1}, '\x09\x03\x01\x04\x01\x01\x04\x01')])
-        self._run([({'': 1, 0: 2}, '\x09\x03\x01\x04\x01\x01\x04\x02')])
 
     def test_empty_dict(self):
         """
@@ -287,8 +294,22 @@
 
     def test_object(self):
         self._run([
-            ({'': 1, 0: 2}, '\x0a\x0b\x01\x01\x04\x01\x03\x30\x04\x02\x01')])
+            ({'a': 1, 'b': 2}, '\x0a\x0b\x01\x03\x62\x04\x02\x03\x61\x04\x01'
+                '\x01')])
+        self._run([
+            ({'baz': u'hello'}, '\x0a\x0b\x01\x07\x62\x61\x7a\x06\x0b\x68\x65'
+                '\x6c\x6c\x6f\x01')])
+        self._run([
+            ({'baz': u'hello'}, '\x0a\x13\x01\x07\x62\x61\x7a\x06\x0b\x68\x65'
+                '\x6c\x6c\x6f')])
+        self._run([
+            ({'baz': u'hello'}, '\x0a\x13\x31\x63\x6f\x6d\x2e\x63\x6f\x6c\x6c'
+                '\x61\x62\x2e\x64\x65\x76\x2e\x70\x79\x61\x6d\x66\x2e\x66\x6f'
+                '\x6f\x07\x62\x61\x7a\x06\x0b\x68\x65\x6c\x6c\x6f')])
 
+    def test_byte_array(self):
+        self._run([(amf3.ByteArray('hello'), '\x0c\x0bhello')])
+
 class ModifiedUTF8TestCase(unittest.TestCase):
     data = [
         ('hello', '\x00\x05\x68\x65\x6c\x6c\x6f'),

Modified: branches/amf3-5/pyamf/util.py
===================================================================
--- branches/amf3-5/pyamf/util.py	2007-10-25 11:53:11 UTC (rev 74)
+++ branches/amf3-5/pyamf/util.py	2007-10-26 09:59:07 UTC (rev 75)
@@ -36,7 +36,7 @@
     except ImportError:
         import elementtree.ElementTree as ET
 
-class NetworkIOMixIn:
+class NetworkIOMixIn(object):
     """Provides mix-in methods for file like objects to read and write basic
     datatypes in network (= big-endian) byte-order."""
 


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic