Index: server/lib/gutenbach/ipp/__init__.py
===================================================================
--- server/lib/gutenbach/ipp/__init__.py	(revision aded2d1280aa9d2333d252f6f2557cfa3b1b1cd1)
+++ server/lib/gutenbach/ipp/__init__.py	(revision b828a96dac6143596be1f8d07d8f319288fde70d)
@@ -18,5 +18,5 @@
 __all__.extend(constants.__all__)
 
-import exceptions as errors
+import errors
 __all__.append('errors')
 
Index: server/lib/gutenbach/ipp/attribute.py
===================================================================
--- server/lib/gutenbach/ipp/attribute.py	(revision cad7502f2e3816fb8f3099cc05928f7fdc5e44f9)
+++ server/lib/gutenbach/ipp/attribute.py	(revision b828a96dac6143596be1f8d07d8f319288fde70d)
@@ -70,4 +70,10 @@
         self.name = name
         self.values = values
+
+    def __cmp__(self, other):
+        eq = self.name == other.name
+        for v1, v2 in zip(self.values, other.values):
+            eq = eq and (v1 == v2)
+        return 0 if eq else 1
 
     @property
Index: server/lib/gutenbach/ipp/attributegroup.py
===================================================================
--- server/lib/gutenbach/ipp/attributegroup.py	(revision b2e077a94f58512ca52085a59f40ffecab7178d5)
+++ server/lib/gutenbach/ipp/attributegroup.py	(revision b828a96dac6143596be1f8d07d8f319288fde70d)
@@ -40,4 +40,10 @@
         self.attributes = []
         self.extend(attributes)
+
+    def __cmp__(self, other):
+        eq = self.tag == other.tag
+        for a1, a2 in zip(self.attributes, other.attributes):
+            eq = eq and (a1 == a2)
+        return 0 if eq else 1
 
     def __getitem__(self, name):
Index: server/lib/gutenbach/ipp/object_attributes/__init__.py
===================================================================
--- server/lib/gutenbach/ipp/object_attributes/__init__.py	(revision aded2d1280aa9d2333d252f6f2557cfa3b1b1cd1)
+++ server/lib/gutenbach/ipp/object_attributes/__init__.py	(revision b828a96dac6143596be1f8d07d8f319288fde70d)
@@ -2,9 +2,12 @@
 from job_description_attributes import *
 from printer_description_attributes import *
+from operation_attributes import *
 
 __all__ = ['job_template_attributes',
            'job_description_attributes',
-           'printer_description_attributes']
+           'printer_description_attributes',
+           'operation_attributes']
 __all__.extend(job_template_attributes.__all__)
 __all__.extend(job_description_attributes.__all__)
 __all__.extend(printer_description_attributes.__all__)
+__all__.extend(operation_attributes.__all__)
Index: server/lib/gutenbach/ipp/object_attributes/job_description_attributes.py
===================================================================
--- server/lib/gutenbach/ipp/object_attributes/job_description_attributes.py	(revision aded2d1280aa9d2333d252f6f2557cfa3b1b1cd1)
+++ server/lib/gutenbach/ipp/object_attributes/job_description_attributes.py	(revision b828a96dac6143596be1f8d07d8f319288fde70d)
@@ -37,5 +37,5 @@
 from ..constants import *
 
-class JobUri(Attribute):
+def JobUri(val):
     """4.3.1 job-uri (uri)
 
@@ -61,10 +61,9 @@
     """
 
-    def __init__(self, val):
-        super(type(self), self).__init__(
-            'job-uri',
-            [Value(CharacterStringTags.URI, val)])
-
-class JobId(Attribute):
+    return Attribute(
+        'job-uri',
+        [Value(CharacterStringTags.URI, val)])
+
+def JobId(val):
     """4.3.2 job-id (integer(1:MAX))
 
@@ -82,10 +81,9 @@
     """
     
-    def __init__(self, val):
-        super(type(self), self).__init__(
-            'job-id',
-            [Value(IntegerTags.INTEGER, val)])
-
-class JobPrinterUri(Attribute):
+    return Attribute(
+        'job-id',
+        [Value(IntegerTags.INTEGER, val)])
+
+def JobPrinterUri(val):
     """4.3.3 job-printer-uri (uri)
 
@@ -105,18 +103,16 @@
     """
 
-    def __init__(self, val):
-        super(type(self), self).__init__(
-            'job-printer-uri',
-            [Value(CharacterStringTags.URI, val)])
-
-class JobMoreInfo(Attribute):
+    return Attribute(
+        'job-printer-uri',
+        [Value(CharacterStringTags.URI, val)])
+
+def JobMoreInfo(val):
     """4.3.4 job-more-info (uri)
 
     """
 
-    def __init__(self, val):
-        raise ClientErrorAttributes, "job-more-info"
-
-class JobName(Attribute):
+    raise ClientErrorAttributes, "job-more-info"
+
+def JobName(val):
     """4.3.5 job-name (name(MAX))
     
@@ -138,10 +134,9 @@
     """
     
-    def __init__(self, val):
-        super(type(self), self).__init__(
-            'job-name',
-            [Value(CharacterStringTags.NAME_WITHOUT_LANGUAGE, val)])
-
-class JobOriginatingUserName(Attribute):
+    return Attribute(
+        'job-name',
+        [Value(CharacterStringTags.NAME_WITHOUT_LANGUAGE, val)])
+
+def JobOriginatingUserName(val):
     """4.3.6 job-originating-user-name (name(MAX))
 
@@ -163,10 +158,9 @@
     """
     
