diff options
Diffstat (limited to 'pyasn1/type/base.py')
-rw-r--r-- | pyasn1/type/base.py | 140 |
1 files changed, 90 insertions, 50 deletions
diff --git a/pyasn1/type/base.py b/pyasn1/type/base.py index 7995118..21e4041 100644 --- a/pyasn1/type/base.py +++ b/pyasn1/type/base.py @@ -12,7 +12,8 @@ from pyasn1.type import constraint from pyasn1.type import tag from pyasn1.type import tagmap -__all__ = ['Asn1Item', 'Asn1ItemBase', 'AbstractSimpleAsn1Item', 'AbstractConstructedAsn1Item'] +__all__ = ['Asn1Item', 'Asn1Type', 'SimpleAsn1Type', + 'ConstructedAsn1Type'] class Asn1Item(object): @@ -25,7 +26,17 @@ class Asn1Item(object): return Asn1Item._typeCounter -class Asn1ItemBase(Asn1Item): +class Asn1Type(Asn1Item): + """Base class for all classes representing ASN.1 types. + + In the user code, |ASN.1| class is normally used only for telling + ASN.1 objects from others. + + Note + ---- + For as long as ASN.1 is concerned, a way to compare ASN.1 types + is to use :meth:`isSameTypeWith` and :meth:`isSuperTypeOf` methods. + """ #: Set or return a :py:class:`~pyasn1.type.tag.TagSet` object representing #: ASN.1 tag(s) associated with |ASN.1| type. tagSet = tag.TagSet() @@ -91,8 +102,8 @@ class Asn1ItemBase(Asn1Item): Returns ------- : :class:`bool` - :class:`True` if *other* is |ASN.1| type, - :class:`False` otherwise. + :obj:`True` if *other* is |ASN.1| type, + :obj:`False` otherwise. """ return (self is other or (not matchTags or self.tagSet == other.tagSet) and @@ -115,8 +126,8 @@ class Asn1ItemBase(Asn1Item): Returns ------- : :class:`bool` - :class:`True` if *other* is a subtype of |ASN.1| type, - :class:`False` otherwise. + :obj:`True` if *other* is a subtype of |ASN.1| type, + :obj:`False` otherwise. """ return (not matchTags or (self.tagSet.isSuperTagSetOf(other.tagSet)) and @@ -146,9 +157,13 @@ class Asn1ItemBase(Asn1Item): def getSubtypeSpec(self): return self.subtypeSpec + # backward compatibility def hasValue(self): return self.isValue +# Backward compatibility +Asn1ItemBase = Asn1Type + class NoValue(object): """Create a singleton instance of NoValue class. @@ -221,19 +236,31 @@ class NoValue(object): raise error.PyAsn1Error('Attempted "%s" operation on ASN.1 schema object' % attr) def __repr__(self): - return '<%s object at 0x%x>' % (self.__class__.__name__, id(self)) + return '<%s object>' % self.__class__.__name__ noValue = NoValue() -# Base class for "simple" ASN.1 objects. These are immutable. -class AbstractSimpleAsn1Item(Asn1ItemBase): +class SimpleAsn1Type(Asn1Type): + """Base class for all simple classes representing ASN.1 types. + + ASN.1 distinguishes types by their ability to hold other objects. + Scalar types are known as *simple* in ASN.1. + + In the user code, |ASN.1| class is normally used only for telling + ASN.1 objects from others. + + Note + ---- + For as long as ASN.1 is concerned, a way to compare ASN.1 types + is to use :meth:`isSameTypeWith` and :meth:`isSuperTypeOf` methods. + """ #: Default payload value defaultValue = noValue def __init__(self, value=noValue, **kwargs): - Asn1ItemBase.__init__(self, **kwargs) + Asn1Type.__init__(self, **kwargs) if value is noValue: value = self.defaultValue else: @@ -248,19 +275,18 @@ class AbstractSimpleAsn1Item(Asn1ItemBase): self._value = value def __repr__(self): - representation = '%s %s object at 0x%x' % ( - self.__class__.__name__, self.isValue and 'value' or 'schema', id(self) - ) + representation = '%s %s object' % ( + self.__class__.__name__, self.isValue and 'value' or 'schema') for attr, value in self.readOnly.items(): if value: - representation += ' %s %s' % (attr, value) + representation += ', %s %s' % (attr, value) if self.isValue: value = self.prettyPrint() if len(value) > 32: value = value[:16] + '...' + value[-16:] - representation += ' payload [%s]' % value + representation += ', payload [%s]' % value return '<%s>' % representation @@ -296,17 +322,18 @@ class AbstractSimpleAsn1Item(Asn1ItemBase): def isValue(self): """Indicate that |ASN.1| object represents ASN.1 value. - If *isValue* is `False` then this object represents just ASN.1 schema. + If *isValue* is :obj:`False` then this object represents just + ASN.1 schema. - If *isValue* is `True` then, in addition to its ASN.1 schema features, - this object can also be used like a Python built-in object (e.g. `int`, - `str`, `dict` etc.). + If *isValue* is :obj:`True` then, in addition to its ASN.1 schema + features, this object can also be used like a Python built-in object + (e.g. :class:`int`, :class:`str`, :class:`dict` etc.). Returns ------- : :class:`bool` - :class:`False` if object represents just ASN.1 schema. - :class:`True` if object represents ASN.1 schema and can be used as a normal value. + :obj:`False` if object represents just ASN.1 schema. + :obj:`True` if object represents ASN.1 schema and can be used as a normal value. Note ---- @@ -425,10 +452,12 @@ class AbstractSimpleAsn1Item(Asn1ItemBase): def prettyPrint(self, scope=0): return self.prettyOut(self._value) - # noinspection PyUnusedLocal def prettyPrintType(self, scope=0): return '%s -> %s' % (self.tagSet, self.__class__.__name__) +# Backward compatibility +AbstractSimpleAsn1Item = SimpleAsn1Type + # # Constructed types: # * There are five of them: Sequence, SequenceOf/SetOf, Set and Choice @@ -449,9 +478,22 @@ class AbstractSimpleAsn1Item(Asn1ItemBase): # -class AbstractConstructedAsn1Item(Asn1ItemBase): +class ConstructedAsn1Type(Asn1Type): + """Base class for all constructed classes representing ASN.1 types. + + ASN.1 distinguishes types by their ability to hold other objects. + Those "nesting" types are known as *constructed* in ASN.1. - #: If `True`, requires exact component type matching, + In the user code, |ASN.1| class is normally used only for telling + ASN.1 objects from others. + + Note + ---- + For as long as ASN.1 is concerned, a way to compare ASN.1 types + is to use :meth:`isSameTypeWith` and :meth:`isSuperTypeOf` methods. + """ + + #: If :obj:`True`, requires exact component type matching, #: otherwise subtype relation is only enforced strictConstraints = False @@ -465,51 +507,51 @@ class AbstractConstructedAsn1Item(Asn1ItemBase): } readOnly.update(kwargs) - Asn1ItemBase.__init__(self, **readOnly) - - self._componentValues = [] + Asn1Type.__init__(self, **readOnly) def __repr__(self): - representation = '%s %s object at 0x%x' % ( - self.__class__.__name__, self.isValue and 'value' or 'schema', id(self) + representation = '%s %s object' % ( + self.__class__.__name__, self.isValue and 'value' or 'schema' ) for attr, value in self.readOnly.items(): if value is not noValue: - representation += ' %s=%r' % (attr, value) + representation += ', %s=%r' % (attr, value) - if self.isValue and self._componentValues: - representation += ' payload [%s]' % ', '.join([repr(x) for x in self._componentValues]) + if self.isValue and self.components: + representation += ', payload [%s]' % ', '.join( + [repr(x) for x in self.components]) return '<%s>' % representation def __eq__(self, other): - return self is other and True or self._componentValues == other + return self is other or self.components == other def __ne__(self, other): - return self._componentValues != other + return self.components != other def __lt__(self, other): - return self._componentValues < other + return self.components < other def __le__(self, other): - return self._componentValues <= other + return self.components <= other def __gt__(self, other): - return self._componentValues > other + return self.components > other def __ge__(self, other): - return self._componentValues >= other + return self.components >= other if sys.version_info[0] <= 2: def __nonzero__(self): - return self._componentValues and True or False + return bool(self.components) else: def __bool__(self): - return self._componentValues and True or False + return bool(self.components) - def __len__(self): - return len(self._componentValues) + @property + def components(self): + raise error.PyAsn1Error('Method not implemented') def _cloneComponentValues(self, myClone, cloneValueFlag): pass @@ -535,8 +577,7 @@ class AbstractConstructedAsn1Item(Asn1ItemBase): Note ---- Due to the mutable nature of the |ASN.1| object, even if no arguments - are supplied, new |ASN.1| object will always be created as a shallow - copy of `self`. + are supplied, a new |ASN.1| object will be created and returned. """ cloneValueFlag = kwargs.pop('cloneValueFlag', False) @@ -588,9 +629,8 @@ class AbstractConstructedAsn1Item(Asn1ItemBase): Note ---- - Due to the immutable nature of the |ASN.1| object, if no arguments - are supplied, no new |ASN.1| object will be created and `self` will - be returned instead. + Due to the mutable nature of the |ASN.1| object, even if no arguments + are supplied, a new |ASN.1| object will be created and returned. """ initializers = self.readOnly.copy() @@ -631,9 +671,6 @@ class AbstractConstructedAsn1Item(Asn1ItemBase): self[k] = kwargs[k] return self - def clear(self): - self._componentValues = [] - # backward compatibility def setDefaultComponents(self): @@ -641,3 +678,6 @@ class AbstractConstructedAsn1Item(Asn1ItemBase): def getComponentType(self): return self.componentType + +# Backward compatibility +AbstractConstructedAsn1Item = ConstructedAsn1Type |