word(), widget=IPPAttributeWidget())

    timeout = colander.SchemaNode(
        colander.Integer(),
        widget=IPPAttributeWidget())

    first_printer_name = colander.SchemaNode(
        Name(),
        widget=IPPAttributeWidget())
    printer_location = colander.SchemaNode(
        Text(),
        widget=IPPAttributeWidget())
    printer_type = colander.SchemaNode(Enum(), widget=IPPAttributeWidget())
    printer_type_mask = colander.SchemaNode(
        Enum(),
        widget=IPPAttributeWidget())
    requested_attributes = colander.SchemaNode(
        Keyword(),
        widget=IPPAttributeWidget())
    requested_user_name = colander.SchemaNode(Name(),
                                              widget=IPPAttributeWidget())

    document_name = colander.SchemaNode(Name(), widget=IPPAttributeWidget())
    compression = colander.SchemaNode(Keyword(), widget=IPPAttributeWidget())
    document_format = colander.SchemaNode(MimeMediaType(),
                                          widget=IPPAttributeWidget())
    document_natural_language = colander.SchemaNode(
        NaturalLanguage(),
        widget=IPPAttributeWidget())
    last_document = colander.SchemaNode(
        colander.Boolean(false_val=0, true_val=1),
        widget=IPPAttributeWidget())


class JobAttributesGroup(colander.Schema):
    job_priority = colander.SchemaNode(Integer(),
                                       widget=IPPAttributeWidget())
    job_printer_uri = colander.SchemaNode(Uri(),
                                          widget=IPPAttributeWidget())
    job_hold_until = colander.SchemaNode(Keyword(),
                                         widget=IPPAttributeWidget())
    job_sheets = colander.SchemaNode(Keyword(), widget=IPPAttributeWidget())
    auth_info = colander.SchemaNode(Text(), widget=IPPAttributeWidget())
    job_billing = colander.SchemaNode(Text(), widget=IPPAttributeWidget())
    multiple_document_handling = colander.SchemaNode(
        Keyword(),
        widget=IPPAttributeWidget())
    copies = colander.SchemaNode(Integer(), widget=IPPAttributeWidget())
    finishings = colander.SchemaNode(Enum(), widget=IPPAttributeWidget())
    page_ranges = colander.SchemaNode(RangeOfInteger(),
                                      widget=IPPAttributeWidget(),
                                      validator=range_of_integer_validator)
    sides = colander.SchemaNode(Keyword(), widget=IPPAttributeWidget())
    number_up = colander.SchemaNode(Integer(), widget=IPPAttributeWidget())
    orientation_requested = colander.SchemaNode(Enum(),
                                                widget=IPPAttributeWidget())
    media = colander.SchemaNode(Keyword(), widget=IPPAttributeWidget())
    printer_resolution = colander.SchemaNode(Resolution(),
                                             widget=IPPAttributeWidget())
    print_quality = colander.SchemaNode(Enum(), widget=IPPAttributeWidget())

    # Arbitrary Job Attributes
    ezeep_job_uuid = colander.SchemaNode(Text(),
                                         widget=IPPAttributeWidget())


class SubscriptionGroup(colander.Schema):
    notify_recipient_uri = colander.SchemaNode(Uri(),
                                               widget=IPPAttributeWidget())
    notify_events = colander.SchemaNode(Keyword(),
                                        widget=IPPAttributeWidget())
    notify_job_id = colander.SchemaNode(colander.Integer(),
                                        widget=IPPAttributeWidget())
    notify_pull_method = colander.SchemaNode(Keyword(),
                                             widget=IPPAttributeWidget())
    notify_attributes = colander.SchemaNode(Keyword(),
                                            widget=IPPAttributeWidget())
    notify_charset = colander.SchemaNode(Charset(),
                                         widget=IPPAttributeWidget())
    notify_natural_language = colander.SchemaNode(Language(),
                                                  widget=IPPAttributeWidget())
    notify_time_interval = colander.SchemaNode(colander.Integer(),
                                               widget=IPPAttributeWidget())
    notify_lease_duration = colander.SchemaNode(colander.Integer(),
                                                widget=IPPAttributeWidget())