-    def __init__(self, val):
-        super(type(self), self).__init__(
-            'job-originating-user-name',
-            [Value(CharacterStringTags.NAME_WITHOUT_LANGUAGE, val)])
-
-class JobState(Attribute):
+    return Attribute(
+        'job-originating-user-name',
+        [Value(CharacterStringTags.NAME_WITHOUT_LANGUAGE, val)])
+
+def JobState(val):
     """4.3.7 job-state (type1 enum)
 
@@ -181,10 +175,9 @@
     """
     
-    def __init__(self, val):
-        super(type(self), self).__init__(
-            'job-state',
-            [Value(IntegerTags.ENUM, val)])
-
-class JobStateReasons(Attribute):
+    return Attribute(
+        'job-state',
+        [Value(IntegerTags.ENUM, val)])
+
+def JobStateReasons(val):
     """4.3.8 job-state-reasons (1setOf type2 keyword)
 
@@ -212,50 +205,44 @@
     """
 
-    def __init__(self, *vals):
-        super(type(self), self).__init__(
-            'job-state-reasons',
-            [Value(CharacterStringTags.KEYWORD, val) for val in vals])
-
-class JobStateMessage(Attribute):
+    return Attribute(
+        'job-state-reasons',
+        [Value(CharacterStringTags.KEYWORD, val) for val in vals])
+
+def JobStateMessage(val):
     """4.3.9 job-state-message (text(MAX))
 
     """
 
-    def __init__(self, val):
-        raise ClientErrorAttributes, "job-state-message"
-
-class JobDetailedStatusMessages(Attribute):
+    raise ClientErrorAttributes, "job-state-message"
+
+def JobDetailedStatusMessages(val):
     """4.3.10 job-detailed-status-messages (1setOf text(MAX))
 
     """
 
-    def __init__(self, *vals):
-        raise ClientErrorAttributes, "job-detailed-status-messages"
-
-class JobDocumentAccessErrors(Attribute):
+    raise ClientErrorAttributes, "job-detailed-status-messages"
+
+def JobDocumentAccessErrors(val):
     """4.3.11 job-document-access-errors (1setOf text(MAX))
 
     """
 
-    def __init__(self, *vals):
-        raise ClientErrorAttributes, "job-document-access-errors"
-
-class NumberOfDocuments(Attribute):
+    raise ClientErrorAttributes, "job-document-access-errors"
+
+def NumberOfDocuments(val):
     """4.3.12 number-of-documents (integer(0:MAX))
 
     """
 
-    def __init__(self, val):
-        raise ClientErrorAttributes, "number-of-documents"
-
-class OutputDeviceAssigned(Attribute):
+    raise ClientErrorAttributes, "number-of-documents"
+
+def OutputDeviceAssigned(val):
     """4.3.13 output-device-assigned (name(127))
 
     """
 
-    def __init__(self, val):
-        raise ClientErrorAttributes, "output-device-assigned"
-
-class TimeAtCreation(Attribute):
+    raise ClientErrorAttributes, "output-device-assigned"
+
+def TimeAtCreation(val):
     """4.3.14.1 time-at-creation (integer(MIN:MAX))
 
@@ -265,10 +252,9 @@
     """
     
-    def __init__(self, val):
-        super(type(self), self).__init__(
-            "time-at-creation",
-            [Value(IntegerTags.INTEGER, val)])
-
-class TimeAtProcessing(Attribute):
+    return Attribute(
+        "time-at-creation",
+        [Value(IntegerTags.INTEGER, val)])
+
+def TimeAtProcessing(val):
     """4.3.14.2 time-at-processing (integer(MIN:MAX))
 
@@ -281,10 +267,9 @@
     """
 
-    def __init__(self, val):
-        super(type(self), self).__init__(
-            "time-at-processing",
-            [Value(IntegerTags.INTEGER, val)])
-
-class TimeAtCompleted(Attribute):
+    return Attribute(
+        "time-at-processing",
+        [Value(IntegerTags.INTEGER, val)])
+
+def TimeAtCompleted(val):
     """4.3.14.3 time-at-completed (integer(MIN:MAX))
 
@@ -296,10 +281,9 @@
     """
 
-    def __init__(self, val):
-        super(type(self), self).__init__(
-            "time-at-completed",
-            [Value(IntegerTags.INTEGER, val)])
-
-class JobPrinterUpTime(Attribute):
+    return Attribute(
+        "time-at-completed",
+        [Value(IntegerTags.INTEGER, val)])
+
+def JobPrinterUpTime(val):
     """4.3.14.4 job-printer-up-time (integer(1:MAX))
 
@@ -321,51 +305,45 @@
     """
 
-    def __init__(self, val):
-        super(type(self), self).__init__(
-            "job-printer-up-time",
-            [Value(IntegerTags.INTEGER, val)])
-
-
-class DateTimeAtCreation(Attribute):
+    return Attribute(
+        "job-printer-up-time",
+        [Value(IntegerTags.INTEGER, val)])
+
+
+def DateTimeAtCreation(val):
     """4.3.14.5 date-time-at-creation (dateTime)
 
     """
 
-    def __init__(self, val):
-        raise ClientErrorAttributes, "date-time-at-creation"
-
-class DateTimeAtProcessing(Attribute):
+    raise ClientErrorAttributes, "date-time-at-creation"
+
+def DateTimeAtProcessing(val):
     """4.3.14.6 date-time-at-processing (dateTime)
 
     """
 
-    def __init__(self, val):
-        raise ClientErrorAttributes, "date-time-at-processing"
-
-class DateTimeAtCompletion(Attribute):
+    raise ClientErrorAttributes, "date-time-at-processing"
+
+def DateTimeAtCompletion(val):
     """4.3.14.7 date-time-at-completed (dateTime)
 
     """
 
