def prettyIn(self, value): """Dotted -> tuple of numerics OID converter""" if isinstance(value, tuple): pass elif isinstance(value, ObjectIdentifier): return tuple(value) elif octets.isStringType(value): r = [] for element in [ x for x in value.split('.') if x != '' ]: try: r.append(int(element, 0)) except ValueError: raise error.PyAsn1Error( 'Malformed Object ID %s at %s: %s' % (str(value), self.__class__.__name__, sys.exc_info()[1]) ) value = tuple(r) else: try: value = tuple(value) except TypeError: raise error.PyAsn1Error( 'Malformed Object ID %s at %s: %s' % (str(value), self.__class__.__name__,sys.exc_info()[1]) ) for x in value: if not isinstance(x, intTypes) or x < 0: raise error.PyAsn1Error( 'Invalid sub-ID in %s at %s' % (value, self.__class__.__name__) ) return value
def prettyIn(self, value): """Dotted -> tuple of numerics OID converter""" if isinstance(value, tuple): pass elif isinstance(value, ObjectIdentifier): return tuple(value) elif octets.isStringType(value): r = [] for element in [ x for x in value.split('.') if x != '' ]: try: r.append(int(element, 0)) except ValueError: raise error.PyAsn1Error( 'Malformed Object ID %s at %s: %s' % (str(value), self.__class__.__name__, sys.exc_info()[1]) ) value = tuple(r) else: try: value = tuple(value) except TypeError: raise error.PyAsn1Error( 'Malformed Object ID %s at %s: %s' % (str(value), self.__class__.__name__,sys.exc_info()[1]) ) for x in value: if not isinstance(x, intTypes) or x < 0: raise error.PyAsn1Error( 'Invalid sub-ID in %s at %s' % (value, self.__class__.__name__) ) return value
def prettyIn(self, value): if isinstance(value, RelativeOID): return tuple(value) elif isStringType(value): if '-' in value: raise error.PyAsn1Error( 'Malformed RELATIVE-OID %s at %s: %s' % (value, self.__class__.__name__, sys.exc_info()[1])) try: return tuple( [int(subOid) for subOid in value.split('.') if subOid]) except ValueError: raise error.PyAsn1Error( 'Malformed RELATIVE-OID %s at %s: %s' % (value, self.__class__.__name__, sys.exc_info()[1])) try: tupleOfInts = tuple( [int(subOid) for subOid in value if subOid >= 0]) except (ValueError, TypeError): raise error.PyAsn1Error( 'Malformed RELATIVE-OID %s at %s: %s' % (value, self.__class__.__name__, sys.exc_info()[1])) if len(tupleOfInts) == len(value): return tupleOfInts raise error.PyAsn1Error('Malformed RELATIVE-OID %s at %s' % (value, self.__class__.__name__))
def prettyIn(self, value): # override asn1 type method """Implements DISPLAY-HINT parsing into base SNMP value Proper parsing seems impossible due to ambiguities. Here we are trying to do our best, but be prepared for failures on complicated DISPLAY-HINTs. Keep in mind that this parser only works with "text" input meaning `unicode` (Py2) or `str` (Py3). """ for base in inspect.getmro(self.__class__): if not issubclass(base, TextualConvention) and issubclass( base, Asn1Item): break else: raise SmiError( 'TEXTUAL-CONVENTION has no underlying SNMP base type') if self.displayHint and ( self.__integer.isSuperTypeOf(self, matchConstraints=False) and self.getNamedValues() or self.__unsigned32.isSuperTypeOf( self, matchConstraints=False) or self.__timeticks.isSuperTypeOf(self, matchConstraints=False)): value = str(value) _ = lambda t, f=0: (t, f) displayHintType, decimalPrecision = _(*self.displayHint.split('-')) if displayHintType == 'x' and (value.startswith('0x') or value.startswith('-0x')): try: if value.startswith('-'): return base.prettyIn(self, -int(value[3:], 16)) else: return base.prettyIn(self, int(value[2:], 16)) except Exception: raise SmiError('integer evaluation error: %s' % sys.exc_info()[1]) elif displayHintType == 'd': try: return base.prettyIn( self, int(float(value) * 10**int(decimalPrecision))) except Exception: raise SmiError('float evaluation error: %s' % sys.exc_info()[1]) elif displayHintType == 'o' and (value.startswith('0') or value.startswith('-0')): try: return base.prettyIn(self, int(value, 8)) except Exception: raise SmiError('octal evaluation error: %s' % sys.exc_info()[1]) elif displayHintType == 'b' and (value.startswith('B') or value.startswith('-B')): negative = value.startswith('-') if negative: value = value[2:] else: value = value[1:] value = [x != '0' and 1 or 0 for x in value] binValue = 0 while value: binValue <<= value[0] del value[0] return base.prettyIn(self, binValue) else: raise SmiError('Unsupported numeric type spec "%s" at %s' % (displayHintType, self.__class__.__name__)) elif self.displayHint and self.__octetString.isSuperTypeOf( self, matchConstraints=False): numBase = {'x': 16, 'd': 10, 'o': 8} numDigits = { 'x': octets.str2octs(string.hexdigits), 'o': octets.str2octs(string.octdigits), 'd': octets.str2octs(string.digits) } # how do we know if object is initialized with display-hint # formatted text? based on "text" input maybe? # That boils down to `str` object on Py3 or `unicode` on Py2. if octets.isStringType(value) and not octets.isOctetsType(value): value = base.prettyIn(self, value) else: return base.prettyIn(self, value) outputValue = octets.str2octs('') runningValue = value displayHint = self.displayHint while runningValue and displayHint: # 1 this information is totally lost, just fail explicitly if displayHint[0] == '*': raise SmiError('Can\'t parse "*" in DISPLAY-HINT (%s)' % self.__class__.__name__) # 2 this becomes ambiguous when it comes to rendered value octetLength = '' while displayHint and displayHint[0] in string.digits: octetLength += displayHint[0] displayHint = displayHint[1:] # length is mandatory but people ignore that if not octetLength: octetLength = len(runningValue) try: octetLength = int(octetLength) except Exception: raise SmiError('Bad octet length: %s' % octetLength) if not displayHint: raise SmiError('Short octet length: %s' % self.displayHint) # 3 displayFormat = displayHint[0] displayHint = displayHint[1:] # 4 this is the lifesaver -- we could use it as an anchor if displayHint and displayHint[ 0] not in string.digits and displayHint[0] != '*': displaySep = displayHint[0] displayHint = displayHint[1:] else: displaySep = '' # 5 is probably impossible to support if displayFormat in ('a', 't'): outputValue += runningValue[:octetLength] elif displayFormat in numBase: if displaySep: guessedOctetLength = runningValue.find( octets.str2octs(displaySep)) if guessedOctetLength == -1: guessedOctetLength = len(runningValue) else: for idx in range(len(runningValue)): if runningValue[idx] not in numDigits[ displayFormat]: guessedOctetLength = idx break else: guessedOctetLength = len(runningValue) try: num = int( octets.octs2str(runningValue[:guessedOctetLength]), numBase[displayFormat]) except Exception: raise SmiError('Display format eval failure: %s: %s' % (runningValue[:guessedOctetLength], sys.exc_info()[1])) num_as_bytes = [] if num: while num: num_as_bytes.append(num & 0xFF) num >>= 8 else: num_as_bytes = [0] while len(num_as_bytes) < octetLength: num_as_bytes.append(0) num_as_bytes.reverse() outputValue += octets.ints2octs(num_as_bytes) if displaySep: guessedOctetLength += 1 octetLength = guessedOctetLength else: raise SmiError('Unsupported display format char: %s' % displayFormat) runningValue = runningValue[octetLength:] if not displayHint: displayHint = self.displayHint return base.prettyIn(self, outputValue) else: return base.prettyIn(self, value)
def test_isStringType(self): assert octets.isStringType('abc') == True assert octets.isStringType(123) == False assert octets.isStringType(unicode('abc')) == True
def test_isStringType(self): assert octets.isStringType('abc') == True assert octets.isStringType(123) == False assert octets.isStringType(bytes()) == False
def prettyIn(self, value): # override asn1 type method """Implements DISPLAY-HINT parsing into base SNMP value Proper parsing seems impossible due to ambiguities. Here we are trying to do our best, but be prepared for failures on complicated DISPLAY-HINTs. Keep in mind that this parser only works with "text" input meaning `unicode` (Py2) or `str` (Py3). """ for base in inspect.getmro(self.__class__): if not issubclass(base, TextualConvention) and issubclass(base, Asn1Item): break else: raise SmiError('TEXTUAL-CONVENTION has no underlying SNMP base type') if self.displayHint and (self.__integer.isSuperTypeOf(self, matchConstraints=False) and self.getNamedValues() or self.__unsigned32.isSuperTypeOf(self, matchConstraints=False) or self.__timeticks.isSuperTypeOf(self, matchConstraints=False)): value = str(value) _ = lambda t, f=0: (t, f) displayHintType, decimalPrecision = _(*self.displayHint.split('-')) if displayHintType == 'x' and (value.startswith('0x') or value.startswith('-0x')): try: if value.startswith('-'): return base.prettyIn(self, -int(value[3:], 16)) else: return base.prettyIn(self, int(value[2:], 16)) except Exception as exc: raise SmiError( 'integer evaluation error: %s' % exc ) elif displayHintType == 'd': try: return base.prettyIn(self, int(float(value) * 10**int(decimalPrecision))) except Exception as exc: raise SmiError( 'float evaluation error: %s' % exc ) elif displayHintType == 'o' and (value.startswith('0') or value.startswith('-0')): try: return base.prettyIn(self, int(value, 8)) except Exception as exc: raise SmiError( 'octal evaluation error: %s' % exc ) elif displayHintType == 'b' and (value.startswith('B') or value.startswith('-B')): negative = value.startswith('-') if negative: value = value[2:] else: value = value[1:] value = [x != '0' and 1 or 0 for x in value] binValue = 0 while value: binValue <<= value[0] del value[0] return base.prettyIn(self, binValue) else: raise SmiError( 'Unsupported numeric type spec "%s" at %s' % (displayHintType, self.__class__.__name__) ) elif self.displayHint and self.__octetString.isSuperTypeOf(self, matchConstraints=False): numBase = { 'x': 16, 'd': 10, 'o': 8 } numDigits = { 'x': octets.str2octs(string.hexdigits), 'o': octets.str2octs(string.octdigits), 'd': octets.str2octs(string.digits) } # how do we know if object is initialized with display-hint # formatted text? based on "text" input maybe? # That boils down to `str` object on Py3 or `unicode` on Py2. if octets.isStringType(value) and not octets.isOctetsType(value): value = base.prettyIn(self, value) else: return base.prettyIn(self, value) outputValue = octets.str2octs('') runningValue = value displayHint = self.displayHint while runningValue and displayHint: # 1 this information is totally lost, just fail explicitly if displayHint[0] == '*': raise SmiError( 'Can\'t parse "*" in DISPLAY-HINT (%s)' % self.__class__.__name__ ) # 2 this becomes ambiguous when it comes to rendered value octetLength = '' while displayHint and displayHint[0] in string.digits: octetLength += displayHint[0] displayHint = displayHint[1:] # length is mandatory but people ignore that if not octetLength: octetLength = len(runningValue) try: octetLength = int(octetLength) except Exception: raise SmiError( 'Bad octet length: %s' % octetLength ) if not displayHint: raise SmiError( 'Short octet length: %s' % self.displayHint ) # 3 displayFormat = displayHint[0] displayHint = displayHint[1:] # 4 this is the lifesaver -- we could use it as an anchor if displayHint and displayHint[0] not in string.digits and displayHint[0] != '*': displaySep = displayHint[0] displayHint = displayHint[1:] else: displaySep = '' # 5 is probably impossible to support if displayFormat in ('a', 't'): outputValue += runningValue[:octetLength] elif displayFormat in numBase: if displaySep: guessedOctetLength = runningValue.find(octets.str2octs(displaySep)) if guessedOctetLength == -1: guessedOctetLength = len(runningValue) else: for idx in range(len(runningValue)): if runningValue[idx] not in numDigits[displayFormat]: guessedOctetLength = idx break else: guessedOctetLength = len(runningValue) try: num = int(octets.octs2str(runningValue[:guessedOctetLength]), numBase[displayFormat]) except Exception as exc: raise SmiError( 'Display format eval failure: %s: %s' % (runningValue[:guessedOctetLength], exc) ) num_as_bytes = [] if num: while num: num_as_bytes.append(num & 0xFF) num >>= 8 else: num_as_bytes = [0] while len(num_as_bytes) < octetLength: num_as_bytes.append(0) num_as_bytes.reverse() outputValue += octets.ints2octs(num_as_bytes) if displaySep: guessedOctetLength += 1 octetLength = guessedOctetLength else: raise SmiError( 'Unsupported display format char: %s' % displayFormat ) runningValue = runningValue[octetLength:] if not displayHint: displayHint = self.displayHint return base.prettyIn(self, outputValue) else: return base.prettyIn(self, value)
def __getitem__(self, idx): if octets.isStringType(idx): nameToPosIdx = self.__getNameToPosIdx() return self.__namedTypes[nameToPosIdx[idx]] else: return self.__namedTypes[idx]
def __getitem__(self, idx): if octets.isStringType(idx): nameToPosIdx = self.__getNameToPosIdx() return self.__namedTypes[nameToPosIdx[idx]] else: return self.__namedTypes[idx]