class DocumentAttributesGroup(colander.Schema):
    file = colander.SchemaNode(colander.String(), widget=IPPFileWidget())


class PrinterAttributesGroup(colander.Schema):
    auth_info_required = colander.SchemaNode(Keyword(),
                                             widget=IPPAttributeWidget())

    printer_is_accepting_jobs = colander.SchemaNode(
        colander.Boolean(false_val=0, true_val=1),
        widget=IPPAttributeWidget())
    printer_info = colander.SchemaNode(Text(), widget=IPPAttributeWidget())
    printer_location = colander.SchemaNode(Text(), widget=IPPAttributeWidget())
    printer_more_info = colander.SchemaNode(Uri(), widget=IPPAttributeWidget())
    printer_op_policy = colander.SchemaNode(Name(),
                                            widget=IPPAttributeWidget())
    printer_state = colander.SchemaNode(Enum(), widget=IPPAttributeWidget())
    printer_state_message = colander.SchemaNode(
        Text(),
        widget=IPPAttributeWidget())
    requesting_user_name_allowed = colander.SchemaNode(
        Name(),
        widget=IPPAttributeWidget())
    requesting_user_name_denied = colander.SchemaNode(
        Name(),
        widget=IPPAttributeWidget())
    printer_is_shared = colander.SchemaNode(colander.Boolean(true_val=1,
                                                             false_val=0),
                                            widget=IPPAttributeWidget())
    job_sheets_default = colander.SchemaNode(Name(),
                                             widget=IPPAttributeWidget())
    device_uri = colander.SchemaNode(Uri(),
                                     widget=IPPAttributeWidget())
    port_monitor = colander.SchemaNode(Name(), widget=IPPAttributeWidget())
    ppd_name = colander.SchemaNode(Name(), widget=IPPAttributeWidget())
    member_uris = colander.SchemaNode(Uri(), widget=IPPAttributeWidget())

    # Always last
    file = colander.SchemaNode(colander.String(), widget=IPPFileWidget())


class BaseIPPSchema(colander.Schema):
    name = colander.SchemaNode(colander.String(), widget=IPPNameWidget())
    operation = colander.SchemaNode(colander.String(), widget=IPPNameWidget())
    operation_attributes_tag = OperationAttributesGroup(
        widget=IPPGroupWidget())


class CancelJobSchema(BaseIPPSchema):
    name = 'Cancel Job'
    operation = 'Cancel-Job'


class ReleaseJobSchema(BaseIPPSchema):
    name = 'Release Job'
    operation = 'Release-Job'


class CupsAddModifyPrinterSchema(BaseIPPSchema):
    name = 'CUPS Add Modify Printer'
    operation = 'CUPS-Add-Modify-Printer'
    printer_attributes_tag = PrinterAttributesGroup(widget=IPPGroupWidget())


class CupsDeletePrinterSchema(BaseIPPSchema):
    name = 'CUPS Delete Printer'
    operation = 'CUPS-Delete-Printer'


class CupsAddModifyClassSchema(BaseIPPSchema):
    name = 'CUPS Add Modify Class'
    operation = 'CUPS-Add-Modify-Class'
    printer_attributes_tag = PrinterAttributesGroup(widget=IPPGroupWidget())


class CupsDeleteClassSchema(CupsDeletePrinterSchema):
    name = 'CUPS Delete Class'
    operation = 'CUPS-Delete-Class'


class CupsGetClassesSchema(BaseIPPSchema):
    name = 'CUPS Get Classes'
    operation = 'CUPS-Get-Classes'


class CupsGetDevicesSchema(BaseIPPSchema):
    name = 'CUPS Get Devices'
    operation = 'CUPS-Get-Devices'


class CupsGetPPDSchema(BaseIPPSchema):
    name = 'CUPS Get PPD'
    operation