-    def __init__(self, val):
-        raise ClientErrorAttributes, "date-time-at-completion"
-
-class NumberOfInterveningJobs(Attribute):
+    raise ClientErrorAttributes, "date-time-at-completion"
+
+def NumberOfInterveningJobs(val):
     """4.3.15 number-of-intervening-jobs (integer(0:MAX))
 
     """
 
-    def __init__(self, val):
-        raise ClientErrorAttributes, "number-of-intervening-jobs"
-
-class JobMessageFromOperator(Attribute):
+    raise ClientErrorAttributes, "number-of-intervening-jobs"
+
+def JobMessageFromOperator(val):
     """4.3.16 job-message-from-operator (text(127))
 
     """
 
-    def __init__(self, val):
-        raise ClientErrorAttributes, "job-message-from-operator"
-
-class JobKOctets(Attribute):
+    raise ClientErrorAttributes, "job-message-from-operator"
+
+def JobKOctets(val):
     """4.3.17.1 job-k-octets (integer(0:MAX))
 
@@ -392,50 +370,44 @@
     """
     
-    def __init__(self, val):
-        super(type(self), self).__init__(
-            'job-k-octets',
-            [Value(IntegerTags.INTEGER, val)])
-
-class JobImpressions(Attribute):
+    return Attribute(
+        'job-k-octets',
+        [Value(IntegerTags.INTEGER, val)])
+
+def JobImpressions(val):
     """4.3.17.2 job-impressions (integer(0:MAX))
 
     """
 
-    def __init__(self, val):
-        raise ClientErrorAttributes, "job-impressions"
-
-class JobMediaSheets(Attribute):
+    raise ClientErrorAttributes, "job-impressions"
+
+def JobMediaSheets(val):
     """4.3.17.3 job-media-sheets (integer(0:MAX))
 
     """
 
-    def __init__(self, val):
-        raise ClientErrorAttributes, "job-media-sheets"
-
-class JobKOctetsProcessed(Attribute):
+    raise ClientErrorAttributes, "job-media-sheets"
+
+def JobKOctetsProcessed(val):
     """4.3.18.1 job-k-octets-processed (integer(0:MAX))
 
     """
 
-    def __init__(self, val):
-        raise ClientErrorAttributes, "job-k-octets-processed"
-
-class JobImpressionsCompleted(Attribute):
+    raise ClientErrorAttributes, "job-k-octets-processed"
+
+def JobImpressionsCompleted(val):
     """4.3.18.2 job-impressions-completed (integer(0:MAX))
 
     """
 
-    def __init__(self, val):
-        raise ClientErrorAttributes, "job-impressions-completed"
-
-class JobMediaSheetsCompleted(Attribute):
+    raise ClientErrorAttributes, "job-impressions-completed"
+
+def JobMediaSheetsCompleted(val):
     """4.3.18.3 job-media-sheets-completed (integer(0:MAX))
 
     """
 
-    def __init__(self, val):
-        raise ClientErrorAttributes, "job-media-sheets-completed"
-
-class AttributesCharset(Attribute):
+    raise ClientErrorAttributes, "job-media-sheets-completed"
+
+def AttributesCharset(val):
     """4.3.19 attributes-charset (charset)
 
@@ -456,10 +428,9 @@
     """
     
-    def __init__(self, val):
-        super(type(self), self).__init__(
-            'attributes-charset',
-            [Value(CharacterStringTags.CHARSET, val)])
-
-class AttributesNaturalLanguage(Attribute):
+    return Attribute(
+        'attributes-charset',
+        [Value(CharacterStringTags.CHARSET, val)])
+
+def AttributesNaturalLanguage(val):
     """4.3.20 attributes-natural-language (naturalLanguage)
 
@@ -477,6 +448,5 @@
     """
     
-    def __init__(self, val):
-        super(type(self), self).__init__(
-            'attributes-natural-language',
-            [Value(CharacterStringTags.NATURAL_LANGUAGE, val)])
+    return Attribute(
+        'attributes-natural-language',
+        [Value(CharacterStringTags.NATURAL_LANGUAGE, val)])
Index: server/lib/gutenbach/ipp/object_attributes/job_template_attributes.py
===================================================================
--- server/lib/gutenbach/ipp/object_attributes/job_template_attributes.py	(revision aded2d1280aa9d2333d252f6f2557cfa3b1b1cd1)
+++ server/lib/gutenbach/ipp/object_attributes/job_template_attributes.py	(revision b828a96dac6143596be1f8d07d8f319288fde70d)
@@ -19,5 +19,5 @@
 from ..exceptions import ClientErrorAttributes
 
