Package pyffi :: Package object_models :: Package xml :: Module enum
[hide private]
[frames] | no frames]

Source Code for Module pyffi.object_models.xml.enum

  1  """Abstract base class for implementing xml enum types.""" 
  2   
  3  # ***** BEGIN LICENSE BLOCK ***** 
  4  # 
  5  # Copyright (c) 2007-2011, Python File Format Interface 
  6  # All rights reserved. 
  7  # 
  8  # Redistribution and use in source and binary forms, with or without 
  9  # modification, are permitted provided that the following conditions 
 10  # are met: 
 11  # 
 12  #    * Redistributions of source code must retain the above copyright 
 13  #      notice, this list of conditions and the following disclaimer. 
 14  # 
 15  #    * Redistributions in binary form must reproduce the above 
 16  #      copyright notice, this list of conditions and the following 
 17  #      disclaimer in the documentation and/or other materials provided 
 18  #      with the distribution. 
 19  # 
 20  #    * Neither the name of the Python File Format Interface 
 21  #      project nor the names of its contributors may be used to endorse 
 22  #      or promote products derived from this software without specific 
 23  #      prior written permission. 
 24  # 
 25  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 26  # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 27  # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
 28  # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
 29  # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
 30  # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
 31  # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
 32  # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
 33  # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
 34  # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
 35  # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
 36  # POSSIBILITY OF SUCH DAMAGE. 
 37  # 
 38  # ***** END LICENSE BLOCK ***** 
 39   
 40  import logging 
 41  import struct 
 42  from itertools import izip 
 43   
 44  from pyffi.object_models.xml.basic import BasicBase 
 45  from pyffi.object_models.editable import EditableComboBox 
 46   
47 -class _MetaEnumBase(type):
48 """This metaclass checks for the presence of _enumkeys, _enumvalues, 49 and _numbytes attributes. It also adds enum class attributes. 50 51 Used as metaclass of EnumBase."""
52 - def __init__(cls, name, bases, dct):
53 super(_MetaEnumBase, cls).__init__(name, bases, dct) 54 # consistency checks 55 if not '_enumkeys' in dct: 56 raise TypeError('%s: missing _enumkeys attribute'%cls) 57 if not '_enumvalues' in dct: 58 raise TypeError('%s: missing _enumvalues attribute'%cls) 59 if not '_numbytes' in dct: 60 raise TypeError('%s: missing _numbytes attribute'%cls) 61 62 # check storage type 63 if cls._numbytes == 1: 64 cls._struct = 'B' 65 elif cls._numbytes == 2: 66 cls._struct = 'H' 67 elif cls._numbytes == 4: 68 cls._struct = 'I' 69 else: 70 raise RuntimeError("unsupported enum numbytes") 71 72 # template type? 73 cls._is_template = False 74 # does the type contain a Ref or a Ptr? 75 cls._has_links = False 76 # does the type contain a Ref? 77 cls._has_refs = False 78 # does the type contain a string? 79 cls._has_strings = False 80 81 # for other read/write checking 82 cls._min = 0 83 cls._max = (1 << (cls._numbytes * 8)) - 1 84 85 # set enum values as class attributes 86 for item, value in izip(cls._enumkeys, cls._enumvalues): 87 setattr(cls, item, value)
88
89 -class EnumBase(BasicBase, EditableComboBox):
90 __metaclass__ = _MetaEnumBase 91 _enumkeys = [] 92 _enumvalues = [] 93 _numbytes = 1 # default width of an enum 94 95 # 96 # BasicBase methods 97 # 98
99 - def __init__(self, **kwargs):
100 super(EnumBase, self).__init__(**kwargs) 101 self._value = self._enumvalues[0]
102
103 - def get_value(self):
104 """Return stored value.""" 105 return self._value
106
107 - def set_value(self, value):
108 """Set value to C{value}.""" 109 try: 110 val = int(value) 111 except ValueError: 112 try: 113 val = int(value, 16) # for '0x...' strings 114 except ValueError: 115 if value in self._enumkeys: 116 val = getattr(self, value) 117 else: 118 raise ValueError( 119 "cannot convert value '%s' to integer"%value) 120 if not val in self._enumvalues: 121 logger = logging.getLogger("pyffi.object_models.xml.enum") 122 logger.error('invalid enum value (%i)' % val) 123 else: 124 self._value = val
125
126 - def read(self, stream, data):
127 """Read value from stream.""" 128 self._value = struct.unpack(data._byte_order + self._struct, 129 stream.read(self._numbytes))[0]
130
131 - def write(self, stream, data):
132 """Write value to stream.""" 133 stream.write(struct.pack(data._byte_order + self._struct, 134 self._value))
135
136 - def __str__(self):
137 try: 138 return self._enumkeys[self._enumvalues.index(self.get_value())] 139 except ValueError: 140 # not in _enumvalues list 141 return "<INVALID (%i)>" % self.get_value()
142
143 - def get_size(self, data=None):
144 """Return size of this type.""" 145 return self._numbytes
146
147 - def get_hash(self, data=None):
148 """Return a hash value for this value.""" 149 return self.get_value()
150 151 # 152 # EditableComboBox methods 153 # 154
155 - def get_editor_keys(self):
156 """List or tuple of strings, each string describing an item.""" 157 return self._enumkeys
158
159 - def set_editor_value(self, index):
160 """Set value from item index.""" 161 self.set_value(self._enumvalues[index])
162
163 - def get_editor_value(self):
164 """Get the item index from the enum value.""" 165 return self._enumvalues.index(self._value)
166
167 - def get_detail_display(self):
168 """Return object that can be used to display the instance.""" 169 try: 170 return self._enumkeys[self._enumvalues.index(self._value)] 171 except ValueError: 172 # value self._value is not in the self._enumvalues list 173 return "<INVALID (0x%08X)>" % self._value
174