Changeset fa0d0ef


Ignore:
Timestamp:
Mar 7, 2011, 9:03:02 PM (13 years ago)
Author:
Jessica B. Hamrick <jhamrick@…>
Branches:
no-cups
Children:
fc427ef
Parents:
c269bc7
git-author:
Jessica B. Hamrick <jhamrick@…> (03/07/11 21:03:02)
git-committer:
Jessica B. Hamrick <jhamrick@…> (03/07/11 21:03:02)
Message:

Redo API in ippvalue.Value; various cases for packing/unpacking have not yet been tested

File:
1 edited

Legend:

Unmodified
Added
Removed
  • server/lib/ippvalue.py

    rc269bc7 rfa0d0ef  
    77logger = logging.getLogger("ippLogger")
    88
    9 class Value():
     9class Value(object):
    1010    """
    1111    An IPP value consists of a tag and a value.
     
    2323    """
    2424
    25     def __init__(self, value_tag=None, value=None, unpack=True):
     25    def __init__(self, value_tag=None, value=None):
    2626        """
    2727        Initialize a Value.  There are three different ways you can
     
    3131
    3232            Value(value_tag, value) -- creates a Value instance from
    33             binary values
    34 
    35             Value(value_tag, value, unpack=False) -- creates a Value
    36             instance from non-binary values
     33            a non-binary value
    3734
    3835        If you create an empty Value instance, once you have set
    39         value_tag and value, you should call pack(), or if you set
    40         value_tag and binary_value, call unpack().
     36        value_tag and value, you can retrieve the packed value from
     37        the packed_value property.
    4138
    4239        Arguments:
     
    4441            value_tag -- one byte, identifying the type of value
    4542
    46             value -- variable size, containing the actual value.  If
    47             unpack is True, then this should be a binary value,
    48             otherwise it should be a string or number.
    49 
    50             unpack -- boolean which indicates whether the value passed
    51             in is binary (i.e., should be unpacked) or not (i.e., does
    52             not need to be unpacked)
     43            value -- variable size, containing the actual value.
     44            It should be a string or number.
    5345        """
    5446
    5547        # make sure the arguments are valid
    56         if value_tag is not None:
    57             assert value is not None, \
    58                    "value must not be null because " + \
    59                    "value_tag is not null!"
    60         elif value_tag is None:
    61             assert value is None, \
    62                    "value must be null because value_tag is null!"
     48        if value is not None:
     49            assert value_tag is not None, \
     50                   "value_tag must not be null because " + \
     51                   "value is not null!"
    6352
    6453        # initialize member variables
    65         self.value_tag    = None # one byte, the type of value
    66         self.value        = None # non-binary value of self.value
    67         self.tag_size     = 1    # length of the tag in bytes
    68         self.value_size   = None # size of self.value in bytes
    69         self.binary_value = None # binary value of self.value
    70 
    71         if value_tag is not None and value is not None:
    72             if unpack:
    73                 self.value_tag = value_tag
    74                 self.binary_value = value
    75                 self.value_size, self.value = self.unpack()
    76             else:
    77                 self.value_tag = value_tag
    78                 self.value = value
    79                 self.value_size, self.binary_value = self.pack()
    80 
    81             self.verify()
    82 
    83     def unpack(self):
    84         """
    85         Given self.value_tag and self.binary_value, unpack the binary
     54        self.value_tag = value_tag # one byte, the type of value
     55        self.value     = value     # non-binary value of self.value
     56
     57    @classmethod
     58    def unpack(cls, value_tag, packed_value):
     59        """Unpack a binary IPP value
     60
     61        Unpacks a binary string into a Value object.
     62
     63        """
     64        return cls(value_tag, cls._unpack(value_tag, packed_value))
     65
     66    @staticmethod
     67    def _unpack(value_tag, packed_value):
     68        """
     69        Given self.value_tag and self.packed_value, unpack the binary
    8670        value into either a string or number.  These values MUST NOT
    87         be null.  Furthermore, if self.value and self.value_size are
    88         set, this method will check to make sure that unpacking
    89         self.binary_value matches up.
    90 
    91         Returns: tuple of (value_size, value)
    92         """
    93 
    94         assert self.value_tag is not None, \
     71        be null.
     72
     73        Returns: unpacked value
     74
     75        """
     76
     77        assert value_tag is not None, \
    9578               "Cannot unpack values with unspecified value tag!"
    96         assert self.binary_value is not None, \
     79        assert packed_value is not None, \
    9780               "Cannot unpack null values!"
    9881
    99         value_size = None
    10082        value = None
    10183
    10284        # out-of-band value tags
    103         if self.value_tag == OutOfBandTags.UNSUPPORTED or \
    104                self.value_tag == OutOfBandTags.DEFAULT or \
    105                self.value_tag == OutOfBandTags.UNKNOWN or \
    106                self.value_tag == OutOfBandTags.NO_VALUE:
     85        if value_tag == OutOfBandTags.UNSUPPORTED or \
     86               value_tag == OutOfBandTags.DEFAULT or \
     87               value_tag == OutOfBandTags.UNKNOWN or \
     88               value_tag == OutOfBandTags.NO_VALUE:
    10789            value_size = 0
    10890            value = ''
    10991
    11092        # integer value tags
    111         elif self.value_tag == IntegerTags.INTEGER:
    112             value_size = 4
    113             value = struct.unpack('>i', self.binary_value)[0]
    114         elif self.value_tag == IntegerTags.BOOLEAN:
    115             value_size = 1
    116             value = struct.unpack('>?', self.binary_value)[0]
    117         elif self.value_tag == IntegerTags.ENUM:
    118             value_size = 4
    119             value = struct.unpack('>i', self.binary_value)[0]
     93        elif value_tag == IntegerTags.INTEGER:
     94            value = struct.unpack('>i', packed_value)[0]
     95        elif value_tag == IntegerTags.BOOLEAN:
     96            value = struct.unpack('>?', packed_value)[0]
     97        elif value_tag == IntegerTags.ENUM:
     98            value = struct.unpack('>i', packed_value)[0]
    12099
    121100       
    122         elif self.value_tag == OctetStringTags.DATETIME:
     101        elif value_tag == OctetStringTags.DATETIME:
    123102            # field  octets  contents                  range
    124103            # -----  ------  --------                  -----
     
    135114            #  10      11    minutes from UTC          0..59
    136115
    137             value_size = 11
    138             value = struct.unpack('>hbbbbbbcbb', self.binary_value)[0]
    139            
    140         elif self.value_tag == OctetStringTags.RESOLUTION:
     116            value = struct.unpack('>hbbbbbbcbb', packed_value)
     117           
     118        elif value_tag == OctetStringTags.RESOLUTION:
    141119            # OCTET-STRING consisting of nine octets of 2
    142120            # SIGNED-INTEGERs followed by a SIGNED-BYTE. The first
     
    146124            # contains the units
    147125
    148             value_size = 9
    149             value = struct.unpack('>iib', self.binary_value)
    150            
    151         elif self.value_tag == OctetStringTags.RANGE_OF_INTEGER:
     126            value = struct.unpack('>iib', packed_value)
     127           
     128        elif value_tag == OctetStringTags.RANGE_OF_INTEGER:
    152129            # Eight octets consisting of 2 SIGNED-INTEGERs.  The first
    153130            # SIGNED-INTEGER contains the lower bound and the second
    154131            # SIGNED-INTEGER contains the upper bound.
    155132
    156             value_size = 8
    157             value = struct.unpack('>ii', self.binary_value)
    158 
    159         elif self.value_tag == OctetStringTags.TEXT_WITH_LANGUAGE or \
    160                  self.value_tag == OctetStringTags.NAME_WITH_LANGUAGE:
    161             a = struct.unpack('>h', self.binary_value[:2])[0]
    162             b = struct.unpack('>%ss' % a, self.binary_value[2:a+2])[0]
    163             c = struct.unpack('>h', self.binary_value[a+2:a+4])[0]
    164             d = struct.unpack('>%ss' % c, self.binary_value[a+4:][0])
    165             value_size = 4 + a + c
     133            value = struct.unpack('>ii', packed_value)
     134
     135        elif value_tag == OctetStringTags.TEXT_WITH_LANGUAGE or \
     136                 value_tag == OctetStringTags.NAME_WITH_LANGUAGE:
     137            a = struct.unpack('>h', packed_value[:2])[0]
     138            b = struct.unpack('>%ss' % a, packed_value[2:a+2])[0]
     139            c = struct.unpack('>h', packed_value[a+2:a+4])[0]
     140            d = struct.unpack('>%ss' % c, packed_value[a+4:][0])
    166141            value = (a, b, c, d)
    167142
    168143        # character string value tags
    169         elif self.value_tag == \
     144        elif value_tag == \
    170145                 CharacterStringTags.TEXT_WITHOUT_LANGUAGE or \
    171                  self.value_tag == \
     146                 value_tag == \
    172147                 CharacterStringTags.NAME_WITHOUT_LANGUAGE:
    173             value_size = len(str(self.binary_value))
    174             value = str(self.binary_value)
    175         elif self.value_tag == CharacterStringTags.GENERIC or \
    176                  self.value_tag == CharacterStringTags.KEYWORD or \
    177                  self.value_tag == CharacterStringTags.URI or \
    178                  self.value_tag == CharacterStringTags.URI_SCHEME or \
    179                  self.value_tag == CharacterStringTags.CHARSET or \
    180                  self.value_tag == CharacterStringTags.NATURAL_LANGUAGE or \
    181                  self.value_tag == CharacterStringTags.MIME_MEDIA_TYPE:
    182             value_size = len(str(self.binary_value))
    183             value = str(self.binary_value)
     148            value = str(packed_value)
     149        elif value_tag == CharacterStringTags.GENERIC or \
     150                 value_tag == CharacterStringTags.KEYWORD or \
     151                 value_tag == CharacterStringTags.URI or \
     152                 value_tag == CharacterStringTags.URI_SCHEME or \
     153                 value_tag == CharacterStringTags.CHARSET or \
     154                 value_tag == CharacterStringTags.NATURAL_LANGUAGE or \
     155                 value_tag == CharacterStringTags.MIME_MEDIA_TYPE:
     156            value = str(packed_value)
    184157
    185158        # anything else that we didn't handle
    186159        else:
    187             if value_size is None and value is None:
    188                 value_size = len(self.binary_value)
    189                 value = self.binary_value
    190 
    191         if self.value_size is not None:
    192             assert value_size == self.value_size, \
    193                    "unpacked value_size is not the same " + \
    194                    "as self.value_size!"
    195         if self.value is not None:
    196             assert value == self.value, \
    197                    "unpacked value is not the same as self.value!"
    198 
    199         return value_size, value
    200 
    201     def pack(self):
     160            if value is None:
     161                value = packed_value
     162
     163        return value
     164
     165    @property
     166    def packed_value(self):
    202167        """
    203168        Given self.value_tag and self.value, pack the value into
    204         binary formo.  These values MUST NOT be null.  Furthermore, if
    205         self.binary_value and self.value_size are set, this method
    206         will check to make sure that packing self.value matches up.
    207 
    208         Returns: tuple of (value_size, binary_value)
     169        binary form.  These values MUST NOT be null.
     170
     171        Returns: packed_value
     172
    209173        """
    210174       
     
    214178               "cannot pack null value!"
    215179
    216         value_size = None
    217         binary_value = None
     180        packed_value = None
    218181
    219182        # out-of-band value tags
     
    222185               self.value_tag == OutOfBandTags.UNKNOWN or \
    223186               self.value_tag == OutOfBandTags.NO_VALUE:
    224             value_size = 0
    225             binary_value = ''
     187            packed_value = ''
    226188
    227189        # integer value tags
    228190        elif self.value_tag == IntegerTags.INTEGER:
    229             value_size = 4
    230             binary_value = struct.pack('>i', self.value)
     191            packed_value = struct.pack('>i', self.value)
    231192        elif self.value_tag == IntegerTags.BOOLEAN:
    232             value_size = 1
    233             binary_value = struct.pack('>?', self.value)
     193            packed_value = struct.pack('>?', self.value)
    234194        elif self.value_tag == IntegerTags.ENUM:
    235             value_size = 4
    236             binary_value = struct.pack('>i', self.value)
     195            packed_value = struct.pack('>i', self.value)
    237196
    238197        # octet string value tags
     
    252211            #  10      11    minutes from UTC          0..59
    253212
    254             value_size = 11
    255             binary_value = struct.pack('>hbbbbbbcbb', self.value)
     213            packed_value = struct.pack('>hbbbbbbcbb', *self.value)
    256214           
    257215        elif self.value_tag == OctetStringTags.RESOLUTION:
     
    263221            # contains the units
    264222
    265             value_size = 9
    266             binary_value = truct.pack('>iib', self.value)
     223            packed_value = truct.pack('>iib', self.value)
    267224           
    268225        elif self.value_tag == OctetStringTags.RANGE_OF_INTEGER:
     
    271228            # SIGNED-INTEGER contains the upper bound.
    272229
    273             value_size = 8
    274             binary_value = struct.pack('>ii', self.value)
     230            packed_value = struct.pack('>ii', self.value)
    275231
    276232        elif self.value_tag == OctetStringTags.TEXT_WITH_LANGUAGE or \
     
    282238            d_bin = struct.pack('>%ss' % self.value[2], self.value[3])
    283239
    284             value_size = 4 + self.value[0] + self.value[2]
    285             binary_value = a_bin + b_bin + c_bin + d_bin
     240            packed_value = a_bin + b_bin + c_bin + d_bin
    286241
    287242        # character string value tags
     
    291246                 CharacterStringTags.NAME_WITHOUT_LANGUAGE:
    292247
    293             value_size = len(self.value)
    294             binary_value = struct.pack('>%ss' % len(self.value),
     248            packed_value = struct.pack('>%ss' % len(self.value),
    295249                                       self.value)
    296250                   
     
    303257                 self.value_tag == CharacterStringTags.MIME_MEDIA_TYPE:
    304258           
    305             value_size = len(self.value)
    306             binary_value = struct.pack('>%ss' % len(self.value),
     259            packed_value = struct.pack('>%ss' % len(self.value),
    307260                                       self.value)
    308261
    309262        else:
    310             value_size = len(self.value)
    311             binary_value = self.value
    312 
    313         return value_size, binary_value
    314 
    315     def verify(self):
    316         """
    317         Verifies that the binary and non-binary values for this Value
    318         instance line up.  All of self.value, self.binary_value,
    319         self.value_size, and self.value_tag must be defined.
    320 
    321         This function will throw an assertion error if the Value
    322         instance is not valid.
    323         """
    324 
    325         assert self.value is not None, \
    326                "value is null!"
    327         assert self.binary_value is not None, \
    328                "binary value is null!"
    329         assert self.value_size is not None, \
    330                "value size is unknown!"
    331         assert self.value_tag is not None, \
    332                "value type is unknown!"
    333 
    334         value_size1, binary_value = self.pack()
    335         value_size2, value = self.unpack()
    336 
    337         assert value_size1 == value_size2, \
    338                "packed value size is not the same as " + \
    339                "unpacked value size!"
    340         assert value_size == self.value_size, \
    341                "packed value size is not the same as " + \
    342                "self.value_size!"
    343         assert binary_value == self.binary_value, \
    344                "packed binary value is not the same as " + \
    345                "self.binary_value!"
    346 
    347     def getValue(self):
    348         """
    349         Get the non-binary value.
    350         """
    351 
    352         return self.value
    353 
    354     def getBinaryValue(self):
    355         """
    356         Get the binary value.
     263            packed_value = self.value
     264
     265        return packed_value
     266
     267    @packed_value.setter
     268    def set_packed_value(self, packed_value):
     269        """Replace a value using a new packed value
     270
     271        Unpacks a new packed_value (of the same value_tag).
     272
     273        """
     274        self.value = self._unpack(self.value_tag, packed_value)
     275
     276    @property
     277    def packed_value_size(self):
     278        """
     279        Get the size of the value in bytes.
    357280        """
    358281       
    359         return self.binary_value
    360 
    361     def getValueTag(self):
    362         """
    363         Get the value tag (type of value). This is an integer
    364         corresponding to a value in ippconstants.
    365         """
    366        
    367         return self.value_tag
    368 
    369     def getValueSize(self):
    370         """
    371         Get the size of the value in bytes.
    372         """
    373        
    374         return self.value_size
    375 
    376     def getTagSize(self):
    377         """
    378         Get the size of the value tag in bytes.
    379         """
    380 
    381         return self.tag_size
    382 
    383     def setValue(self, value):
    384         """
    385         Set the non-binary value.
    386         """
    387 
    388         self.value = value
    389 
    390     def setBinaryValue(self, binary_value):
    391         """
    392         Set the binary value.
    393         """
    394 
    395         self.binary_value = binary_value
    396 
    397     def setValueTag(self, value_tag):
    398         """
    399         Set the type (tag) of the value.  This should correspond to an
    400         integer defined in ippconstants.
    401         """
    402        
    403         self.value_tag = value_tag
    404 
    405     def setValueSize(self, size):
    406         """
    407         Set the size of the value in bytes.
    408         """
    409        
    410         self.value_size = size
    411 
    412     def getTotalSize(self):
     282        return len(self.packed_value)
     283
     284    @property
     285    def total_size(self):
    413286        """
    414287        Get the total size of the IPP value.
    415288        """
    416289
    417         return self.value_size + self.tag_size
     290        # 1 byte for the tag
     291        return self.packed_value_size + 1
    418292
    419293    def __str__(self):
    420         return self.value
     294        return str(self.value)
     295
     296    def __repr__(self):
     297        return '<IPPValue (%r, %r)>' % (self.value_tag, self.value)
Note: See TracChangeset for help on using the changeset viewer.