-class JobPriority(Attribute):
+def JobPriority(val):
     """4.2.1 job-priority (integer(1:100))
 
@@ -69,103 +69,90 @@
     
     
-    def __init__(self, val):
-        super(type(self), self).__init__(
-            'job-priority',
-            [Value(IntegerTags.INTEGER), val])
+    return Attribute(
+        'job-priority',
+        [Value(IntegerTags.INTEGER), val])
 
-class JobHoldUntil(Attribute):
+def JobHoldUntil(val):
     """4.2.2 job-hold-until (type3 keyword | name (MAX))
     
     """
 
-    def __init__(self, val):
-        raise ClientErrorAttributes, "job-hold-until"
-
-class JobSheets(Attribute):
+    raise ClientErrorAttributes, "job-hold-until"
+    
+def JobSheets(val):
     """4.2.3 job-sheets (type3 keyword | name(MAX))
 
     """
+    
+    raise ClientErrorAttributes, "job-sheets"
 
-    def __init__(self, val):
-        raise ClientErrorAttributes, "job-sheets"
-
-class MultipleDocumentHandling(Attribute):
+def MultipleDocumentHandling(val):
     """4.2.4 multiple-document-handling (type2 keyword)
 
     """
 
-    def __init__(self, val):
-        raise ClientErrorAttributes, "multiple-document-handling"
+    raise ClientErrorAttributes, "multiple-document-handling"
 
-class Copies(Attribute):
+def Copies(val):
     """4.2.5 copies (integer(1:MAX))
 
     """
+    
+    raise ClientErrorAttributes, "copies"
 
-    def __init__(self, val):
-        raise ClientErrorAttributes, "copies"
-
-class Finishings(Attribute):
+def Finishings(*vals):
     """4.2.6 finishings (1setOf type2 enum)
 
     """
 
-    def __init__(self, *vals):
-        raise ClientErrorAttributes, "finishings"
+    raise ClientErrorAttributes, "finishings"
 
-class PageRanges(Attribute):
+def PageRanges(*vals):
     """4.2.7 page-ranges (1setOf rangeOfInteger (1:MAX))
 
     """
 
-    def __init__(self, *vals):
-        raise ClientErrorAttributes, "page-ranges"
+    raise ClientErrorAttributes, "page-ranges"
 
-class Sides(Attribute):
+def Sides(val):
     """4.2.8 sides (type2 keyword)
 
     """
 
-    def __init__(self, val):
-        raise ClientErrorAttributes, "sides"
+    raise ClientErrorAttributes, "sides"
 
-class NumberUp(Attribute):
+def NumberUp(val):
     """4.2.9 number-up (integer(1:MAX))
 
     """
 
-    def __init__(self, val):
-        raise ClientErrorAttributes, "number-up"
+    raise ClientErrorAttributes, "number-up"
 
-class OrientationRequested(Attribute):
+def OrientationRequested(val):
     """4.2.10 orientation-requested (type2 enum)
 
     """
 
-    def __init__(self, val):
-        raise ClientErrorAttributes, "orientation-requested"
+    raise ClientErrorAttributes, "orientation-requested"
 
-class Media(Attribute):
+def Media(val):
     """4.2.11 media (type3 keyword | name(MAX))
 
     """
 
-    def __init__(self, val):
-        raise ClientErrorAttributes, "media"
+    raise ClientErrorAttributes, "media"
 
 ### XXX: we may want to repurpose this for bitrate?
-class PrinterResolution(Attribute):
+def PrinterResolution(val):
     """4.2.12 printer-resolution (resolution)
 
     """
 
-    def __init__(self, val):
-        raise ClientErrorAttributes, "printer-resolution"
+    raise ClientErrorAttributes, "printer-resolution"
 
-class PrintQuality(Attribute):
+def PrintQuality(val):
     """4.2.13 print-quality (type2 enum)
 
     """
 
-    def __init__(self, val):
-        raise ClientErrorAttributes, "print-quality"
+    raise ClientErrorAttributes, "print-quality"
Index: server/lib/gutenbach/ipp/object_attributes/operation_attributes.py
===================================================================
--- server/lib/gutenbach/ipp/object_attributes/operation_attributes.py	(revision aded2d1280aa9d2333d252f6f2557cfa3b1b1cd1)
+++ server/lib/gutenbach/ipp/object_attributes/operation_attributes.py	(revision b828a96dac6143596be1f8d07d8f319288fde70d)
@@ -9,13 +9,11 @@
 from ..constants import *
 
-class PrinterUri(Attribute):
-    def __init__(self, val):
-        super(type(self), self).__init__(
-            'printer-uri',
-            [Value(CharacterStringTags.URI, val)])
+def PrinterUri(val):
+    return Attribute(
+        'printer-uri',
+        [Value(CharacterStringTags.URI, val)])
 
-class RequestingUserName(Attribute):
-    def __init__(self, val):
-        super(type(self), self).__init__(
-            'requesting-user-name',
-            [Value(CharacterStringTags.NAME_WITHOUT_LANGUAGE, val)])
+def RequestingUserName(val):
+    return Attribute(
+        'requesting-user-name',
+        [Value(CharacterStringTags.NAME_WITHOUT_LANGUAGE, val)])
Index: server/lib/gutenbach/ipp/object_attributes/printer_description_attributes.py
===================================================================
--- server/lib/gutenbach/ipp/object_attributes/printer_description_attributes.py	(revision aded2d1280aa9d2333d252f6f2557cfa3b1b1cd1)
+++ server/lib/gutenbach/ipp/object_attributes/printer_description_attributes.py	(revision b828a96dac6143596be1f8d07d8f319288fde70d)
@@ -44,5 +44,5 @@
 from ..constants import *
 
-class PrinterUriSupported(Attribute):
+def PrinterUriSupported(*vals):
     """4.4.1 printer-uri-supported (1setOf uri)
 
@@ -63,11 +63,10 @@
     """
     
-    def __init__(self, *vals):
-        super(type(self), self).__init__(
-            'printer-uri-supported',
-            [Value(CharacterStringTags.URI, val) for val in vals])
-
-
-class UriAuthenticationSupported(Attribute):
+    return Attribute(
+        'printer-uri-supported',
+        [Value(CharacterStringTags.URI, val) for val in vals])
+
+
+def UriAuthenticationSupported(*vals):
     """4.4.2 uri-authentication-supported (1setOf type2 keyword)
 
