744 lines
22 KiB
Python
744 lines
22 KiB
Python
#
|
|
# This file is part of pysnmp software.
|
|
#
|
|
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
|
# License: http://pysnmp.sf.net/license.html
|
|
#
|
|
from sys import version_info
|
|
from pyasn1.type import univ, tag, constraint, namedtype, namedval
|
|
from pyasn1.compat import octets
|
|
from pysnmp.proto import rfc1155, error
|
|
|
|
__all__ = ['Opaque', 'TimeTicks', 'Bits', 'Integer', 'OctetString',
|
|
'IpAddress', 'Counter64', 'Unsigned32', 'Gauge32', 'Integer32',
|
|
'ObjectIdentifier', 'Counter32']
|
|
|
|
|
|
class Integer32(univ.Integer):
|
|
"""Creates an instance of SNMP Integer32 class.
|
|
|
|
:py:class:`~pysnmp.proto.rfc1902.Integer32` type represents
|
|
integer-valued information between -2147483648 to 2147483647
|
|
inclusive (:RFC:`1902#section-7.1.1`). This type is indistinguishable
|
|
from the :py:class:`~pysnmp.proto.rfc1902.Integer` type.
|
|
The :py:class:`~pysnmp.proto.rfc1902.Integer32` type may be sub-typed
|
|
to be more constrained than the base
|
|
:py:class:`~pysnmp.proto.rfc1902.Integer32` type.
|
|
|
|
Parameters
|
|
----------
|
|
initializer : int
|
|
Python integer in range between -2147483648 to 2147483647 inclusive
|
|
or :py:class:`~pysnmp.proto.rfc1902.Integer32`.
|
|
|
|
Raises
|
|
------
|
|
PyAsn1Error :
|
|
On constraint violation or bad initializer.
|
|
|
|
Examples
|
|
--------
|
|
>>> from pysnmp.proto.rfc1902 import *
|
|
>>> Integer32(1234)
|
|
Integer32(1234)
|
|
>>> Integer32(1) > 2
|
|
True
|
|
>>> Integer32(1) + 1
|
|
Integer32(2)
|
|
>>> int(Integer32(321))
|
|
321
|
|
>>> SmallInteger = Integer32.withRange(1,3)
|
|
>>> SmallInteger(1)
|
|
Integer32(1)
|
|
>>> DiscreetInteger = Integer32.withValues(4, 8, 1)
|
|
>>> DiscreetInteger(4)
|
|
Integer32(4)
|
|
>>>
|
|
|
|
"""
|
|
subtypeSpec = univ.Integer.subtypeSpec + constraint.ValueRangeConstraint(
|
|
-2147483648, 2147483647
|
|
)
|
|
|
|
@classmethod
|
|
def withValues(cls, *values):
|
|
"""Creates a subclass with discreet values constraint.
|
|
"""
|
|
|
|
class X(cls):
|
|
subtypeSpec = cls.subtypeSpec + constraint.SingleValueConstraint(*values)
|
|
|
|
X.__name__ = cls.__name__
|
|
return X
|
|
|
|
@classmethod
|
|
def withRange(cls, minimum, maximum):
|
|
"""Creates a subclass with value range constraint.
|
|
"""
|
|
|
|
class X(cls):
|
|
subtypeSpec = cls.subtypeSpec + constraint.ValueRangeConstraint(minimum, maximum)
|
|
|
|
X.__name__ = cls.__name__
|
|
return X
|
|
|
|
|
|
class Integer(Integer32):
|
|
"""Creates an instance of SNMP INTEGER class.
|
|
|
|
The :py:class:`~pysnmp.proto.rfc1902.Integer` type represents
|
|
integer-valued information as named-number enumerations
|
|
(:RFC:`1902#section-7.1.1`). This type inherits and is indistinguishable
|
|
from :py:class:`~pysnmp.proto.rfc1902.Integer32` class.
|
|
The :py:class:`~pysnmp.proto.rfc1902.Integer` type may be sub-typed
|
|
to be more constrained than the base
|
|
:py:class:`~pysnmp.proto.rfc1902.Integer` type.
|
|
|
|
Parameters
|
|
----------
|
|
initializer : int
|
|
Python integer in range between -2147483648 to 2147483647 inclusive
|
|
or :py:class:`~pysnmp.proto.rfc1902.Integer` class instance.
|
|
In case of named-numbered enumerations, initialization is also
|
|
possible by enumerated literal.
|
|
|
|
Raises
|
|
------
|
|
PyAsn1Error :
|
|
On constraint violation or bad initializer.
|
|
|
|
Examples
|
|
--------
|
|
>>> from pysnmp.proto.rfc1902 import *
|
|
>>> Integer(1234)
|
|
Integer(1234)
|
|
>>> Integer(1) > 2
|
|
True
|
|
>>> Integer(1) + 1
|
|
Integer(2)
|
|
>>> int(Integer(321))
|
|
321
|
|
>>> SomeState = Integer.withNamedValues(enable=1, disable=0)
|
|
>>> SomeState(1)
|
|
Integer('enable')
|
|
>>> int(SomeState('disable'))
|
|
0
|
|
>>>
|
|
|
|
"""
|
|
|
|
@classmethod
|
|
def withNamedValues(cls, **values):
|
|
"""Creates a subclass with discreet named values constraint.
|
|
"""
|
|
|
|
class X(cls):
|
|
namedValues = cls.namedValues + namedval.NamedValues(*values.items())
|
|
subtypeSpec = cls.subtypeSpec + constraint.SingleValueConstraint(*values.values())
|
|
|
|
X.__name__ = cls.__name__
|
|
return X
|
|
|
|
|
|
class OctetString(univ.OctetString):
|
|
"""Creates an instance of SNMP OCTET STRING class.
|
|
|
|
The :py:class:`~pysnmp.proto.rfc1902.OctetString` type represents
|
|
arbitrary binary or text data (:RFC:`1902#section-7.1.2`).
|
|
It may be sub-typed to be constrained in size.
|
|
|
|
Parameters
|
|
----------
|
|
strValue : str
|
|
Python string or :py:class:`~pysnmp.proto.rfc1902.OctetString`
|
|
class instance.
|
|
|
|
Other parameters
|
|
----------------
|
|
hexValue : str
|
|
Python string representing octets in a hexadecimal notation
|
|
(e.g. DEADBEEF).
|
|
|
|
Raises
|
|
------
|
|
PyAsn1Error :
|
|
On constraint violation or bad initializer.
|
|
|
|
Examples
|
|
--------
|
|
>>> from pysnmp.proto.rfc1902 import *
|
|
>>> OctetString('some apples')
|
|
OctetString('some apples')
|
|
>>> OctetString('some apples') + ' and oranges'
|
|
OctetString('some apples and oranges')
|
|
>>> str(OctetString('some apples'))
|
|
'some apples'
|
|
>>> SomeString = OctetString.withSize(3, 12)
|
|
>>> str(SomeString(hexValue='deadbeef'))
|
|
'\xde\xad\xbe\xef'
|
|
>>>
|
|
|
|
"""
|
|
subtypeSpec = univ.OctetString.subtypeSpec + constraint.ValueSizeConstraint(
|
|
0, 65535
|
|
)
|
|
|
|
# rfc1902 uses a notion of "fixed length string" what might mean
|
|
# having zero-range size constraint applied. The following is
|
|
# supposed to be used for setting and querying this property.
|
|
|
|
fixedLength = None
|
|
|
|
def setFixedLength(self, value):
|
|
self.fixedLength = value
|
|
return self
|
|
|
|
def isFixedLength(self):
|
|
return self.fixedLength is not None
|
|
|
|
def getFixedLength(self):
|
|
return self.fixedLength
|
|
|
|
def clone(self, value=None, tagSet=None, subtypeSpec=None,
|
|
encoding=None, binValue=None, hexValue=None):
|
|
return univ.OctetString.clone(
|
|
self, value, tagSet, subtypeSpec, encoding, binValue, hexValue
|
|
).setFixedLength(self.getFixedLength())
|
|
|
|
def subtype(self, value=None, implicitTag=None, explicitTag=None,
|
|
subtypeSpec=None):
|
|
return univ.OctetString.subtype(
|
|
self, value, implicitTag, explicitTag, subtypeSpec
|
|
).setFixedLength(self.getFixedLength())
|
|
|
|
@classmethod
|
|
def withSize(cls, minimum, maximum):
|
|
"""Creates a subclass with value size constraint.
|
|
"""
|
|
|
|
class X(cls):
|
|
subtypeSpec = cls.subtypeSpec + constraint.ValueSizeConstraint(minimum, maximum)
|
|
|
|
X.__name__ = cls.__name__
|
|
return X
|
|
|
|
# modern pyasn1 does this all by itself
|
|
def prettyOut(self, value):
|
|
if version_info[0] <= 2:
|
|
numbers = tuple((ord(x) for x in value))
|
|
else:
|
|
numbers = tuple(value)
|
|
for x in numbers:
|
|
if x < 32 or x > 126:
|
|
return '0x' + ''.join(('%.2x' % x for x in numbers))
|
|
else:
|
|
return octets.octs2str(value)
|
|
|
|
|
|
class ObjectIdentifier(univ.ObjectIdentifier):
|
|
"""Creates an instance of SNMP OBJECT IDENTIFIER class.
|
|
|
|
The :py:class:`~pysnmp.proto.rfc1902.ObjectIdentifier` type represents
|
|
administratively assigned names (:RFC:`1902#section-7.1.3`).
|
|
Supports sequence protocol where elements are integer sub-identifiers.
|
|
|
|
Parameters
|
|
----------
|
|
initializer: tuple, str
|
|
Python tuple of up to 128 integers in range between 0 to 4294967295
|
|
inclusive or Python string containing OID in "dotted" form or
|
|
:py:class:`~pysnmp.proto.rfc1902.ObjectIdentifier`.
|
|
|
|
Raises
|
|
------
|
|
PyAsn1Error :
|
|
On constraint violation or bad initializer.
|
|
|
|
Examples
|
|
--------
|
|
>>> from pysnmp.proto.rfc1902 import *
|
|
>>> ObjectIdentifier((1, 3, 6))
|
|
ObjectIdentifier('1.3.6')
|
|
>>> ObjectIdentifier('1.3.6')
|
|
ObjectIdentifier('1.3.6')
|
|
>>> tuple(ObjectIdentifier('1.3.6'))
|
|
(1, 3, 6)
|
|
>>> str(ObjectIdentifier('1.3.6'))
|
|
'1.3.6'
|
|
>>>
|
|
|
|
"""
|
|
|
|
|
|
class IpAddress(OctetString):
|
|
"""Creates an instance of SNMP IpAddress class.
|
|
|
|
The :py:class:`~pysnmp.proto.rfc1902.IpAddress` class represents
|
|
a 32-bit internet address as an OCTET STRING of length 4, in network
|
|
byte-order (:RFC:`1902#section-7.1.5`).
|
|
|
|
Parameters
|
|
----------
|
|
strValue : str
|
|
The same as :py:class:`~pysnmp.proto.rfc1902.OctetString`,
|
|
additionally IPv4 address in dotted notation ('127.0.0.1').
|
|
|
|
Raises
|
|
------
|
|
PyAsn1Error :
|
|
On constraint violation or bad initializer.
|
|
|
|
Examples
|
|
--------
|
|
>>> from pysnmp.proto.rfc1902 import *
|
|
>>> IpAddress('127.0.0.1')
|
|
IpAddress(hexValue='7f000001')
|
|
>>> str(IpAddress(hexValue='7f000001'))
|
|
'\x7f\x00\x00\x01'
|
|
>>> IpAddress('\x7f\x00\x00\x01')
|
|
IpAddress(hexValue='7f000001')
|
|
>>>
|
|
|
|
"""
|
|
tagSet = OctetString.tagSet.tagImplicitly(
|
|
tag.Tag(tag.tagClassApplication, tag.tagFormatSimple, 0x00)
|
|
)
|
|
subtypeSpec = OctetString.subtypeSpec + constraint.ValueSizeConstraint(
|
|
4, 4
|
|
)
|
|
fixedLength = 4
|
|
|
|
def prettyIn(self, value):
|
|
if isinstance(value, str) and len(value) != 4:
|
|
try:
|
|
value = [int(x) for x in value.split('.')]
|
|
except:
|
|
raise error.ProtocolError('Bad IP address syntax %s' % value)
|
|
value = OctetString.prettyIn(self, value)
|
|
if len(value) != 4:
|
|
raise error.ProtocolError('Bad IP address syntax')
|
|
return value
|
|
|
|
def prettyOut(self, value):
|
|
if value:
|
|
return '.'.join(
|
|
['%d' % x for x in self.__class__(value).asNumbers()]
|
|
)
|
|
else:
|
|
return ''
|
|
|
|
|
|
class Counter32(univ.Integer):
|
|
"""Creates an instance of SNMP Counter32 class.
|
|
|
|
:py:class:`~pysnmp.proto.rfc1902.Counter32` type represents
|
|
a non-negative integer which monotonically increases until it
|
|
reaches a maximum value of 4294967295, when it wraps around and
|
|
starts increasing again from zero (:RFC:`1902#section-7.1.6`).
|
|
|
|
Parameters
|
|
----------
|
|
initializer : int
|
|
Python integer in range between 0 to 4294967295 inclusive
|
|
or any :py:class:`~pysnmp.proto.rfc1902.Integer`-based class.
|
|
|
|
Raises
|
|
------
|
|
PyAsn1Error :
|
|
On constraint violation or bad initializer.
|
|
|
|
Examples
|
|
--------
|
|
>>> from pysnmp.proto.rfc1902 import *
|
|
>>> Counter32(1234)
|
|
Counter32(1234)
|
|
>>> Counter32(1) + 1
|
|
Counter32(2)
|
|
>>> int(Counter32(321))
|
|
321
|
|
>>>
|
|
|
|
"""
|
|
tagSet = univ.Integer.tagSet.tagImplicitly(
|
|
tag.Tag(tag.tagClassApplication, tag.tagFormatSimple, 0x01)
|
|
)
|
|
subtypeSpec = univ.Integer.subtypeSpec + constraint.ValueRangeConstraint(
|
|
0, 4294967295
|
|
)
|
|
|
|
|
|
class Gauge32(univ.Integer):
|
|
"""Creates an instance of SNMP Gauge32 class.
|
|
|
|
:py:class:`~pysnmp.proto.rfc1902.Gauge32` type represents
|
|
a non-negative integer, which may increase or decrease, but shall
|
|
never exceed a maximum value. The maximum value can not be greater
|
|
than 4294967295 (:RFC:`1902#section-7.1.7`).
|
|
|
|
Parameters
|
|
----------
|
|
initializer : int
|
|
Python integer in range between 0 to 4294967295 inclusive
|
|
or any :py:class:`~pysnmp.proto.rfc1902.Integer`-based class.
|
|
|
|
Raises
|
|
------
|
|
PyAsn1Error :
|
|
On constraint violation or bad initializer.
|
|
|
|
Examples
|
|
--------
|
|
>>> from pysnmp.proto.rfc1902 import *
|
|
>>> Gauge32(1234)
|
|
Gauge32(1234)
|
|
>>> Gauge32(1) + 1
|
|
Gauge32(2)
|
|
>>> int(Gauge32(321))
|
|
321
|
|
>>>
|
|
|
|
"""
|
|
tagSet = univ.Integer.tagSet.tagImplicitly(
|
|
tag.Tag(tag.tagClassApplication, tag.tagFormatSimple, 0x02)
|
|
)
|
|
subtypeSpec = univ.Integer.subtypeSpec + constraint.ValueRangeConstraint(
|
|
0, 4294967295
|
|
)
|
|
|
|
|
|
class Unsigned32(univ.Integer):
|
|
"""Creates an instance of SNMP Unsigned32 class.
|
|
|
|
:py:class:`~pysnmp.proto.rfc1902.Unsigned32` type represents
|
|
integer-valued information between 0 and 4294967295
|
|
(:RFC:`1902#section-7.1.11`).
|
|
|
|
Parameters
|
|
----------
|
|
initializer : int
|
|
Python integer in range between 0 to 4294967295 inclusive
|
|
or any :py:class:`~pysnmp.proto.rfc1902.Integer`-based class.
|
|
|
|
Raises
|
|
------
|
|
PyAsn1Error :
|
|
On constraint violation or bad initializer.
|
|
|
|
Examples
|
|
--------
|
|
>>> from pysnmp.proto.rfc1902 import *
|
|
>>> Unsigned32(1234)
|
|
Unsigned32(1234)
|
|
>>> Unsigned32(1) + 1
|
|
Unsigned32(2)
|
|
>>> int(Unsigned32(321))
|
|
321
|
|
>>>
|
|
|
|
"""
|
|
tagSet = univ.Integer.tagSet.tagImplicitly(
|
|
tag.Tag(tag.tagClassApplication, tag.tagFormatSimple, 0x02)
|
|
)
|
|
subtypeSpec = univ.Integer.subtypeSpec + constraint.ValueRangeConstraint(
|
|
0, 4294967295
|
|
)
|
|
|
|
|
|
class TimeTicks(univ.Integer):
|
|
"""Creates an instance of SNMP TimeTicks class.
|
|
|
|
:py:class:`~pysnmp.proto.rfc1902.TimeTicks` type represents
|
|
a non-negative integer which represents the time, modulo 4294967296,
|
|
in hundredths of a second between two epochs (:RFC:`1902#section-7.1.8`).
|
|
|
|
Parameters
|
|
----------
|
|
initializer : int
|
|
Python integer in range between 0 to 4294967295 inclusive
|
|
or any :py:class:`~pysnmp.proto.rfc1902.Integer`-based class.
|
|
|
|
Raises
|
|
------
|
|
PyAsn1Error :
|
|
On constraint violation or bad initializer.
|
|
|
|
Examples
|
|
--------
|
|
>>> from pysnmp.proto.rfc1902 import *
|
|
>>> TimeTicks(1234)
|
|
TimeTicks(1234)
|
|
>>> TimeTicks(1) + 1
|
|
TimeTicks(2)
|
|
>>> int(TimeTicks(321))
|
|
321
|
|
>>>
|
|
|
|
"""
|
|
tagSet = univ.Integer.tagSet.tagImplicitly(
|
|
tag.Tag(tag.tagClassApplication, tag.tagFormatSimple, 0x03)
|
|
)
|
|
subtypeSpec = univ.Integer.subtypeSpec + constraint.ValueRangeConstraint(
|
|
0, 4294967295
|
|
)
|
|
|
|
|
|
class Opaque(univ.OctetString):
|
|
"""Creates an instance of SNMP Opaque class.
|
|
|
|
The :py:class:`~pysnmp.proto.rfc1902.Opaque` type supports the
|
|
capability to pass arbitrary ASN.1 syntax. A value is encoded
|
|
using the ASN.1 BER into a string of octets. This, in turn, is
|
|
encoded as an OCTET STRING, in effect "double-wrapping" the original
|
|
ASN.1 value (:RFC:`1902#section-7.1.9`).
|
|
|
|
Parameters
|
|
----------
|
|
strValue : str
|
|
Python string or :py:class:`~pysnmp.proto.rfc1902.OctetString`-based
|
|
class instance.
|
|
|
|
Other parameters
|
|
----------------
|
|
hexValue : str
|
|
Python string representing octets in a hexadecimal notation
|
|
(e.g. DEADBEEF).
|
|
|
|
Raises
|
|
------
|
|
PyAsn1Error :
|
|
On constraint violation or bad initializer.
|
|
|
|
Examples
|
|
--------
|
|
>>> from pysnmp.proto.rfc1902 import *
|
|
>>> Opaque('some apples')
|
|
Opaque('some apples')
|
|
>>> Opaque('some apples') + ' and oranges'
|
|
Opaque('some apples and oranges')
|
|
>>> str(Opaque('some apples'))
|
|
'some apples'
|
|
>>> str(Opaque(hexValue='deadbeef'))
|
|
'\xde\xad\xbe\xef'
|
|
>>>
|
|
|
|
"""
|
|
tagSet = univ.OctetString.tagSet.tagImplicitly(
|
|
tag.Tag(tag.tagClassApplication, tag.tagFormatSimple, 0x04)
|
|
)
|
|
|
|
|
|
class Counter64(univ.Integer):
|
|
"""Creates an instance of SNMP Counter64 class.
|
|
|
|
:py:class:`~pysnmp.proto.rfc1902.Counter64` type represents
|
|
a non-negative integer which monotonically increases until it reaches
|
|
a maximum value of 18446744073709551615, when it wraps around and starts
|
|
increasing again from zero (:RFC:`1902#section-7.1.10`).
|
|
|
|
Parameters
|
|
----------
|
|
initializer : int
|
|
Python integer in range between 0 to 4294967295 inclusive
|
|
or any :py:class:`~pysnmp.proto.rfc1902.Integer`-based class.
|
|
|
|
Raises
|
|
------
|
|
PyAsn1Error :
|
|
On constraint violation or bad initializer.
|
|
|
|
Examples
|
|
--------
|
|
>>> from pysnmp.proto.rfc1902 import *
|
|
>>> Counter64(1234)
|
|
Counter64(1234)
|
|
>>> Counter64(1) + 1
|
|
Counter64(2)
|
|
>>> int(Counter64(321))
|
|
321
|
|
>>>
|
|
|
|
"""
|
|
tagSet = univ.Integer.tagSet.tagImplicitly(
|
|
tag.Tag(tag.tagClassApplication, tag.tagFormatSimple, 0x06)
|
|
)
|
|
subtypeSpec = univ.Integer.subtypeSpec + constraint.ValueRangeConstraint(
|
|
0, 18446744073709551615
|
|
)
|
|
|
|
|
|
class Bits(OctetString):
|
|
"""Creates an instance of SNMP BITS class.
|
|
|
|
The :py:class:`~pysnmp.proto.rfc1902.Bits` type represents
|
|
an enumeration of named bits. This collection is assigned non-negative,
|
|
contiguous values, starting at zero. Only those named-bits so enumerated
|
|
may be present in a value (:RFC:`1902#section-7.1.4`).
|
|
|
|
The bits are named and identified by their position in the octet string.
|
|
Position zero is the high order (or left-most) bit in the first octet of
|
|
the string. Position 7 is the low order (or right-most) bit of the first
|
|
octet of the string. Position 8 is the high order bit in the second octet
|
|
of the string, and so on
|
|
(`BITS Pseudotype <https://tools.ietf.org/html/draft-perkins-bits-00>`_).
|
|
|
|
Parameters
|
|
----------
|
|
strValue : str, tuple
|
|
Sequence of bit names or a Python string (as a raw data) or
|
|
:py:class:`~pysnmp.proto.rfc1902.OctetString` class instance.
|
|
|
|
Other parameters
|
|
----------------
|
|
hexValue : str
|
|
Python string representing octets in a hexadecimal notation
|
|
(e.g. DEADBEEF).
|
|
|
|
Raises
|
|
------
|
|
PyAsn1Error :
|
|
On constraint violation or bad initializer.
|
|
|
|
Examples
|
|
--------
|
|
>>> from pysnmp.proto.rfc1902 import *
|
|
>>> SomeBits = Bits.withNamedBits(apple=0, orange=1, peach=2)
|
|
>>> SomeBits(('apple', 'orange')).prettyPrint()
|
|
'apple, orange'
|
|
>>> SomeBits(('apple', 'orange'))
|
|
Bits(hexValue='c0')
|
|
>>> SomeBits('\x80')
|
|
Bits(hexValue='80')
|
|
>>> SomeBits(hexValue='80')
|
|
Bits(hexValue='80')
|
|
>>> SomeBits(hexValue='80').prettyPrint()
|
|
'apple'
|
|
>>>
|
|
|
|
"""
|
|
namedValues = namedval.NamedValues()
|
|
|
|
def __init__(self, value=None, tagSet=None, subtypeSpec=None,
|
|
encoding=None, binValue=None, hexValue=None,
|
|
namedValues=None):
|
|
if namedValues is None:
|
|
self.__namedValues = self.namedValues
|
|
else:
|
|
self.__namedValues = namedValues
|
|
OctetString.__init__(
|
|
self, value, tagSet, subtypeSpec, encoding, binValue, hexValue
|
|
)
|
|
|
|
def prettyIn(self, bits):
|
|
if not isinstance(bits, (tuple, list)):
|
|
return OctetString.prettyIn(self, bits) # raw bitstring
|
|
_octets = []
|
|
for bit in bits: # tuple of named bits
|
|
v = self.__namedValues.getValue(bit)
|
|
if v is None:
|
|
raise error.ProtocolError(
|
|
'Unknown named bit %s' % bit
|
|
)
|
|
d, m = divmod(v, 8)
|
|
if d >= len(_octets):
|
|
_octets.extend([0] * (d - len(_octets) + 1))
|
|
_octets[d] |= 0x01 << (7 - m)
|
|
return OctetString.prettyIn(self, _octets)
|
|
|
|
def prettyOut(self, value):
|
|
names = []
|
|
ints = self.__class__(value).asNumbers()
|
|
i = 0
|
|
while i < len(ints):
|
|
v = ints[i]
|
|
j = 7
|
|
while j >= 0:
|
|
if v & (0x01 << j):
|
|
name = self.__namedValues.getName(i * 8 + 7 - j)
|
|
if name is None:
|
|
name = 'UnknownBit-%s' % (i * 8 + 7 - j,)
|
|
names.append(name)
|
|
j -= 1
|
|
i += 1
|
|
return ', '.join([str(x) for x in names])
|
|
|
|
def clone(self, value=None, tagSet=None, subtypeSpec=None,
|
|
encoding=None, binValue=None, hexValue=None,
|
|
namedValues=None):
|
|
if value is None and tagSet is None and subtypeSpec is None \
|
|
and namedValues is None:
|
|
return self
|
|
if value is None:
|
|
value = self._value
|
|
if tagSet is None:
|
|
tagSet = self._tagSet
|
|
if subtypeSpec is None:
|
|
subtypeSpec = self._subtypeSpec
|
|
if namedValues is None:
|
|
namedValues = self.__namedValues
|
|
return self.__class__(value, tagSet, subtypeSpec, encoding,
|
|
binValue, hexValue, namedValues)
|
|
|
|
def subtype(self, value=None, implicitTag=None, explicitTag=None,
|
|
subtypeSpec=None, namedValues=None):
|
|
if value is None:
|
|
value = self._value
|
|
if implicitTag is not None:
|
|
tagSet = self._tagSet.tagImplicitly(implicitTag)
|
|
elif explicitTag is not None:
|
|
tagSet = self._tagSet.tagExplicitly(explicitTag)
|
|
else:
|
|
tagSet = self._tagSet
|
|
if subtypeSpec is None:
|
|
subtypeSpec = self._subtypeSpec
|
|
else:
|
|
subtypeSpec = subtypeSpec + self._subtypeSpec
|
|
if namedValues is None:
|
|
namedValues = self.__namedValues
|
|
else:
|
|
namedValues = namedValues + self.__namedValues
|
|
return self.__class__(value, tagSet, subtypeSpec,
|
|
namedValues=namedValues)
|
|
|
|
@classmethod
|
|
def withNamedBits(cls, **values):
|
|
"""Creates a subclass with discreet named bits constraint.
|
|
"""
|
|
|
|
class X(cls):
|
|
namedValues = cls.namedValues + namedval.NamedValues(*values.items())
|
|
|
|
X.__name__ = cls.__name__
|
|
return X
|
|
|
|
|
|
class ObjectName(univ.ObjectIdentifier):
|
|
pass
|
|
|
|
|
|
class SimpleSyntax(rfc1155.TypeCoercionHackMixIn, univ.Choice):
|
|
componentType = namedtype.NamedTypes(
|
|
namedtype.NamedType('integer-value', Integer()),
|
|
namedtype.NamedType('string-value', OctetString()),
|
|
namedtype.NamedType('objectID-value', univ.ObjectIdentifier())
|
|
)
|
|
|
|
|
|
class ApplicationSyntax(rfc1155.TypeCoercionHackMixIn, univ.Choice):
|
|
componentType = namedtype.NamedTypes(
|
|
namedtype.NamedType('ipAddress-value', IpAddress()),
|
|
namedtype.NamedType('counter-value', Counter32()),
|
|
namedtype.NamedType('timeticks-value', TimeTicks()),
|
|
namedtype.NamedType('arbitrary-value', Opaque()),
|
|
namedtype.NamedType('big-counter-value', Counter64()),
|
|
# This conflicts with Counter32
|
|
# namedtype.NamedType('unsigned-integer-value', Unsigned32()),
|
|
namedtype.NamedType('gauge32-value', Gauge32())
|
|
) # BITS misplaced?
|
|
|
|
|
|
class ObjectSyntax(univ.Choice):
|
|
componentType = namedtype.NamedTypes(
|
|
namedtype.NamedType('simple', SimpleSyntax()),
|
|
namedtype.NamedType('application-wide', ApplicationSyntax())
|
|
)
|