Index: server/lib/ipprequest.py
===================================================================
--- server/lib/ipprequest.py	(revision 8403f61f7f4d1613116c682f90324e3086a042cf)
+++ server/lib/ipprequest.py	(revision 8e43aa84ac938567b574f237763f0afa75a8b9ad)
@@ -86,6 +86,6 @@
         assert value is not None
 
-        self.value_tag = hex(value_tag)
-        self.value = str(value)
+        self.value_tag = value_tag
+        self.value = value
 
 class IPPAttribute():
@@ -128,7 +128,7 @@
         Arguments:
 
-        name -- the name of the attribute
-
-        values -- a list of IPPValues.  May not be empty.
+            name -- the name of the attribute
+
+            values -- a list of IPPValues.  May not be empty.
         """
 
@@ -141,5 +141,5 @@
         for value in values: assert isinstance(value, IPPValue)
          
-        self.name = str(name)
+        self.name = name
         self.values = values
 
@@ -152,23 +152,84 @@
         values = []
         for v, i in zip(self.values, xrange(len(self.values))):
+            name_length = len(self.name)
+            if i > 0: name_length = 0
+            value_length = len(v.value)
+
+            logger.debug("dumping name_length : %i" % name_length)
+            logger.debug("dumping name : %s" % self.name)
+            logger.debug("dumping value_length : %i" % value_length)
+            logger.debug("dumping value : %s" % v.value)
+
+            # the value tag in binary
+            value_tag_bin = struct.pack('>b', v.value_tag)
+
+            # the name length in binary
+            name_length_bin = struct.pack('>h', name_length)
+
+            # the name in binary
+            name_bin = self.name
+
+            # the value length in binary
+            value_length_bin = struct.pack('>h', value_length)
+
+            # the value in binary
+            value_bin = v.value
+
             if i == 0:
-                name_length = sys.getsizeof(self.name)
-                value_length = sys.getsizeof(v.value)
-                values.append(struct.pack('>bh%ssh%ss' % (name_length, value_length),
-                                          v.value_tag,
-                                          name_length,
-                                          self.name,
-                                          value_length,
-                                          v.value))
+                values.append(''.join([value_tag_bin,
+                                       name_length_bin,
+                                       name_bin,
+                                       value_length_bin,
+                                       value_bin]))
             else:
-                value_length = sys.getsizeof(v.value)
-                values.append(struct.pack('>bhh%ss' % (value_length),
-                                          v.value_tag,
-                                          name_length,
-                                          value_length,
-                                          v.value))
+                values.append(''.join([value_tag_bin,
+                                       name_length_bin,
+                                       value_length_bin,
+                                       value_bin]))
                 
         # concatenate everything together and return it
         return ''.join(values)
+
+class IPPAttributeGroup():
+    """
+    An IPPAttributeGroup consists of an attribute-group-tag, followed
+    by a sequence of IPPAttributes.
+    """
+
+    def __init__(self, attribute_group_tag, attributes=[]):
+        """
+        Initialize an IPPAttributeGroup.
+
+        Arguments:
+
+            attribute_group_tag -- a signed char, holds the tag of the
+                                   attribute group
+
+            attributes -- (optional) a list of attributes
+        """
+
+        # make sure attribute_group_tag isn't empty
+        assert attribute_group_tag is not None
+
+        # make sure attributes is a list or tuple of IPPAttributes
+        assert isinstance(attributes, (list, tuple))
+        for a in attributes: assert isinstance(a, IPPAttribute)
+
+        self.attribute_group_tag = attribute_group_tag
+        self.attributes = attributes
+
+    def toBinaryData(self):
+        """
+        Convert the IPPAttributeGroup to binary.
+        """
+
+        # conver the attribute_group_tag to binary
+        tag = struct.pack('>b', self.attribute_group_tag)
+
+        # convert each of the attributes to binary
+        attributes = [a.toBinaryData() for a in self.attributes]
+
+        # concatenate everything and return
+        return tag + ''.join(attributes)
 
 class IPPRequest():
@@ -199,5 +260,6 @@
     # attribute_sequence, and data, or a file handler (request) which
     # can be read from to get the request
-    def __init__(self, version=None, operation_id=None, request_id=None, attributes=[], data=None, request=None):
+    def __init__(self, version=None, operation_id=None, request_id=None,
+                 attribute_groups=[], data=None, request=None):
         """
         Create an IPPRequest.  Takes either the segments of the
@@ -218,5 +280,5 @@
                           request itself.
 
-            attributes -- (optional) a list of IPPAttributes
+            attribute_groups -- a list of IPPAttributes, at least length 1
 
             data -- (optional) variable length, containing the actual
@@ -239,4 +301,7 @@
             # make sure the request id isn't empty
             assert request_id is not None
+            # make sure attribute_groups is a list of IPPAttributes
+            assert len(attribute_groups) > 0
+            for a in attribute_groups: assert isinstance(a, IPPAttribute)
             
         # if the request isn't None, then we'll read directly from
@@ -258,5 +323,5 @@
             # now we have to read in the attributes.  Each attribute
             # has a tag (1 byte) and a sequence of values (n bytes)
-            self.attributes     = []
+            self.attribute_groups = []
 
             # read in the next byte
@@ -271,4 +336,6 @@
                 logger.debug("attribute-tag : %i" % attribute_group_tag)
 
+                attributes = []
+
                 next_byte = struct.unpack('>b', request.read(1))[0]
                 logger.debug("next byte : 0x%X" % next_byte)
@@ -299,6 +366,6 @@
                         # create a new IPPAttribute from the data we just
                         # read in, and add it to our attributes list
-                        self.attributes.append(IPPAttribute(name,
-                                                            [IPPValue(value_tag, value)]))
+                        attributes.append(IPPAttribute(name,
+                                                       [IPPValue(value_tag, value)]))
 
                     else:
@@ -312,8 +379,10 @@
 
                         # add another value to the last attribute
-                        self.attributes[-1].values.append(IPPValue(value_tag, value))
+                        attributes[-1].values.append(IPPValue(value_tag, value))
 
                     # read another byte
                     next_byte = struct.unpack('>b', request.read(1))[0]
+
+                self.attribute_groups.append(IPPAttributeGroup(attribute_group_tag, attributes))
 
             # once we hit the end-of-attributes tag, the only thing
@@ -325,8 +394,8 @@
         # arguments passed in
         else:
-            self.version = (int(version[0]), int(version[1]))
-            self.operation_id = int(operation_id)
-            self.request_id = int(request_id)
-            self.attributes = attributes
+            self.version = (version[0], version[1])
+            self.operation_id = operation_id
+            self.request_id = request_id
+            self.attribute_groups = attribute_groups
             self.data = data
 
@@ -343,6 +412,6 @@
                                     self.request_id)
 
-        # convert the attributes to binary
-        attributes = ''.join([a.toBinaryData() for a in self.attributes])
+        # convert the attribute groups to binary
+        attribute_groups = ''.join([a.toBinaryData() for a in self.attribute_groups])
 
         # conver the end-of-attributes-tag to binary
@@ -356,3 +425,3 @@
 
         # append everything together and return it
-        return preattributes + attributes + end_of_attributes_tag + data
+        return preattributes + attribute_groups + end_of_attributes_tag + data