@@ -86,10 +85,9 @@
     """
     
-    def __init__(self, val):
-        super(type(self), self).__init__(
-            'uri-authentication-supported',
-            [Value(CharacterStringTags.KEYWORD, val)])
-
-class UriSecuritySupported(Attribute):
+    return Attribute(
+        'uri-authentication-supported',
+        [Value(CharacterStringTags.KEYWORD, val) for val in vals])
+
+def UriSecuritySupported(*vals):
     """4.4.3 uri-security-supported (1setOf type2 keyword)
 
@@ -117,10 +115,9 @@
     """
     
-    def __init__(self, val):
-        super(type(self), self).__init__(
-            'uri-security-supported',
-            [Value(CharacterStringTags.KEYWORD, val)])
-
-class PrinterName(Attribute):
+    return Attribute(
+        'uri-security-supported',
+        [Value(CharacterStringTags.KEYWORD, val) for val in vals])
+
+def PrinterName(val):
     """4.4.4 printer-name (name(127))
 
@@ -134,58 +131,51 @@
     """
     
-    def __init__(self, val):
-        super(type(self), self).__init__(
-            'printer-name',
-            [Value(CharacterStringTags.NAME_WITHOUT_LANGUAGE, val)])
-
-class PrinterLocation(Attribute):
+    return Attribute(
+        'printer-name',
+        [Value(CharacterStringTags.NAME_WITHOUT_LANGUAGE, val)])
+
+def PrinterLocation(val):
     """4.4.5 printer-location (text(127))
 
     """
 
-    def __init__(self, val):
-        raise ClientErrorAttributes, "printer-location"
-
-class PrinterInfo(Attribute):
+    raise ClientErrorAttributes, "printer-location"
+
+def PrinterInfo(val):
     """4.4.6 printer-info (text(127))
 
     """
 
-    def __init__(self, val):
-        raise ClientErrorAttributes, "printer-info"
-
-class PrinterMoreInfo(Attribute):
+    raise ClientErrorAttributes, "printer-info"
+
+def PrinterMoreInfo(val):
     """4.4.7 printer-more-info (uri)
 
     """
 
-    def __init__(self, val):
-        raise ClientErrorAttributes, "printer-more-info"
-
-class PrinterDriverInstaller(Attribute):
+    raise ClientErrorAttributes, "printer-more-info"
+
+def PrinterDriverInstaller(val):
     """4.4.8 printer-driver-installer (uri)
 
     """
 
-    def __init__(self, val):
-        raise ClientErrorAttributes, "printer-driver-installer"
-
-class PrinterMakeAndModel(Attribute):
+    raise ClientErrorAttributes, "printer-driver-installer"
+
+def PrinterMakeAndModel(val):
     """4.4.9 printer-make-and-model (text(127))
 
     """
 
-    def __init__(self, val):
-        raise ClientErrorAttributes, "printer-make-and-model"
-
-class PrinterMoreInfoManufacturer(Attribute):
+    raise ClientErrorAttributes, "printer-make-and-model"
+
+def PrinterMoreInfoManufacturer(val):
     """4.4.10 printer-more-info-manufacturer (uri)
 
     """
 
-    def __init__(self, val):
-        raise ClientErrorAttributes, "printer-more-info-manufacturer"
-
-class PrinterState(Attribute):
+    raise ClientErrorAttributes, "printer-more-info-manufacturer"
+
+def PrinterState(val):
     """4.4.11 printer-state (type1 enum)
 
@@ -203,10 +193,9 @@
     """
     
-    def __init__(self, val):
-        super(type(self), self).__init__(
-            'printer-state',
-            [Value(IntegerTags.ENUM, val)])
-
-class PrinterStateReasons(Attribute):
+    return Attribute(
+        'printer-state',
+        [Value(IntegerTags.ENUM, val)])
+
+def PrinterStateReasons(*vals):
     """4.4.12 printer-state-reasons (1setOf type2 keyword)
 
@@ -221,18 +210,16 @@
     """
     
-    def __init__(self, val):
-        super(type(self), self).__init__(
-            'printer-state-reasons',
-            [Value(CharacterStringTags.KEYWORD, val)])
-
-class PrinterStateMessage(Attribute):
+    return Attribute(
+        'printer-state-reasons',
+        [Value(CharacterStringTags.KEYWORD, val) for val in vals])
+
+def PrinterStateMessage(val):
     """4.4.13 printer-state-message (text(MAX))
 
     """
 
-    def __init__(self, val):
-        raise ClientErrorAttributes, "printer-state-message"
-
-class IppVersionsSupported(Attribute):
+    raise ClientErrorAttributes, "printer-state-message"
+
+def IppVersionsSupported(*vals):
     """4.4.14 ipp-versions-supported (1setOf type2 keyword)
 
@@ -266,10 +253,9 @@
     """
     
-    def __init__(self, *vals):
-        super(type(self), self).__init__(
-            'ipp-versions-supported',
-            [Value(CharacterStringTags.KEYWORD, val) for val in vals])
-
-class OperationsSupported(Attribute):
+    return Attribute(
+        'ipp-versions-supported',
+        [Value(CharacterStringTags.KEYWORD, val) for val in vals])
+
+def OperationsSupported(*vals):
     """4.4.15 operations-supported (1setOf type2 enum)
 
@@ -286,10 +272,9 @@
     """
     
-    def __init__(self, *vals):
-        super(type(self), self).__init__(
-            'operations-supported',
-            [Value(IntegerTags.ENUM, val) for val in vals])
-
-class MultipleDocumentJobsSupported(Attribute):
+    return Attribute(
+        'operations-supported',
+        [Value(IntegerTags.ENUM, val) for val in vals])
+
+def MultipleDocumentJobsSupported(val):
     """4.4.16 multiple-document-jobs-supported (boolean)
 
@@ -302,10 +287,9 @@
     """
     
-    def __init__(self, val):
-        super(type(self), self).__init__(
-            'multiple-document-jobs-supported',
-            [Value(IntegerTags.BOOLEAN, val)])
-
-class CharsetConfigured(Attribute):
+    return Attribute(
+        'multiple-document-jobs-supported',
+        [Value(IntegerTags.BOOLEAN, val)])
+
+def CharsetConfigured(val):
     """4.4.17 charset-configured (charset)
 
@@ -321,10 +305,9 @@
     """
     
-    def __init__(self, val):
-        super(type(self), self).__init__(
-            'charset-configured',
-            [Value(CharacterStringTags.CHARSET, val)])
-
-class CharsetSupported(Attribute):
+    return Attribute(
+        'charset-configured',
+        [Value(CharacterStringTags.CHARSET, val)])
+
+def CharsetSupported(*vals):
     """4.4.18 charset-supported (1setOf charset)
 
@@ -344,10 +327,9 @@
     """
     
-    def __init__(self, *vals):
-        super(type(self), self).__init__(
-            'charset-supported',
-            [Value(CharacterStringTags.CHARSET, val) for val in vals])
-
-class NaturalLanguageConfigured(Attribute):
+    return Attribute(
+        'charset-supported',
+        [Value(CharacterStringTags.CHARSET, val) for val in vals])
+
+def NaturalLanguageConfigured(val):
     """4.4.19 natural-language-configured (naturalLanguage)
 
@@ -370,10 +352,9 @@
     """
     
-    def __init__(self, val):
-        super(type(self), self).__init__(
-            'natural-language-configured',
-            [Value(CharacterStringTags.NATURAL_LANGUAGE, val)])
-
-class GeneratedNaturalLanguageSupported(Attribute):
+    return Attribute(
+        'natural-language-configured',
+        [Value(CharacterStringTags.NATURAL_LANGUAGE, val)])
+
+def GeneratedNaturalLanguageSupported(*vals):
     """4.4.20 generated-natural-language-supported (1setOf naturalLanguage)
 
@@ -402,10 +383,9 @@
     """
     
-    def __init__(self, *vals):
-        super(type(self), self).__init__(
-            'generated-natural-language-supported',
-            [Value(CharacterStringTags.NATURAL_LANGUAGE, val) for val in vals])
-
-class DocumentFormatDefault(Attribute):
+    return Attribute(
+        'generated-natural-language-supported',
+        [Value(CharacterStringTags.NATURAL_LANGUAGE, val) for val in vals])
+
+def DocumentFormatDefault(val):
     """4.4.21 document-format-default (mimeMediaType)
 
@@ -421,10 +401,9 @@
     """
     
-    def __init__(self, val):
-        super(type(self), self).__init__(
-            'document-format-default',
-            [Value(CharacterStringTags.MIME_MEDIA_TYPE, val)])
-
-class DocumentFormatSupported(Attribute):
+    return Attribute(
+        'document-format-default',
+        [Value(CharacterStringTags.MIME_MEDIA_TYPE, val)])
+
+def DocumentFormatSupported(*vals):
     """4.4.22 document-format-supported (1setOf mimeMediaType)
 
@@ -436,10 +415,9 @@
     """
     
-    def __init__(self, *vals):
-        super(type(self), self).__init__(
-            'document-format-supported',
-            [Value(CharacterStringTags.MIME_MEDIA_TYPE, val) for val in vals])
-
-class PrinterIsAcceptingJobs(Attribute):
+    return Attribute(
+        'document-format-supported',
+        [Value(CharacterStringTags.MIME_MEDIA_TYPE, val) for val in vals])
+
+def PrinterIsAcceptingJobs(val):
     """4.4.23 printer-is-accepting-jobs (boolean)
 
@@ -462,10 +440,9 @@
     """
     
-    def __init__(self, val):
-        super(type(self), self).__init__(
-            'printer-is-accepting-jobs',
-            [Value(IntegerTags.BOOLEAN, val)])
-
-class QueuedJobCount(Attribute):
+    return Attribute(
+        'printer-is-accepting-jobs',
+        [Value(IntegerTags.BOOLEAN, val)])
+
+def QueuedJobCount(val):
     """4.4.24 queued-job-count (integer(0:MAX))
 
@@ -476,34 +453,30 @@
     """
     
-    def __init__(self, val):
-        super(type(self), self).__init__(
-            'queued-job-count',
-            [Value(IntegerTags.INTEGER, val)])
-
-class PrinterMessageFromOperator(Attribute):
+    return Attribute(
+        'queued-job-count',
+        [Value(IntegerTags.INTEGER, val)])
+
+def PrinterMessageFromOperator(val):
     """4.4.25 printer-message-from-operator (text(127))
 
     """
 
-    def __init__(self, val):
-        raise ClientErrorAttributes, "printer-message-from-operator"
-
-class ColorSupported(Attribute):
+    raise ClientErrorAttributes, "printer-message-from-operator"
+
+def ColorSupported(val):
     """4.4.26 color-supported (boolean)
 
     """
 
-    def __init__(self, val):
-        raise ClientErrorAttributes, "color-supported"
-
-class ReferenceUriSchemeSupported(Attribute):
+    raise ClientErrorAttributes, "color-supported"
+    
+def ReferenceUriSchemeSupported(val):
     """4.4.27 reference-uri-schemes-supported (1setOf uriScheme)
 
     """
 
-    def __init__(self, *vals):
-        raise ClientErrorAttributes, "reference-uri-scheme-supported"
-
-class PdlOverrideSupported(Attribute):
+    raise ClientErrorAttributes, "reference-uri-scheme-supported"
+
+def PdlOverrideSupported(val):
     """4.4.28 pdl-override-supported (type2 keyword)
 
@@ -528,10 +501,9 @@
     """
     
-    def __init__(self, val):
-        super(type(self), self).__init__(
-            'pdl-override-supported',
-            [Value(CharacterStringTags.KEYWORD, val)])
-
-class PrinterUpTime(Attribute):
+    return Attribute(
+        'pdl-override-supported',
+        [Value(CharacterStringTags.KEYWORD, val)])
+
+def PrinterUpTime(val):
     """4.4.29 printer-up-time (integer(1:MAX))
 
@@ -566,18 +538,16 @@
     """
     
-    def __init__(self, val):
-        super(type(self), self).__init__(
-            'printer-up-time',
-            [Value(IntegerTags.INTEGER, val)])
-
-class PrinterCurrentTime(Attribute):
+    return Attribute(
+        'printer-up-time',
+        [Value(IntegerTags.INTEGER, val)])
+
+def PrinterCurrentTime(val):
     """4.4.30 printer-current-time (dateTime)
 
     """
 
-    def __init__(self, val):
-        raise ClientErrorAttributes, "printer-current-time"
-
-class MultipleOperationTimeOut(Attribute):
+    raise ClientErrorAttributes, "printer-current-time"
+
+def MultipleOperationTimeOut(val):
     """4.4.31 multiple-operation-time-out (integer(1:MAX))
 
@@ -598,10 +568,9 @@
     """
     
-    def __init__(self, val):
-        super(type(self), self).__init__(
-            'multiple-operation-time-out',
-            [Value(IntegerTags.INTEGER, val)])
-
-class CompressionSupported(Attribute):
+    return Attribute(
+        'multiple-operation-time-out',
+        [Value(IntegerTags.INTEGER, val)])
+
+def CompressionSupported(*vals):
     """4.4.32 compression-supported (1setOf type3 keyword)
 
@@ -623,47 +592,41 @@
     """
     
-    def __init__(self, *vals):
-        super(type(self), self).__init__(
-            'compression-supported',
-            [Value(CharacterStringTags.KEYWORD, val) for val in vals])
-
-class JobKOctetsSupported(Attribute):
+    return Attribute(
+        'compression-supported',
+        [Value(CharacterStringTags.KEYWORD, val) for val in vals])
+
+def JobKOctetsSupported(val):
     """4.4.33 job-k-octets-supported (rangeOfInteger(0:MAX))
 
     """
 
-    def __init__(self, val):
-        raise ClientErrorAttributes, "job-k-octets-supported"
-
-class JobImpressionsSupported(Attribute):
+    raise ClientErrorAttributes, "job-k-octets-supported"
+
+def JobImpressionsSupported(val):
     """4.4.34 job-impressions-supported (rangeOfInteger(0:MAX))
 
     """
 
-    def __init__(self, val):
-        raise ClientErrorAttributes, "job-impressions-supported"
-
-class JobMediaSheetsSupported(Attribute):
+    raise ClientErrorAttributes, "job-impressions-supported"
+
+def JobMediaSheetsSupported(val):
     """4.4.35 job-media-sheets-supported (rangeOfInteger(0:MAX))
 
     """
 
-    def __init__(self, val):
-        raise ClientErrorAttributes, "job-media-sheets-supported"
-
-class PagesPerMinute(Attribute):
+    raise ClientErrorAttributes, "job-media-sheets-supported"
+
+def PagesPerMinute(val):
     """4.4.36 pages-per-minute (integer(0:MAX))
 
     """
 
-    def __init__(self, val):
-        raise ClientErrorAttributes, "pages-per-minute"
-
-class PagesPerMinuteColor(Attribute):
+    raise ClientErrorAttributes, "pages-per-minute"
+
+def PagesPerMinuteColor(val):
     """4.4.37 pages-per-minute-color (integer(0:MAX))
 
     """
 
-    def __init__(self, val):
-        raise ClientErrorAttributes, "pages-per-minute-color"
-    
+    raise ClientErrorAttributes, "pages-per-minute-color"
+    
Index: server/lib/gutenbach/ipp/operations/__init__.py
===================================================================
--- server/lib/gutenbach/ipp/operations/__init__.py	(revision aded2d1280aa9d2333d252f6f2557cfa3b1b1cd1)
+++ server/lib/gutenbach/ipp/operations/__init__.py	(revision b828a96dac6143596be1f8d07d8f319288fde70d)
@@ -45,17 +45,20 @@
     # check charset
     charset_attr = op_attrs.attributes[0]
-    if charset_attr != object_attributes.AttributesCharset('utf-8'):
-        raise errors.ClientErrorBadRequest
+    expected = object_attributes.AttributesCharset('utf-8')
+    if charset_attr != expected:
+        raise errors.ClientErrorBadRequest("%s != %s" % (charset_attr, expected))
 
     # check for attributes-natural-language
     natlang_attr = op_attrs.attributes[1]
-    if natlang_attr != object_attributes.AttributesNaturalLanguage('en-us'):
-        raise errors.ClientErrorBadRequest
+    expected = object_attributes.AttributesNaturalLanguage('en-us')
+    if natlang_attr != expected:
+        raise errors.ClientErrorBadRequest("%s != %s" % (natlang_attr, expected))
 
     return dict([(attr.name, attr) for attr in op_attrs.attributes])
 
 def verify_printer_uri(uri_attr):
-    if uri_attr != object_attributes.PrinterUri(uri_attr.values[0].value):
-        raise errors.ClientErrorBadRequest
+    expected = object_attributes.PrinterUri(uri_attr.values[0].value)
+    if uri_attr != expected:
+        raise errors.ClientErrorBadRequest("%s != %s" % (uri_attr, expected))
     
     # actually get the printer name
@@ -67,6 +70,7 @@
 
 def verify_requesting_username(username_attr):
-    if username_attr != object_attributes.RequestingUserName(username_attr.values[0].value):
-        raise errors.ClientErrorBadRequest
+    expected = object_attributes.RequestingUserName(username_attr.values[0].value)
+    if username_attr != expected:
+        raise errors.ClientErrorBadRequest("%s != %s" % (username_attr, expected))
     return username_attr.values[0].value
 
@@ -121,6 +125,4 @@
 from validate_job import verify_validate_job_request, make_validate_job_response
 
-
-
 __all__ = ['verify_cups_get_classes_request', 'make_cups_get_classes_response'
            'verify_cups_get_default_request', 'make_cups_get_default_response'
Index: server/lib/gutenbach/ipp/value.py
===================================================================
--- server/lib/gutenbach/ipp/value.py	(revision 0c4f3bf680913d11872a61e37a8d01f84797e339)
+++ server/lib/gutenbach/ipp/value.py	(revision b828a96dac6143596be1f8d07d8f319288fde70d)
@@ -54,4 +54,8 @@
         self.tag = tag # one byte, the type of value
         self.value     = value     # non-binary value of self.value
+
+    def __cmp__(self, other):
+        eq = (self.value == other.value) and (self.tag == other.tag)
+        return 0 if eq else 1
 
     @classmethod
Index: server/lib/gutenbach/server/requests.py
===================================================================
--- server/lib/gutenbach/server/requests.py	(revision aded2d1280aa9d2333d252f6f2557cfa3b1b1cd1)
+++ server/lib/gutenbach/server/requests.py	(revision b828a96dac6143596be1f8d07d8f319288fde70d)
@@ -53,5 +53,5 @@
         except ipp.errors.IPPException:
             exctype, excval, exctb = sys.exc_info()
-            logger.error(traceback.format_exc())
+            logger.error("%s: %s" % (exctype.__name__, excval.message))
             response = ipp.ops.make_empty_response(request)
             excval.update_response(response)
@@ -86,10 +86,10 @@
         """
         
-        raise NotImplementedError
+        raise ipp.errors.ServerErrorOperationNotSupported
 
     @handler_for(consts.Operations.VALIDATE_JOB)
     def validate_job(self, request):
 
-        raise NotImplementedError
+        raise ipp.errors.ServerErrorOperationNotSupported
 
     @handler_for(consts.Operations.GET_JOBS)
@@ -129,5 +129,5 @@
     @handler_for(consts.Operations.PRINT_URI)
     def print_uri(self, request):
-        raise NotImplementedError
+        raise ipp.errors.ServerErrorOperationNotSupported
 
     @handler_for(consts.Operations.CREATE_JOB)
@@ -181,13 +181,13 @@
         """
 
-        raise NotImplementedError
+        raise ipp.errors.ServerErrorOperationNotSupported
     
     @handler_for(consts.Operations.PAUSE_PRINTER)
     def pause_printer(self, request):
-        raise NotImplementedError
+        raise ipp.errors.ServerErrorOperationNotSupported
 
     @handler_for(consts.Operations.RESUME_PRINTER)
     def resume_printer(self, request):
-        raise NotImplementedError
+        raise ipp.errors.ServerErrorOperationNotSupported
 
     @handler_for(consts.Operations.GET_PRINTER_ATTRIBUTES)
@@ -252,5 +252,5 @@
     @handler_for(consts.Operations.SET_PRINTER_ATTRIBUTES)
     def set_printer_attributes(self, request):
-        raise NotImplementedError
+        raise ipp.errors.ServerErrorOperationNotSupported
 
     ##### Job Commands
@@ -258,13 +258,13 @@
     @handler_for(consts.Operations.CANCEL_JOB)
     def cancel_job(self, request):
-        raise NotImplementedError
+        raise ipp.errors.ServerErrorOperationNotSupported
 
     @handler_for(consts.Operations.SEND_DOCUMENT)
     def send_document(self, request):
-        raise NotImplementedError
+        raise ipp.errors.ServerErrorOperationNotSupported
 
     @handler_for(consts.Operations.SEND_URI)
     def send_uri(self, request):
-        raise NotImplementedError
+        raise ipp.errors.ServerErrorOperationNotSupported
 
     @handler_for(consts.Operations.GET_JOB_ATTRIBUTES)
@@ -297,13 +297,13 @@
     @handler_for(consts.Operations.SET_JOB_ATTRIBUTES)
     def set_job_attributes(self, request):
-        raise NotImplementedError
+        raise ipp.errors.ServerErrorOperationNotSupported
 
     @handler_for(consts.Operations.RESTART_JOB)
     def restart_job(self, request):
-        raise NotImplementedError
+        raise ipp.errors.ServerErrorOperationNotSupported
 
     @handler_for(consts.Operations.PROMOTE_JOB)
     def promote_job(self, request):
-        raise NotImplementedError
+        raise ipp.errors.ServerErrorOperationNotSupported
 
     ##### CUPS Specific Commands
@@ -311,5 +311,5 @@
     @handler_for(consts.Operations.CUPS_GET_DOCUMENT)
     def cups_get_document(self, request):
-        raise NotImplementedError
+        raise ipp.errors.ServerErrorOperationNotSupported
 
     @handler_for(consts.Operations.CUPS_GET_DEFAULT)
