From 6fb2b5ddc59ac08649bb5a68a2f82e59f165b04d Mon Sep 17 00:00:00 2001 From: Ilya Etingof Date: Fri, 21 Apr 2017 01:09:10 +0200 Subject: ANY DEFINED BY decoding implemented --- CHANGES.rst | 1 + pyasn1/codec/ber/decoder.py | 13 ++++++++++++- pyasn1/type/namedtype.py | 28 ++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/CHANGES.rst b/CHANGES.rst index 56f3fed..ce97e34 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -2,6 +2,7 @@ Revision 0.2.4, released XX-03-2017 ----------------------------------- +- ANY DEFINED BY clause support implemented - ASN.1 types initialization refactored to minimize the use of relatively expensive isNoValue() call - Lazily pre-populate list of values of Sequence/Set/Choice types diff --git a/pyasn1/codec/ber/decoder.py b/pyasn1/codec/ber/decoder.py index e100e75..46f861d 100644 --- a/pyasn1/codec/ber/decoder.py +++ b/pyasn1/codec/ber/decoder.py @@ -403,6 +403,17 @@ class SequenceAndSetDecoderBase(AbstractConstructedDecoder): matchTags=False, matchConstraints=False ) + for holeName, governingName, typesMap in namedTypes.holes: + holeComponent = asn1Object[holeName] + if holeComponent.isValue: + governingComponent = asn1Object[governingName] + if governingComponent in typesMap: + component, rest = decodeFun( + holeComponent.asOctets(), + asn1Spec=typesMap[governingComponent] + ) + asn1Object.setComponentByName(holeName, component, matchTags=False, matchConstraints=False) + if not namedTypes: asn1Object.verifySizeSpec() @@ -1008,7 +1019,7 @@ class Decoder(object): 'codec %s yields type %s, value:\n%s\n...remaining substrate is: %s' % (concreteDecoder.__class__.__name__, value.__class__.__name__, value.prettyPrint(), substrate and debug.hexdump(substrate) or '')) if state == stErrorCondition: raise error.PyAsn1Error( - '%s not in asn1Spec: %s' % (tagSet, asn1Spec) + '%s not in asn1Spec: %r' % (tagSet, asn1Spec) ) if debug.logger and debug.logger & debug.flagDecoder: debug.scope.pop() diff --git a/pyasn1/type/namedtype.py b/pyasn1/type/namedtype.py index 3f9ae19..710ce93 100644 --- a/pyasn1/type/namedtype.py +++ b/pyasn1/type/namedtype.py @@ -34,6 +34,8 @@ class NamedType(object): self.__name = name self.__type = asn1Object self.__nameAndType = name, asn1Object + self.__governingName = None + self.__typesMap = None def __repr__(self): return '%s(%r, %r)' % (self.__class__.__name__, self.__name, self.__type) @@ -73,6 +75,19 @@ class NamedType(object): def asn1Object(self): return self.__type + def definedBy(self, governingName, typesMap): + self.__governingName = governingName + self.__typesMap = typesMap + return self + + @property + def governingName(self): + return self.__governingName + + @property + def typesMap(self): + return self.__typesMap + # Backward compatibility def getName(self): @@ -116,6 +131,7 @@ class NamedTypes(object): self.__tagMap = {} self.__hasOptionalOrDefault = None self.__requiredComponents = None + self.__holes = None def __repr__(self): return '%s(%s)' % ( @@ -473,3 +489,15 @@ class NamedTypes(object): [idx for idx, nt in enumerate(self.__namedTypes) if not nt.isOptional and not nt.isDefaulted] ) return self.__requiredComponents + + @property + def holes(self): + if self.__holes is None: + holes = [] + for namedType in self.__namedTypes: + if namedType.governingName: + holes.append((namedType.name, namedType.governingName, namedType.typesMap)) + + self.__holes = holes + + return self.__holes -- cgit v1.2.1 From 1967b4af0e38506d4c1cdaf56f85d74e51927978 Mon Sep 17 00:00:00 2001 From: Ilya Etingof Date: Fri, 21 Apr 2017 10:02:29 +0200 Subject: quick fix to OctetString.prettyOut on Py3 --- pyasn1/type/univ.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyasn1/type/univ.py b/pyasn1/type/univ.py index 911eb65..595192a 100644 --- a/pyasn1/type/univ.py +++ b/pyasn1/type/univ.py @@ -1105,7 +1105,7 @@ class OctetString(base.AbstractSimpleAsn1Item): numbers = tuple(value) for x in numbers: if x < 32 or x > 126: - return octets.octs2str('0x') + ''.join(('%.2x' % x for x in numbers)) + return octets.str2octs('0x' + ''.join(('%.2x' % x for x in numbers))) else: try: return value.decode(self._encoding) -- cgit v1.2.1 From 602f7a3a1b6ea43ada2973e248b97f7b0e80f115 Mon Sep 17 00:00:00 2001 From: Ilya Etingof Date: Fri, 7 Jul 2017 10:03:44 +0200 Subject: run hole type substitution only when components are in place --- pyasn1/codec/ber/decoder.py | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/pyasn1/codec/ber/decoder.py b/pyasn1/codec/ber/decoder.py index 46f861d..e7da9a1 100644 --- a/pyasn1/codec/ber/decoder.py +++ b/pyasn1/codec/ber/decoder.py @@ -403,18 +403,19 @@ class SequenceAndSetDecoderBase(AbstractConstructedDecoder): matchTags=False, matchConstraints=False ) - for holeName, governingName, typesMap in namedTypes.holes: - holeComponent = asn1Object[holeName] - if holeComponent.isValue: - governingComponent = asn1Object[governingName] - if governingComponent in typesMap: - component, rest = decodeFun( - holeComponent.asOctets(), - asn1Spec=typesMap[governingComponent] - ) + if namedTypes: + for holeName, governingName, typesMap in namedTypes.holes: + holeComponent = asn1Object[holeName] + if holeComponent.isValue: + governingComponent = asn1Object[governingName] + if governingComponent in typesMap: + component, rest = decodeFun( + holeComponent.asOctets(), + asn1Spec=typesMap[governingComponent] + ) asn1Object.setComponentByName(holeName, component, matchTags=False, matchConstraints=False) - if not namedTypes: + else: asn1Object.verifySizeSpec() return asn1Object, tail @@ -470,7 +471,19 @@ class SequenceAndSetDecoderBase(AbstractConstructedDecoder): 'No EOO seen before substrate ends' ) - if not namedTypes: + if namedTypes: + for holeName, governingName, typesMap in namedTypes.holes: + holeComponent = asn1Object[holeName] + if holeComponent.isValue: + governingComponent = asn1Object[governingName] + if governingComponent in typesMap: + component, rest = decodeFun( + holeComponent.asOctets(), + asn1Spec=typesMap[governingComponent] + ) + asn1Object.setComponentByName(holeName, component, matchTags=False, matchConstraints=False) + + else: asn1Object.verifySizeSpec() return asn1Object, substrate -- cgit v1.2.1 From 8308c329ac49af66de054158598194f41855699f Mon Sep 17 00:00:00 2001 From: Ilya Etingof Date: Fri, 21 Apr 2017 01:09:10 +0200 Subject: ANY DEFINED BY decoding implemented --- CHANGES.rst | 5 +++++ pyasn1/codec/ber/decoder.py | 12 ++++++++++++ pyasn1/type/namedtype.py | 28 ++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index dfdf3ce..065ac18 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,4 +1,9 @@ +Revision 0.4.1, released XX-09-2017 +----------------------------------- + +- ANY DEFINED BY clause support implemented + Revision 0.3.4, released 07-09-2017 ----------------------------------- diff --git a/pyasn1/codec/ber/decoder.py b/pyasn1/codec/ber/decoder.py index 4fff81b..75960cf 100644 --- a/pyasn1/codec/ber/decoder.py +++ b/pyasn1/codec/ber/decoder.py @@ -493,6 +493,18 @@ class UniversalConstructedTypeDecoder(AbstractConstructedDecoder): ) idx += 1 + for holeName, governingName, typesMap in namedTypes.holes: + holeComponent = asn1Object[holeName] + if holeComponent.isValue: + governingComponent = asn1Object[governingName] + if governingComponent in typesMap: + component, rest = decodeFun( + holeComponent.asOctets(), + asn1Spec=typesMap[governingComponent] + ) + asn1Object.setComponentByName(holeName, component, matchTags=False, matchConstraints=False) + + if not namedTypes: asn1Object.verifySizeSpec() return asn1Object, tail diff --git a/pyasn1/type/namedtype.py b/pyasn1/type/namedtype.py index 7a51f18..6bf82f4 100644 --- a/pyasn1/type/namedtype.py +++ b/pyasn1/type/namedtype.py @@ -34,6 +34,8 @@ class NamedType(object): self.__name = name self.__type = asn1Object self.__nameAndType = name, asn1Object + self.__governingName = None + self.__typesMap = None def __repr__(self): return '%s(%r, %r)' % (self.__class__.__name__, self.__name, self.__type) @@ -73,6 +75,19 @@ class NamedType(object): def asn1Object(self): return self.__type + def definedBy(self, governingName, typesMap): + self.__governingName = governingName + self.__typesMap = typesMap + return self + + @property + def governingName(self): + return self.__governingName + + @property + def typesMap(self): + return self.__typesMap + # Backward compatibility def getName(self): @@ -123,6 +138,7 @@ class NamedTypes(object): self.__keys = frozenset([namedType.name for namedType in self.__namedTypes]) self.__values = tuple([namedType.asn1Object for namedType in self.__namedTypes]) self.__items = tuple([(namedType.name, namedType.asn1Object) for namedType in self.__namedTypes]) + self.__holes = self.__computeTypeHoles() def __repr__(self): return '%s(%s)' % ( @@ -509,3 +525,15 @@ class NamedTypes(object): @property def requiredComponents(self): return self.__requiredComponents + + @property + def holes(self): + return self.__holes + + def __computeTypeHoles(self): + holes = [] + for namedType in self.__namedTypes: + if namedType.governingName: + holes.append((namedType.name, namedType.governingName, namedType.typesMap)) + + return holes -- cgit v1.2.1 From fd581c9becc475760314703760dbf06777b11d43 Mon Sep 17 00:00:00 2001 From: Ilya Etingof Date: Fri, 7 Jul 2017 10:03:44 +0200 Subject: run hole type substitution only when components are in place --- pyasn1/codec/ber/decoder.py | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/pyasn1/codec/ber/decoder.py b/pyasn1/codec/ber/decoder.py index 75960cf..58c45aa 100644 --- a/pyasn1/codec/ber/decoder.py +++ b/pyasn1/codec/ber/decoder.py @@ -493,18 +493,19 @@ class UniversalConstructedTypeDecoder(AbstractConstructedDecoder): ) idx += 1 - for holeName, governingName, typesMap in namedTypes.holes: - holeComponent = asn1Object[holeName] - if holeComponent.isValue: - governingComponent = asn1Object[governingName] - if governingComponent in typesMap: - component, rest = decodeFun( - holeComponent.asOctets(), - asn1Spec=typesMap[governingComponent] - ) + if namedTypes: + for holeName, governingName, typesMap in namedTypes.holes: + holeComponent = asn1Object[holeName] + if holeComponent.isValue: + governingComponent = asn1Object[governingName] + if governingComponent in typesMap: + component, rest = decodeFun( + holeComponent.asOctets(), + asn1Spec=typesMap[governingComponent] + ) asn1Object.setComponentByName(holeName, component, matchTags=False, matchConstraints=False) - if not namedTypes: + else: asn1Object.verifySizeSpec() return asn1Object, tail @@ -603,6 +604,20 @@ class UniversalConstructedTypeDecoder(AbstractConstructedDecoder): raise error.SubstrateUnderrunError( 'No EOO seen before substrate ends' ) + + if namedTypes: + for holeName, governingName, typesMap in namedTypes.holes: + holeComponent = asn1Object[holeName] + if holeComponent.isValue: + governingComponent = asn1Object[governingName] + if governingComponent in typesMap: + component, rest = decodeFun( + holeComponent.asOctets(), + asn1Spec=typesMap[governingComponent] + ) + asn1Object.setComponentByName(holeName, component, matchTags=False, matchConstraints=False) + + else: asn1Object.verifySizeSpec() return asn1Object, substrate -- cgit v1.2.1 From 3e8db6efc18ed08d9a98d10c30749186baa03aee Mon Sep 17 00:00:00 2001 From: Ilya Etingof Date: Fri, 8 Sep 2017 21:02:40 +0200 Subject: codecs signatures unified and pass **options through WARNING: signatures of some undocumented codecs methods changed --- CHANGES.rst | 5 + pyasn1/__init__.py | 2 +- pyasn1/codec/ber/decoder.py | 210 +++++++++++++++++++++++++++-------------- pyasn1/codec/ber/encoder.py | 74 +++++++++------ pyasn1/codec/cer/decoder.py | 6 +- pyasn1/codec/cer/encoder.py | 47 +++++---- pyasn1/codec/der/encoder.py | 17 ++-- pyasn1/codec/native/decoder.py | 22 +++-- pyasn1/codec/native/encoder.py | 40 ++++---- 9 files changed, 265 insertions(+), 158 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index dfdf3ce..8702ee1 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,4 +1,9 @@ +Revision 0.3.5, released XX-09-2017 +----------------------------------- + +- Codecs signatures unified and pass **options through the call chain + Revision 0.3.4, released 07-09-2017 ----------------------------------- diff --git a/pyasn1/__init__.py b/pyasn1/__init__.py index 8b713b4..26495d5 100644 --- a/pyasn1/__init__.py +++ b/pyasn1/__init__.py @@ -1,7 +1,7 @@ import sys # http://www.python.org/dev/peps/pep-0396/ -__version__ = '0.3.4' +__version__ = '0.3.5' if sys.version_info[:2] < (2, 4): raise RuntimeError('PyASN1 requires Python 2.4 or later') diff --git a/pyasn1/codec/ber/decoder.py b/pyasn1/codec/ber/decoder.py index 4fff81b..5424195 100644 --- a/pyasn1/codec/ber/decoder.py +++ b/pyasn1/codec/ber/decoder.py @@ -18,12 +18,16 @@ noValue = base.noValue class AbstractDecoder(object): protoComponent = None - def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, - length, state, decodeFun, substrateFun): + def valueDecoder(self, substrate, asn1Spec, + tagSet=None, length=None, state=None, + decodeFun=None, substrateFun=None, + **options): raise error.PyAsn1Error('Decoder not implemented for %s' % (tagSet,)) - def indefLenValueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, - length, state, decodeFun, substrateFun): + def indefLenValueDecoder(self, substrate, asn1Spec, + tagSet=None, length=None, state=None, + decodeFun=None, substrateFun=None, + **options): raise error.PyAsn1Error('Indefinite length mode decoder not implemented for %s' % (tagSet,)) @@ -44,27 +48,37 @@ class AbstractSimpleDecoder(AbstractDecoder): class ExplicitTagDecoder(AbstractSimpleDecoder): protoComponent = univ.Any('') - def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, - length, state, decodeFun, substrateFun): + def valueDecoder(self, substrate, asn1Spec, + tagSet=None, length=None, state=None, + decodeFun=None, substrateFun=None, + **options): if substrateFun: return substrateFun( self._createComponent(asn1Spec, tagSet, ''), substrate, length ) + head, tail = substrate[:length], substrate[length:] - value, _ = decodeFun(head, asn1Spec, tagSet, length) + + value, _ = decodeFun(head, asn1Spec, tagSet, length, **options) + return value, tail - def indefLenValueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, - length, state, decodeFun, substrateFun): + def indefLenValueDecoder(self, substrate, asn1Spec, + tagSet=None, length=None, state=None, + decodeFun=None, substrateFun=None, + **options): if substrateFun: return substrateFun( self._createComponent(asn1Spec, tagSet, ''), substrate, length ) - value, substrate = decodeFun(substrate, asn1Spec, tagSet, length) - terminator, substrate = decodeFun(substrate, allowEoo=True) - if terminator is eoo.endOfOctets: + + value, substrate = decodeFun(substrate, asn1Spec, tagSet, length, **options) + + eooMarker, substrate = decodeFun(substrate, allowEoo=True, **options) + + if eooMarker is eoo.endOfOctets: return value, substrate else: raise error.PyAsn1Error('Missing end-of-octets terminator') @@ -76,8 +90,10 @@ explicitTagDecoder = ExplicitTagDecoder() class IntegerDecoder(AbstractSimpleDecoder): protoComponent = univ.Integer(0) - def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length, - state, decodeFun, substrateFun): + def valueDecoder(self, substrate, asn1Spec, + tagSet=None, length=None, state=None, + decodeFun=None, substrateFun=None, + **options): if tagSet[0].tagFormat != tag.tagFormatSimple: raise error.PyAsn1Error('Simple tag format expected') @@ -103,8 +119,10 @@ class BitStringDecoder(AbstractSimpleDecoder): protoComponent = univ.BitString(()) supportConstructedForm = True - def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length, - state, decodeFun, substrateFun): + def valueDecoder(self, substrate, asn1Spec, + tagSet=None, length=None, state=None, + decodeFun=None, substrateFun=None, + **options): head, tail = substrate[:length], substrate[length:] if tagSet[0].tagFormat == tag.tagFormatSimple: # XXX what tag to check? if not head: @@ -127,20 +145,23 @@ class BitStringDecoder(AbstractSimpleDecoder): return substrateFun(bitString, substrate, length) while head: - component, head = decodeFun(head, self.protoComponent) + component, head = decodeFun(head, self.protoComponent, **options) bitString += component return bitString, tail - def indefLenValueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, - length, state, decodeFun, substrateFun): + def indefLenValueDecoder(self, substrate, asn1Spec, + tagSet=None, length=None, state=None, + decodeFun=None, substrateFun=None, + **options): bitString = self._createComponent(asn1Spec, tagSet) if substrateFun: return substrateFun(bitString, substrate, length) while substrate: - component, substrate = decodeFun(substrate, self.protoComponent, allowEoo=True) + component, substrate = decodeFun(substrate, self.protoComponent, + allowEoo=True, **options) if component is eoo.endOfOctets: break @@ -156,8 +177,10 @@ class OctetStringDecoder(AbstractSimpleDecoder): protoComponent = univ.OctetString('') supportConstructedForm = True - def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length, - state, decodeFun, substrateFun): + def valueDecoder(self, substrate, asn1Spec, + tagSet=None, length=None, state=None, + decodeFun=None, substrateFun=None, + **options): head, tail = substrate[:length], substrate[length:] if substrateFun: @@ -177,13 +200,16 @@ class OctetStringDecoder(AbstractSimpleDecoder): while head: component, head = decodeFun(head, self.protoComponent, - substrateFun=substrateFun) + substrateFun=substrateFun, + **options) header += component return self._createComponent(asn1Spec, tagSet, header), tail - def indefLenValueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, - length, state, decodeFun, substrateFun): + def indefLenValueDecoder(self, substrate, asn1Spec, + tagSet=None, length=None, state=None, + decodeFun=None, substrateFun=None, + **options): if substrateFun and substrateFun is not self.substrateCollector: asn1Object = self._createComponent(asn1Spec, tagSet) return substrateFun(asn1Object, substrate, length) @@ -197,7 +223,7 @@ class OctetStringDecoder(AbstractSimpleDecoder): component, substrate = decodeFun(substrate, self.protoComponent, substrateFun=substrateFun, - allowEoo=True) + allowEoo=True, **options) if component is eoo.endOfOctets: break header += component @@ -205,14 +231,17 @@ class OctetStringDecoder(AbstractSimpleDecoder): raise error.SubstrateUnderrunError( 'No EOO seen before substrate ends' ) + return self._createComponent(asn1Spec, tagSet, header), substrate class NullDecoder(AbstractSimpleDecoder): protoComponent = univ.Null('') - def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, - length, state, decodeFun, substrateFun): + def valueDecoder(self, substrate, asn1Spec, + tagSet=None, length=None, state=None, + decodeFun=None, substrateFun=None, + **options): if tagSet[0].tagFormat != tag.tagFormatSimple: raise error.PyAsn1Error('Simple tag format expected') @@ -230,9 +259,10 @@ class NullDecoder(AbstractSimpleDecoder): class ObjectIdentifierDecoder(AbstractSimpleDecoder): protoComponent = univ.ObjectIdentifier(()) - def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length, - state, decodeFun, substrateFun): - + def valueDecoder(self, substrate, asn1Spec, + tagSet=None, length=None, state=None, + decodeFun=None, substrateFun=None, + **options): if tagSet[0].tagFormat != tag.tagFormatSimple: raise error.PyAsn1Error('Simple tag format expected') @@ -286,8 +316,10 @@ class ObjectIdentifierDecoder(AbstractSimpleDecoder): class RealDecoder(AbstractSimpleDecoder): protoComponent = univ.Real() - def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, - length, state, decodeFun, substrateFun): + def valueDecoder(self, substrate, asn1Spec, + tagSet=None, length=None, state=None, + decodeFun=None, substrateFun=None, + **options): if tagSet[0].tagFormat != tag.tagFormatSimple: raise error.PyAsn1Error('Simple tag format expected') @@ -371,11 +403,11 @@ class UniversalConstructedTypeDecoder(AbstractConstructedDecoder): def _getComponentPositionByType(self, asn1Object, tagSet, idx): raise NotImplementedError() - def _decodeComponents(self, substrate, decodeFun, tagSet, allowEoo=True): + def _decodeComponents(self, substrate, tagSet=None, decodeFun=None, **options): components = [] componentTypes = set() while substrate: - component, substrate = decodeFun(substrate, allowEoo=True) + component, substrate = decodeFun(substrate, **options) if component is eoo.endOfOctets: break components.append(component) @@ -406,8 +438,10 @@ class UniversalConstructedTypeDecoder(AbstractConstructedDecoder): return asn1Object, substrate - def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, - length, state, decodeFun, substrateFun): + def valueDecoder(self, substrate, asn1Spec, + tagSet=None, length=None, state=None, + decodeFun=None, substrateFun=None, + **options): if tagSet[0].tagFormat != tag.tagFormatConstructed: raise error.PyAsn1Error('Constructed tag format expected') @@ -424,7 +458,9 @@ class UniversalConstructedTypeDecoder(AbstractConstructedDecoder): return substrateFun(asn1Object, substrate, length) if asn1Spec is None: - asn1Object, trailing = self._decodeComponents(head, decodeFun, tagSet) + asn1Object, trailing = self._decodeComponents( + head, tagSet=tagSet, decodeFun=decodeFun, **options + ) if trailing: raise error.PyAsn1Error('Unused trailing %d octets encountered' % len(trailing)) return asn1Object, tail @@ -455,10 +491,10 @@ class UniversalConstructedTypeDecoder(AbstractConstructedDecoder): asn1Spec = namedTypes[idx].asn1Object except IndexError: raise error.PyAsn1Error( - 'Excessive components decoded at %r'(asn1Object,) + 'Excessive components decoded at %r' % (asn1Object,) ) - component, head = decodeFun(head, asn1Spec) + component, head = decodeFun(head, asn1Spec, **options) if not isDeterministic and namedTypes: if isSetType: @@ -485,7 +521,7 @@ class UniversalConstructedTypeDecoder(AbstractConstructedDecoder): asn1Spec = asn1Object.componentType idx = 0 while head: - component, head = decodeFun(head, asn1Spec) + component, head = decodeFun(head, asn1Spec, **options) asn1Object.setComponentByPosition( idx, component, verifyConstraints=False, @@ -497,8 +533,10 @@ class UniversalConstructedTypeDecoder(AbstractConstructedDecoder): return asn1Object, tail - def indefLenValueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, - length, state, decodeFun, substrateFun): + def indefLenValueDecoder(self, substrate, asn1Spec, + tagSet=None, length=None, state=None, + decodeFun=None, substrateFun=None, + **options): if tagSet[0].tagFormat != tag.tagFormatConstructed: raise error.PyAsn1Error('Constructed tag format expected') @@ -513,7 +551,9 @@ class UniversalConstructedTypeDecoder(AbstractConstructedDecoder): return substrateFun(asn1Object, substrate, length) if asn1Spec is None: - return self._decodeComponents(substrate, decodeFun, tagSet, allowEoo=True) + return self._decodeComponents( + substrate, tagSet=tagSet, decodeFun=decodeFun, allowEoo=True, **options + ) asn1Object = asn1Spec.clone() @@ -544,7 +584,7 @@ class UniversalConstructedTypeDecoder(AbstractConstructedDecoder): 'Excessive components decoded at %r' % (asn1Object,) ) - component, substrate = decodeFun(substrate, asn1Spec, allowEoo=True) + component, substrate = decodeFun(substrate, asn1Spec, allowEoo=True, **options) if component is eoo.endOfOctets: break @@ -578,7 +618,7 @@ class UniversalConstructedTypeDecoder(AbstractConstructedDecoder): asn1Spec = asn1Object.componentType idx = 0 while substrate: - component, substrate = decodeFun(substrate, asn1Spec, allowEoo=True) + component, substrate = decodeFun(substrate, asn1Spec, allowEoo=True, **options) if component is eoo.endOfOctets: break asn1Object.setComponentByPosition( @@ -625,8 +665,10 @@ class SetOfDecoder(SetOrSetOfDecoder): class ChoiceDecoder(AbstractConstructedDecoder): protoComponent = univ.Choice() - def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, - length, state, decodeFun, substrateFun): + def valueDecoder(self, substrate, asn1Spec, + tagSet=None, length=None, state=None, + decodeFun=None, substrateFun=None, + **options): head, tail = substrate[:length], substrate[length:] if asn1Spec is None: asn1Object = self.protoComponent.clone(tagSet=tagSet) @@ -636,11 +678,12 @@ class ChoiceDecoder(AbstractConstructedDecoder): return substrateFun(asn1Object, substrate, length) if asn1Object.tagSet == tagSet: # explicitly tagged Choice component, head = decodeFun( - head, asn1Object.componentTagMap + head, asn1Object.componentTagMap, **options ) else: component, head = decodeFun( - head, asn1Object.componentTagMap, tagSet, length, state + head, asn1Object.componentTagMap, + tagSet, length, state, **options ) effectiveTagSet = component.effectiveTagSet asn1Object.setComponentByType( @@ -651,8 +694,10 @@ class ChoiceDecoder(AbstractConstructedDecoder): ) return asn1Object, tail - def indefLenValueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, - length, state, decodeFun, substrateFun): + def indefLenValueDecoder(self, substrate, asn1Spec, + tagSet=None, length=None, state=None, + decodeFun=None, substrateFun=None, + **options): if asn1Spec is None: asn1Object = self.protoComponent.clone(tagSet=tagSet) else: @@ -660,14 +705,19 @@ class ChoiceDecoder(AbstractConstructedDecoder): if substrateFun: return substrateFun(asn1Object, substrate, length) if asn1Object.tagSet == tagSet: # explicitly tagged Choice - component, substrate = decodeFun(substrate, asn1Object.componentType.tagMapUnique) + component, substrate = decodeFun( + substrate, asn1Object.componentType.tagMapUnique, **options + ) # eat up EOO marker - eooMarker, substrate = decodeFun(substrate, allowEoo=True) + eooMarker, substrate = decodeFun( + substrate, allowEoo=True, **options + ) if eooMarker is not eoo.endOfOctets: raise error.PyAsn1Error('No EOO seen before substrate ends') else: component, substrate = decodeFun( - substrate, asn1Object.componentType.tagMapUnique, tagSet, length, state + substrate, asn1Object.componentType.tagMapUnique, + tagSet, length, state, **options ) effectiveTagSet = component.effectiveTagSet asn1Object.setComponentByType( @@ -682,24 +732,35 @@ class ChoiceDecoder(AbstractConstructedDecoder): class AnyDecoder(AbstractSimpleDecoder): protoComponent = univ.Any() - def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, - length, state, decodeFun, substrateFun): + def valueDecoder(self, substrate, asn1Spec, + tagSet=None, length=None, state=None, + decodeFun=None, substrateFun=None, + **options): if asn1Spec is None or asn1Spec is not None and tagSet != asn1Spec.tagSet: + fullSubstrate=options['fullSubstrate'] + # untagged Any container, recover inner header substrate length += len(fullSubstrate) - len(substrate) substrate = fullSubstrate + if substrateFun: return substrateFun(self._createComponent(asn1Spec, tagSet), substrate, length) + head, tail = substrate[:length], substrate[length:] + return self._createComponent(asn1Spec, tagSet, value=head), tail - def indefLenValueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, - length, state, decodeFun, substrateFun): + def indefLenValueDecoder(self, substrate, asn1Spec, + tagSet=None, length=None, state=None, + decodeFun=None, substrateFun=None, + **options): if asn1Spec is not None and tagSet == asn1Spec.tagSet: # tagged Any type -- consume header substrate header = null else: + fullSubstrate=options['fullSubstrate'] + # untagged Any, recover header substrate header = fullSubstrate[:-len(substrate)] @@ -716,7 +777,7 @@ class AnyDecoder(AbstractSimpleDecoder): while substrate: component, substrate = decodeFun(substrate, asn1Spec, substrateFun=substrateFun, - allowEoo=True) + allowEoo=True, **options) if component is eoo.endOfOctets: break header += component @@ -863,9 +924,11 @@ class Decoder(object): self.__tagSetCache = {} self.__eooSentinel = ints2octs((0, 0)) - def __call__(self, substrate, asn1Spec=None, tagSet=None, - length=None, state=stDecodeTag, recursiveFlag=True, - substrateFun=None, allowEoo=False): + def __call__(self, substrate, asn1Spec=None, + tagSet=None, length=None, state=stDecodeTag, + decodeFun=None, substrateFun=None, + **options): + if debug.logger & debug.flagDecoder: logger = debug.logger else: @@ -874,6 +937,8 @@ class Decoder(object): if logger: logger('decoder called at scope %s with state %d, working with up to %d octets of substrate: %s' % (debug.scope, state, len(substrate), debug.hexdump(substrate))) + allowEoo = options.pop('allowEoo', False) + # Look for end-of-octets sentinel if allowEoo and self.supportIndefLength: if substrate[:2] == self.__eooSentinel: @@ -1074,19 +1139,24 @@ class Decoder(object): logger('codec %s chosen by ASN.1 spec, decoding %s' % (state is stDecodeValue and concreteDecoder.__class__.__name__ or "", state is stDecodeValue and 'value' or 'as explicit tag')) debug.scope.push(chosenSpec is None and '?' or chosenSpec.__class__.__name__) if state is stDecodeValue: - if not recursiveFlag and not substrateFun: # deprecate this - def substrateFun(a, b, c): - return a, b[:c] + if not options.get('recursiveFlag', True) and not substrateFun: # deprecate this + substrateFun = lambda a, b, c: (a, b[:c]) + + options.update(fullSubstrate=fullSubstrate) if length == -1: # indef length value, substrate = concreteDecoder.indefLenValueDecoder( - fullSubstrate, substrate, asn1Spec, tagSet, length, - stGetValueDecoder, self, substrateFun + substrate, asn1Spec, + tagSet, length, stGetValueDecoder, + self, substrateFun, + **options ) else: value, substrate = concreteDecoder.valueDecoder( - fullSubstrate, substrate, asn1Spec, tagSet, length, - stGetValueDecoder, self, substrateFun + substrate, asn1Spec, + tagSet, length, stGetValueDecoder, + self, substrateFun, + **options ) if logger: logger('codec %s yields type %s, value:\n%s\n...remaining substrate is: %s' % (concreteDecoder.__class__.__name__, value.__class__.__name__, value.prettyPrint(), substrate and debug.hexdump(substrate) or '')) diff --git a/pyasn1/codec/ber/encoder.py b/pyasn1/codec/ber/encoder.py index 10527ae..758c1a9 100644 --- a/pyasn1/codec/ber/encoder.py +++ b/pyasn1/codec/ber/encoder.py @@ -47,29 +47,32 @@ class AbstractItemEncoder(object): raise error.PyAsn1Error('Length octets overflow (%d)' % substrateLen) return (0x80 | substrateLen,) + substrate - def encodeValue(self, encodeFun, value, defMode, maxChunkSize, ifNotEmpty=False): + def encodeValue(self, value, encodeFun, **options): raise error.PyAsn1Error('Not implemented') def _encodeEndOfOctets(self, encodeFun, defMode): if defMode or not self.supportIndefLenMode: return null else: - return encodeFun(eoo.endOfOctets, defMode) + return encodeFun(eoo.endOfOctets, defMode=defMode) - def encode(self, encodeFun, value, defMode, maxChunkSize, ifNotEmpty=False): + def encode(self, value, encodeFun, **options): substrate, isConstructed, isOctets = self.encodeValue( - encodeFun, value, defMode, maxChunkSize, ifNotEmpty=ifNotEmpty + value, encodeFun, **options ) - if ifNotEmpty and not substrate: + if options.get('ifNotEmpty', False) and not substrate: return substrate tagSet = value.tagSet # tagged value? if tagSet: + defMode = options.get('defMode', True) + if not isConstructed: # primitive form implies definite mode defMode = True + header = self.encodeTag(tagSet[-1], isConstructed) header += self.encodeLength(len(substrate), defMode) @@ -86,17 +89,18 @@ class AbstractItemEncoder(object): class EndOfOctetsEncoder(AbstractItemEncoder): - def encodeValue(self, encodeFun, value, defMode, maxChunkSize, ifNotEmpty=False): + def encodeValue(self, value, encodeFun, **options): return null, False, True class ExplicitlyTaggedItemEncoder(AbstractItemEncoder): - def encodeValue(self, encodeFun, value, defMode, maxChunkSize, ifNotEmpty=False): + def encodeValue(self, value, encodeFun, **options): if isinstance(value, base.AbstractConstructedAsn1Item): value = value.clone(tagSet=value.tagSet[:-1], cloneValueFlag=True) else: value = value.clone(tagSet=value.tagSet[:-1]) - return encodeFun(value, defMode, maxChunkSize, ifNotEmpty=ifNotEmpty), True, True + + return encodeFun(value, **options), True, True explicitlyTaggedItemEncoder = ExplicitlyTaggedItemEncoder() @@ -105,7 +109,7 @@ explicitlyTaggedItemEncoder = ExplicitlyTaggedItemEncoder() class BooleanEncoder(AbstractItemEncoder): supportIndefLenMode = False - def encodeValue(self, encodeFun, value, defMode, maxChunkSize, ifNotEmpty=False): + def encodeValue(self, value, encodeFun, **options): return value and (1,) or (0,), False, False @@ -113,7 +117,7 @@ class IntegerEncoder(AbstractItemEncoder): supportIndefLenMode = False supportCompactZero = False - def encodeValue(self, encodeFun, value, defMode, maxChunkSize, ifNotEmpty=False): + def encodeValue(self, value, encodeFun, **options): if value == 0: # de-facto way to encode zero if self.supportCompactZero: @@ -125,13 +129,14 @@ class IntegerEncoder(AbstractItemEncoder): class BitStringEncoder(AbstractItemEncoder): - def encodeValue(self, encodeFun, value, defMode, maxChunkSize, ifNotEmpty=False): + def encodeValue(self, value, encodeFun, **options): valueLength = len(value) if valueLength % 8: alignedValue = value << (8 - valueLength % 8) else: alignedValue = value + maxChunkSize = options.get('maxChunkSize', 0) if not maxChunkSize or len(alignedValue) <= maxChunkSize * 8: substrate = alignedValue.asOctets() return int2oct(len(substrate) * 8 - valueLength) + substrate, False, True @@ -141,13 +146,14 @@ class BitStringEncoder(AbstractItemEncoder): while stop < valueLength: start = stop stop = min(start + maxChunkSize * 8, valueLength) - substrate += encodeFun(alignedValue[start:stop], defMode, maxChunkSize, ifNotEmpty=ifNotEmpty) + substrate += encodeFun(alignedValue[start:stop], **options) return substrate, True, True class OctetStringEncoder(AbstractItemEncoder): - def encodeValue(self, encodeFun, value, defMode, maxChunkSize, ifNotEmpty=False): + def encodeValue(self, value, encodeFun, **options): + maxChunkSize = options.get('maxChunkSize', 0) if not maxChunkSize or len(value) <= maxChunkSize: return value.asOctets(), False, True else: @@ -157,7 +163,7 @@ class OctetStringEncoder(AbstractItemEncoder): v = value.clone(value[pos:pos + maxChunkSize]) if not v: break - substrate += encodeFun(v, defMode, maxChunkSize, ifNotEmpty=ifNotEmpty) + substrate += encodeFun(v, **options) pos += maxChunkSize return substrate, True, True @@ -166,14 +172,14 @@ class OctetStringEncoder(AbstractItemEncoder): class NullEncoder(AbstractItemEncoder): supportIndefLenMode = False - def encodeValue(self, encodeFun, value, defMode, maxChunkSize, ifNotEmpty=False): + def encodeValue(self, value, encodeFun, **options): return null, False, True class ObjectIdentifierEncoder(AbstractItemEncoder): supportIndefLenMode = False - def encodeValue(self, encodeFun, value, defMode, maxChunkSize, ifNotEmpty=False): + def encodeValue(self, value, encodeFun, **options): oid = value.asTuple() # Build the first pair @@ -271,7 +277,7 @@ class RealEncoder(AbstractItemEncoder): encbase = encBase[i] return sign, m, encbase, e - def encodeValue(self, encodeFun, value, defMode, maxChunkSize, ifNotEmpty=False): + def encodeValue(self, value, encodeFun, **options): if value.isPlusInf: return (0x40,), False, False if value.isMinusInf: @@ -342,10 +348,12 @@ class RealEncoder(AbstractItemEncoder): class SequenceEncoder(AbstractItemEncoder): - def encodeValue(self, encodeFun, value, defMode, maxChunkSize, ifNotEmpty=False): + def encodeValue(self, value, encodeFun, **options): value.verifySizeSpec() + namedTypes = value.componentType substrate = null + idx = len(value) while idx > 0: idx -= 1 @@ -354,29 +362,30 @@ class SequenceEncoder(AbstractItemEncoder): continue if namedTypes[idx].isDefaulted and value[idx] == namedTypes[idx].asn1Object: continue - substrate = encodeFun(value[idx], defMode, maxChunkSize) + substrate + substrate = encodeFun(value[idx], **options) + substrate + return substrate, True, True class SequenceOfEncoder(AbstractItemEncoder): - def encodeValue(self, encodeFun, value, defMode, maxChunkSize, ifNotEmpty=False): + def encodeValue(self, value, encodeFun, **options): value.verifySizeSpec() substrate = null idx = len(value) while idx > 0: idx -= 1 - substrate = encodeFun(value[idx], defMode, maxChunkSize, ifNotEmpty=False) + substrate + substrate = encodeFun(value[idx], **options) + substrate return substrate, True, True class ChoiceEncoder(AbstractItemEncoder): - def encodeValue(self, encodeFun, value, defMode, maxChunkSize, ifNotEmpty=False): - return encodeFun(value.getComponent(), defMode, maxChunkSize, ifNotEmpty=False), True, True + def encodeValue(self, value, encodeFun, **options): + return encodeFun(value.getComponent(), **options), True, True class AnyEncoder(OctetStringEncoder): - def encodeValue(self, encodeFun, value, defMode, maxChunkSize, ifNotEmpty=False): - return value.asOctets(), defMode == False, True + def encodeValue(self, value, encodeFun, **options): + return value.asOctets(), options.get('defMode', True) == False, True tagMap = { @@ -455,16 +464,20 @@ class Encoder(object): self.__tagMap = tagMap self.__typeMap = typeMap - def __call__(self, value, defMode=True, maxChunkSize=0, ifNotEmpty=False): - if not defMode and not self.supportIndefLength: + def __call__(self, value, **options): + if not options.get('defMode', True) and not self.supportIndefLength: raise error.PyAsn1Error('Indefinite length encoding not supported by this codec') + if debug.logger & debug.flagEncoder: logger = debug.logger else: logger = None + if logger: logger('encoder called in %sdef mode, chunk size %s for type %s, value:\n%s' % (not defMode and 'in' or '', maxChunkSize, value.prettyPrintType(), value.prettyPrint())) + tagSet = value.tagSet + if len(tagSet) > 1: concreteEncoder = explicitlyTaggedItemEncoder else: @@ -477,11 +490,12 @@ class Encoder(object): concreteEncoder = self.__tagMap[baseTagSet] except KeyError: raise error.PyAsn1Error('No encoder for %s' % (value,)) + if logger: logger('using value codec %s chosen by %s' % (concreteEncoder.__class__.__name__, tagSet)) - substrate = concreteEncoder.encode( - self, value, defMode, maxChunkSize, ifNotEmpty=ifNotEmpty - ) + + substrate = concreteEncoder.encode(value, self, **options) + if logger: logger('codec %s built %s octets of substrate: %s\nencoder completed' % (concreteEncoder, len(substrate), debug.hexdump(substrate))) return substrate diff --git a/pyasn1/codec/cer/decoder.py b/pyasn1/codec/cer/decoder.py index c7e2174..5e3e8bf 100644 --- a/pyasn1/codec/cer/decoder.py +++ b/pyasn1/codec/cer/decoder.py @@ -15,8 +15,10 @@ __all__ = ['decode'] class BooleanDecoder(decoder.AbstractSimpleDecoder): protoComponent = univ.Boolean(0) - def valueDecoder(self, fullSubstrate, substrate, asn1Spec, tagSet, length, - state, decodeFun, substrateFun): + def valueDecoder(self, substrate, asn1Spec, + tagSet=None, length=None, state=None, + decodeFun=None, substrateFun=None, + **options): head, tail = substrate[:length], substrate[length:] if not head or length != 1: raise error.PyAsn1Error('Not single-octet Boolean payload') diff --git a/pyasn1/codec/cer/encoder.py b/pyasn1/codec/cer/encoder.py index c6f92ca..50cb346 100644 --- a/pyasn1/codec/cer/encoder.py +++ b/pyasn1/codec/cer/encoder.py @@ -14,7 +14,7 @@ __all__ = ['encode'] class BooleanEncoder(encoder.IntegerEncoder): - def encodeValue(self, encodeFun, value, defMode, maxChunkSize, ifNotEmpty=False): + def encodeValue(self, value, encodeFun, **options): if value == 0: substrate = (0,) else: @@ -23,16 +23,18 @@ class BooleanEncoder(encoder.IntegerEncoder): class BitStringEncoder(encoder.BitStringEncoder): - def encodeValue(self, encodeFun, value, defMode, maxChunkSize, ifNotEmpty=False): + def encodeValue(self, value, encodeFun, **options): + options.update(maxChunkSize=1000) return encoder.BitStringEncoder.encodeValue( - self, encodeFun, value, defMode, 1000, ifNotEmpty=ifNotEmpty + self, value, encodeFun, **options ) class OctetStringEncoder(encoder.OctetStringEncoder): - def encodeValue(self, encodeFun, value, defMode, maxChunkSize, ifNotEmpty=False): + def encodeValue(self, value, encodeFun, **options): + options.update(maxChunkSize=1000) return encoder.OctetStringEncoder.encodeValue( - self, encodeFun, value, defMode, 1000, ifNotEmpty=ifNotEmpty + self, value, encodeFun, **options ) @@ -52,7 +54,7 @@ class TimeEncoderMixIn(object): minLength = 12 maxLength = 19 - def encodeValue(self, encodeFun, value, defMode, maxChunkSize, ifNotEmpty=False): + def encodeValue(self, value, encodeFun, **options): # Encoding constraints: # - minutes are mandatory, seconds are optional # - subseconds must NOT be zero @@ -74,8 +76,10 @@ class TimeEncoderMixIn(object): if self.commachar in octets: raise error.PyAsn1Error('Comma in fractions disallowed: %r' % value) + options.update(maxChunkSize=1000) + return encoder.OctetStringEncoder.encodeValue( - self, encodeFun, value, defMode, 1000, ifNotEmpty=ifNotEmpty + self, value, encodeFun, **options ) @@ -95,7 +99,7 @@ class SetOfEncoder(encoder.SequenceOfEncoder): # sort by tags regardless of the Choice value (static sort) return sorted(components, key=lambda x: isinstance(x, univ.Choice) and x.minTagSet or x.tagSet) - def encodeValue(self, encodeFun, value, defMode, maxChunkSize, ifNotEmpty=False): + def encodeValue(self, value, encodeFun, **options): value.verifySizeSpec() substrate = null idx = len(value) @@ -115,9 +119,10 @@ class SetOfEncoder(encoder.SequenceOfEncoder): compsMap[id(value[idx])] = namedTypes and namedTypes[idx].isOptional for comp in self._sortComponents(comps): - substrate += encodeFun(comp, defMode, maxChunkSize, ifNotEmpty=compsMap[id(comp)]) + options.update(ifNotEmpty=compsMap[id(comp)]) + substrate += encodeFun(comp, **options) else: - components = [encodeFun(x, defMode, maxChunkSize) for x in value] + components = [encodeFun(x, **options) for x in value] # sort by serialized and padded components if len(components) > 1: @@ -136,10 +141,12 @@ class SetOfEncoder(encoder.SequenceOfEncoder): class SequenceEncoder(encoder.SequenceEncoder): - def encodeValue(self, encodeFun, value, defMode, maxChunkSize, ifNotEmpty=False): + def encodeValue(self, value, encodeFun, **options): value.verifySizeSpec() + namedTypes = value.componentType substrate = null + idx = len(value) while idx > 0: idx -= 1 @@ -149,24 +156,25 @@ class SequenceEncoder(encoder.SequenceEncoder): if namedTypes[idx].isDefaulted and value[idx] == namedTypes[idx].asn1Object: continue - substrate = encodeFun(value[idx], defMode, maxChunkSize, - namedTypes and namedTypes[idx].isOptional) + substrate + options.update(ifNotEmpty=namedTypes and namedTypes[idx].isOptional) + + substrate = encodeFun(value[idx], **options) + substrate return substrate, True, True class SequenceOfEncoder(encoder.SequenceOfEncoder): - def encodeValue(self, encodeFun, value, defMode, maxChunkSize, ifNotEmpty=False): + def encodeValue(self, value, encodeFun, **options): substrate = null idx = len(value) - if ifNotEmpty and not idx: + if options.get('ifNotEmpty', False) and not idx: return substrate, True, True value.verifySizeSpec() while idx > 0: idx -= 1 - substrate = encodeFun(value[idx], defMode, maxChunkSize, ifNotEmpty=False) + substrate + substrate = encodeFun(value[idx], **options) + substrate return substrate, True, True @@ -200,9 +208,12 @@ typeMap.update({ class Encoder(encoder.Encoder): + supportIndefLength = True - def __call__(self, value, defMode=False, maxChunkSize=0, ifNotEmpty=False): - return encoder.Encoder.__call__(self, value, defMode, maxChunkSize, ifNotEmpty) + def __call__(self, value, **options): + if 'defMode' not in options: + options.update(defMode=False) + return encoder.Encoder.__call__(self, value, **options) #: Turns ASN.1 object into CER octet stream. #: diff --git a/pyasn1/codec/der/encoder.py b/pyasn1/codec/der/encoder.py index 6782819..59dd512 100644 --- a/pyasn1/codec/der/encoder.py +++ b/pyasn1/codec/der/encoder.py @@ -6,21 +6,20 @@ # from pyasn1.type import univ from pyasn1.codec.cer import encoder -from pyasn1 import error __all__ = ['encode'] class BitStringEncoder(encoder.BitStringEncoder): - def encodeValue(self, encodeFun, value, defMode, maxChunkSize, ifNotEmpty=False): + def encodeValue(self, value, encodeFun, **options): return encoder.BitStringEncoder.encodeValue( - self, encodeFun, value, defMode, 0, ifNotEmpty=ifNotEmpty + self, value, encodeFun, **options ) class OctetStringEncoder(encoder.OctetStringEncoder): - def encodeValue(self, encodeFun, value, defMode, maxChunkSize, ifNotEmpty=False): + def encodeValue(self, value, encodeFun, **options): return encoder.OctetStringEncoder.encodeValue( - self, encodeFun, value, defMode, 0, ifNotEmpty=ifNotEmpty + self, value, encodeFun, **options ) class SetOfEncoder(encoder.SetOfEncoder): @@ -50,10 +49,10 @@ typeMap.update({ class Encoder(encoder.Encoder): supportIndefLength = False - def __call__(self, value, defMode=True, maxChunkSize=0, ifNotEmpty=False): - if not defMode: - raise error.PyAsn1Error('DER forbids indefinite length mode') - return encoder.Encoder.__call__(self, value, defMode, maxChunkSize, ifNotEmpty=ifNotEmpty) + def __call__(self, value, **options): + if 'defMode' not in options: + options.update(defMode=True) + return encoder.Encoder.__call__(self, value, **options) #: Turns ASN.1 object into DER octet stream. #: diff --git a/pyasn1/codec/native/decoder.py b/pyasn1/codec/native/decoder.py index 4c7df95..ba9811b 100644 --- a/pyasn1/codec/native/decoder.py +++ b/pyasn1/codec/native/decoder.py @@ -11,47 +11,47 @@ __all__ = ['decode'] class AbstractScalarDecoder(object): - def __call__(self, pyObject, asn1Spec, decoderFunc=None): + def __call__(self, pyObject, asn1Spec, decodeFun=None, **options): return asn1Spec.clone(pyObject) class BitStringDecoder(AbstractScalarDecoder): - def __call__(self, pyObject, asn1Spec, decoderFunc=None): + def __call__(self, pyObject, asn1Spec, decodeFun=None, **options): return asn1Spec.clone(univ.BitString.fromBinaryString(pyObject)) class SequenceOrSetDecoder(object): - def __call__(self, pyObject, asn1Spec, decoderFunc): + def __call__(self, pyObject, asn1Spec, decodeFun=None, **options): asn1Value = asn1Spec.clone() componentsTypes = asn1Spec.componentType for field in asn1Value: if field in pyObject: - asn1Value[field] = decoderFunc(pyObject[field], componentsTypes[field].asn1Object) + asn1Value[field] = decodeFun(pyObject[field], componentsTypes[field].asn1Object, **options) return asn1Value class SequenceOfOrSetOfDecoder(object): - def __call__(self, pyObject, asn1Spec, decoderFunc): + def __call__(self, pyObject, asn1Spec, decodeFun=None, **options): asn1Value = asn1Spec.clone() for pyValue in pyObject: - asn1Value.append(decoderFunc(pyValue, asn1Spec.componentType.asn1Object)) + asn1Value.append(decodeFun(pyValue, asn1Spec.componentType.asn1Object), **options) return asn1Value class ChoiceDecoder(object): - def __call__(self, pyObject, asn1Spec, decoderFunc): + def __call__(self, pyObject, asn1Spec, decodeFun=None, **options): asn1Value = asn1Spec.clone() componentsTypes = asn1Spec.componentType for field in pyObject: if field in componentsTypes: - asn1Value[field] = decoderFunc(pyObject[field], componentsTypes[field].asn1Object) + asn1Value[field] = decodeFun(pyObject[field], componentsTypes[field].asn1Object, **options) break return asn1Value @@ -130,7 +130,7 @@ class Decoder(object): self.__tagMap = tagMap self.__typeMap = typeMap - def __call__(self, pyObject, asn1Spec): + def __call__(self, pyObject, asn1Spec, **options): if debug.logger & debug.flagDecoder: logger = debug.logger else: @@ -144,9 +144,11 @@ class Decoder(object): try: valueDecoder = self.__typeMap[asn1Spec.typeId] + except KeyError: # use base type for codec lookup to recover untagged types baseTagSet = tag.TagSet(asn1Spec.tagSet.baseTag, asn1Spec.tagSet.baseTag) + try: valueDecoder = self.__tagMap[baseTagSet] except KeyError: @@ -155,7 +157,7 @@ class Decoder(object): if logger: logger('calling decoder %s on Python type %s <%s>' % (type(valueDecoder).__name__, type(pyObject).__name__, repr(pyObject))) - value = valueDecoder(pyObject, asn1Spec, self) + value = valueDecoder(pyObject, asn1Spec, self, **options) if logger: logger('decoder %s produced ASN.1 type %s <%s>' % (type(valueDecoder).__name__, type(value).__name__, repr(value))) diff --git a/pyasn1/codec/native/encoder.py b/pyasn1/codec/native/encoder.py index ab4b71a..78fe7c2 100644 --- a/pyasn1/codec/native/encoder.py +++ b/pyasn1/codec/native/encoder.py @@ -17,72 +17,76 @@ __all__ = ['encode'] class AbstractItemEncoder(object): - def encode(self, encodeFun, value): + def encode(self, value, encodeFun, **options): raise error.PyAsn1Error('Not implemented') class ExplicitlyTaggedItemEncoder(AbstractItemEncoder): - def encode(self, encodeFun, value): + def encode(self, value, encodeFun, **options): if isinstance(value, base.AbstractConstructedAsn1Item): value = value.clone(tagSet=value.tagSet[:-1], cloneValueFlag=1) else: value = value.clone(tagSet=value.tagSet[:-1]) - return encodeFun(value) + + return encodeFun(value, **options) explicitlyTaggedItemEncoder = ExplicitlyTaggedItemEncoder() class BooleanEncoder(AbstractItemEncoder): - def encode(self, encodeFun, value): + def encode(self, value, encodeFun, **options): return bool(value) class IntegerEncoder(AbstractItemEncoder): - def encode(self, encodeFun, value): + def encode(self, value, encodeFun, **options): return int(value) class BitStringEncoder(AbstractItemEncoder): - def encode(self, encodeFun, value): + def encode(self, value, encodeFun, **options): return str(value) class OctetStringEncoder(AbstractItemEncoder): - def encode(self, encodeFun, value): + def encode(self, value, encodeFun, **options): return value.asOctets() class TextStringEncoder(AbstractItemEncoder): - def encode(self, encodeFun, value): + def encode(self, value, encodeFun, **options): return value.prettyPrint() class NullEncoder(AbstractItemEncoder): - def encode(self, encodeFun, value): + def encode(self, value, encodeFun, **options): return None class ObjectIdentifierEncoder(AbstractItemEncoder): - def encode(self, encodeFun, value): + def encode(self, value, encodeFun, **options): return str(value) class RealEncoder(AbstractItemEncoder): - def encode(self, encodeFun, value): + def encode(self, value, encodeFun, **options): return float(value) class SetEncoder(AbstractItemEncoder): protoDict = dict - def encode(self, encodeFun, value): + + def encode(self, value, encodeFun, **options): value.verifySizeSpec() + namedTypes = value.componentType substrate = self.protoDict() + for idx, (key, subValue) in enumerate(value.items()): if namedTypes and namedTypes[idx].isOptional and not value[idx].isValue: continue - substrate[key] = encodeFun(subValue) + substrate[key] = encodeFun(subValue, **options) return substrate @@ -91,9 +95,9 @@ class SequenceEncoder(SetEncoder): class SequenceOfEncoder(AbstractItemEncoder): - def encode(self, encodeFun, value): + def encode(self, value, encodeFun, **options): value.verifySizeSpec() - return [encodeFun(x) for x in value] + return [encodeFun(x, **options) for x in value] class ChoiceEncoder(SequenceEncoder): @@ -101,7 +105,7 @@ class ChoiceEncoder(SequenceEncoder): class AnyEncoder(AbstractItemEncoder): - def encode(self, encodeFun, value): + def encode(self, value, encodeFun, **options): return value.asOctets() @@ -154,7 +158,7 @@ class Encoder(object): self.__tagMap = tagMap self.__typeMap = typeMap - def __call__(self, asn1Value): + def __call__(self, asn1Value, **options): if not isinstance(asn1Value, base.Asn1Item): raise error.PyAsn1Error('value is not valid (should be an instance of an ASN.1 Item)') @@ -184,7 +188,7 @@ class Encoder(object): if logger: logger('using value codec %s chosen by %s' % (type(concreteEncoder).__name__, tagSet)) - pyObject = concreteEncoder.encode(self, asn1Value) + pyObject = concreteEncoder.encode(asn1Value, self, **options) if logger: logger('encoder %s produced: %s' % (type(concreteEncoder).__name__, repr(pyObject))) -- cgit v1.2.1 From 8ae824dfe8fe0bae4b755f444b3c0be721f5e908 Mon Sep 17 00:00:00 2001 From: Ilya Etingof Date: Sat, 9 Sep 2017 22:21:36 +0200 Subject: WIP: avoid coping values when encoding explicit ASN.1 tags --- tests/codec/ber/test_encoder.py | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/tests/codec/ber/test_encoder.py b/tests/codec/ber/test_encoder.py index 332b071..7935afe 100644 --- a/tests/codec/ber/test_encoder.py +++ b/tests/codec/ber/test_encoder.py @@ -142,8 +142,7 @@ class ExpTaggedOctetStringEncoderTestCase(unittest.TestCase): def testIndefModeChunked(self): assert encoder.encode( self.o, defMode=False, maxChunkSize=4 - ) == ints2octs((101, 128, 36, 128, 4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, 110, 32, 4, 3, - 102, 111, 120, 0, 0, 0, 0)) + ) == ints2octs((101, 128, 36, 128, 4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, 110, 32, 4, 3, 102, 111, 120, 0, 0, 0, 0)) class NullEncoderTestCase(unittest.TestCase): @@ -618,6 +617,31 @@ class SequenceEncoderWithSchemaTestCase(unittest.TestCase): 0, 2, 1, 1, 0, 0)) +class ExpTaggedSequenceEncoderTestCase(unittest.TestCase): + def setUp(self): + s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.NamedType('number', univ.Integer()), + ) + ) + + s = s.subtype( + explicitTag=tag.Tag(tag.tagClassApplication, tag.tagFormatConstructed, 5) + ) + + s[0] = 12 + + self.s = s + + def testDefMode(self): + assert encoder.encode(self.s) == ints2octs((101, 5, 48, 3, 2, 1, 12)) + + def testIndefMode(self): + assert encoder.encode( + self.s, defMode=False + ) == ints2octs((101, 128, 48, 128, 2, 1, 12, 0, 0, 0, 0)) + + class SetEncoderTestCase(unittest.TestCase): def setUp(self): self.s = univ.Set() -- cgit v1.2.1 From 12f5f38b51144a07ec790244bb7872c22e0c7ba6 Mon Sep 17 00:00:00 2001 From: Ilya Etingof Date: Sun, 10 Sep 2017 13:34:14 +0200 Subject: avoid coping values when encoding explicit ASN.1 tags --- CHANGES.rst | 1 + pyasn1/codec/ber/encoder.py | 96 +++++++++++++++++++++++------------------- pyasn1/codec/native/encoder.py | 56 ++++++++++-------------- 3 files changed, 76 insertions(+), 77 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 8702ee1..984f678 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -3,6 +3,7 @@ Revision 0.3.5, released XX-09-2017 ----------------------------------- - Codecs signatures unified and pass **options through the call chain +- Explicit tag encoding optimized to avoid unnecessary copying Revision 0.3.4, released 07-09-2017 ----------------------------------- diff --git a/pyasn1/codec/ber/encoder.py b/pyasn1/codec/ber/encoder.py index 758c1a9..ef58137 100644 --- a/pyasn1/codec/ber/encoder.py +++ b/pyasn1/codec/ber/encoder.py @@ -4,7 +4,7 @@ # Copyright (c) 2005-2017, Ilya Etingof # License: http://pyasn1.sf.net/license.html # -from pyasn1.type import base, tag, univ, char, useful +from pyasn1.type import tag, univ, char, useful from pyasn1.codec.ber import eoo from pyasn1.compat.octets import int2oct, oct2int, ints2octs, null, str2octs from pyasn1.compat.integer import to_bytes @@ -57,31 +57,44 @@ class AbstractItemEncoder(object): return encodeFun(eoo.endOfOctets, defMode=defMode) def encode(self, value, encodeFun, **options): - substrate, isConstructed, isOctets = self.encodeValue( - value, encodeFun, **options - ) - if options.get('ifNotEmpty', False) and not substrate: + tagSet = value.tagSet + + # untagged item? + if not tagSet: + substrate, isConstructed, isOctets = self.encodeValue( + value, encodeFun, **options + ) return substrate - tagSet = value.tagSet + defMode = options.get('defMode', True) + + for idx, singleTag in enumerate(tagSet.superTags): + + defModeOverride = defMode + + # base tag? + if not idx: + substrate, isConstructed, isOctets = self.encodeValue( + value, encodeFun, **options + ) - # tagged value? - if tagSet: - defMode = options.get('defMode', True) + if options.get('ifNotEmpty', False) and not substrate: + return substrate - if not isConstructed: # primitive form implies definite mode - defMode = True + # primitive form implies definite mode + if not isConstructed: + defModeOverride = True - header = self.encodeTag(tagSet[-1], isConstructed) - header += self.encodeLength(len(substrate), defMode) + header = self.encodeTag(singleTag, isConstructed) + header += self.encodeLength(len(substrate), defModeOverride) if isOctets: substrate = ints2octs(header) + substrate else: substrate = ints2octs(header + substrate) - eoo = self._encodeEndOfOctets(encodeFun, defMode) + eoo = self._encodeEndOfOctets(encodeFun, defModeOverride) if eoo: substrate += eoo @@ -93,19 +106,6 @@ class EndOfOctetsEncoder(AbstractItemEncoder): return null, False, True -class ExplicitlyTaggedItemEncoder(AbstractItemEncoder): - def encodeValue(self, value, encodeFun, **options): - if isinstance(value, base.AbstractConstructedAsn1Item): - value = value.clone(tagSet=value.tagSet[:-1], cloneValueFlag=True) - else: - value = value.clone(tagSet=value.tagSet[:-1]) - - return encodeFun(value, **options), True, True - - -explicitlyTaggedItemEncoder = ExplicitlyTaggedItemEncoder() - - class BooleanEncoder(AbstractItemEncoder): supportIndefLenMode = False @@ -141,6 +141,11 @@ class BitStringEncoder(AbstractItemEncoder): substrate = alignedValue.asOctets() return int2oct(len(substrate) * 8 - valueLength) + substrate, False, True + # strip off explicit tags + alignedValue = alignedValue.clone( + tagSet=tag.TagSet(value.tagSet.baseTag, value.tagSet.baseTag) + ) + stop = 0 substrate = null while stop < valueLength: @@ -156,14 +161,19 @@ class OctetStringEncoder(AbstractItemEncoder): maxChunkSize = options.get('maxChunkSize', 0) if not maxChunkSize or len(value) <= maxChunkSize: return value.asOctets(), False, True + else: + # will strip off explicit tags + baseTagSet = tag.TagSet(value.tagSet.baseTag, value.tagSet.baseTag) + pos = 0 substrate = null while True: - v = value.clone(value[pos:pos + maxChunkSize]) - if not v: + chunk = value.clone(value[pos:pos + maxChunkSize], + tagSet=baseTagSet) + if not chunk: break - substrate += encodeFun(v, **options) + substrate += encodeFun(chunk, **options) pos += maxChunkSize return substrate, True, True @@ -478,21 +488,21 @@ class Encoder(object): tagSet = value.tagSet - if len(tagSet) > 1: - concreteEncoder = explicitlyTaggedItemEncoder - else: + try: + concreteEncoder = self.__typeMap[value.typeId] + + except KeyError: + # use base type for codec lookup to recover untagged types + baseTagSet = tag.TagSet(value.tagSet.baseTag, value.tagSet.baseTag) + try: - concreteEncoder = self.__typeMap[value.typeId] + concreteEncoder = self.__tagMap[baseTagSet] + except KeyError: - # use base type for codec lookup to recover untagged types - baseTagSet = tag.TagSet(value.tagSet.baseTag, value.tagSet.baseTag) - try: - concreteEncoder = self.__tagMap[baseTagSet] - except KeyError: - raise error.PyAsn1Error('No encoder for %s' % (value,)) - - if logger: - logger('using value codec %s chosen by %s' % (concreteEncoder.__class__.__name__, tagSet)) + raise error.PyAsn1Error('No encoder for %s' % (value,)) + + if logger: + logger('using value codec %s chosen by %s' % (concreteEncoder.__class__.__name__, tagSet)) substrate = concreteEncoder.encode(value, self, **options) diff --git a/pyasn1/codec/native/encoder.py b/pyasn1/codec/native/encoder.py index 78fe7c2..3d23d60 100644 --- a/pyasn1/codec/native/encoder.py +++ b/pyasn1/codec/native/encoder.py @@ -10,7 +10,7 @@ try: except ImportError: OrderedDict = dict -from pyasn1.type import base, univ, char, useful +from pyasn1.type import base, univ, tag, char, useful from pyasn1 import debug, error __all__ = ['encode'] @@ -21,19 +21,6 @@ class AbstractItemEncoder(object): raise error.PyAsn1Error('Not implemented') -class ExplicitlyTaggedItemEncoder(AbstractItemEncoder): - def encode(self, value, encodeFun, **options): - if isinstance(value, base.AbstractConstructedAsn1Item): - value = value.clone(tagSet=value.tagSet[:-1], - cloneValueFlag=1) - else: - value = value.clone(tagSet=value.tagSet[:-1]) - - return encodeFun(value, **options) - -explicitlyTaggedItemEncoder = ExplicitlyTaggedItemEncoder() - - class BooleanEncoder(AbstractItemEncoder): def encode(self, value, encodeFun, **options): return bool(value) @@ -158,37 +145,38 @@ class Encoder(object): self.__tagMap = tagMap self.__typeMap = typeMap - def __call__(self, asn1Value, **options): - if not isinstance(asn1Value, base.Asn1Item): + def __call__(self, value, **options): + if not isinstance(value, base.Asn1Item): raise error.PyAsn1Error('value is not valid (should be an instance of an ASN.1 Item)') if debug.logger & debug.flagEncoder: logger = debug.logger else: logger = None + if logger: - debug.scope.push(type(asn1Value).__name__) - logger('encoder called for type %s <%s>' % (type(asn1Value).__name__, asn1Value.prettyPrint())) + debug.scope.push(type(value).__name__) + logger('encoder called for type %s <%s>' % (type(value).__name__, value.prettyPrint())) - tagSet = asn1Value.tagSet - if len(tagSet) > 1: - concreteEncoder = explicitlyTaggedItemEncoder - else: - if asn1Value.typeId is not None and asn1Value.typeId in self.__typeMap: - concreteEncoder = self.__typeMap[asn1Value.typeId] - elif tagSet in self.__tagMap: - concreteEncoder = self.__tagMap[tagSet] - else: - tagSet = asn1Value.baseTagSet - if tagSet in self.__tagMap: - concreteEncoder = self.__tagMap[tagSet] - else: - raise error.PyAsn1Error('No encoder for %s' % (asn1Value,)) + tagSet = value.tagSet + + try: + concreteEncoder = self.__typeMap[value.typeId] + + except KeyError: + # use base type for codec lookup to recover untagged types + baseTagSet = tag.TagSet(value.tagSet.baseTag, value.tagSet.baseTag) + + try: + concreteEncoder = self.__tagMap[baseTagSet] + + except KeyError: + raise error.PyAsn1Error('No encoder for %s' % (value,)) if logger: - logger('using value codec %s chosen by %s' % (type(concreteEncoder).__name__, tagSet)) + logger('using value codec %s chosen by %s' % (concreteEncoder.__class__.__name__, tagSet)) - pyObject = concreteEncoder.encode(asn1Value, self, **options) + pyObject = concreteEncoder.encode(value, self, **options) if logger: logger('encoder %s produced: %s' % (type(concreteEncoder).__name__, repr(pyObject))) -- cgit v1.2.1 From 0864306968a0ac91619189669f3359575d91c9a5 Mon Sep 17 00:00:00 2001 From: Ilya Etingof Date: Sun, 10 Sep 2017 13:45:35 +0200 Subject: end-of-octets marker encoding optimized --- CHANGES.rst | 1 + pyasn1/codec/ber/encoder.py | 11 ++--------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 984f678..b1bfea4 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,6 +4,7 @@ Revision 0.3.5, released XX-09-2017 - Codecs signatures unified and pass **options through the call chain - Explicit tag encoding optimized to avoid unnecessary copying +- End-of-octets sentinel encoding optimized Revision 0.3.4, released 07-09-2017 ----------------------------------- diff --git a/pyasn1/codec/ber/encoder.py b/pyasn1/codec/ber/encoder.py index ef58137..dee13e5 100644 --- a/pyasn1/codec/ber/encoder.py +++ b/pyasn1/codec/ber/encoder.py @@ -50,12 +50,6 @@ class AbstractItemEncoder(object): def encodeValue(self, value, encodeFun, **options): raise error.PyAsn1Error('Not implemented') - def _encodeEndOfOctets(self, encodeFun, defMode): - if defMode or not self.supportIndefLenMode: - return null - else: - return encodeFun(eoo.endOfOctets, defMode=defMode) - def encode(self, value, encodeFun, **options): tagSet = value.tagSet @@ -94,9 +88,8 @@ class AbstractItemEncoder(object): else: substrate = ints2octs(header + substrate) - eoo = self._encodeEndOfOctets(encodeFun, defModeOverride) - if eoo: - substrate += eoo + if not defModeOverride: + substrate += encodeFun(eoo.endOfOctets, defMode=defModeOverride) return substrate -- cgit v1.2.1 From 63f92c7c995752a7418aa6a168c4e48524acc127 Mon Sep 17 00:00:00 2001 From: Ilya Etingof Date: Fri, 21 Apr 2017 01:09:10 +0200 Subject: ANY DEFINED BY decoding implemented --- pyasn1/codec/ber/decoder.py | 12 ++++++++++++ pyasn1/type/namedtype.py | 28 ++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/pyasn1/codec/ber/decoder.py b/pyasn1/codec/ber/decoder.py index 5424195..306f4b4 100644 --- a/pyasn1/codec/ber/decoder.py +++ b/pyasn1/codec/ber/decoder.py @@ -529,6 +529,18 @@ class UniversalConstructedTypeDecoder(AbstractConstructedDecoder): ) idx += 1 + for holeName, governingName, typesMap in namedTypes.holes: + holeComponent = asn1Object[holeName] + if holeComponent.isValue: + governingComponent = asn1Object[governingName] + if governingComponent in typesMap: + component, rest = decodeFun( + holeComponent.asOctets(), + asn1Spec=typesMap[governingComponent] + ) + asn1Object.setComponentByName(holeName, component, matchTags=False, matchConstraints=False) + + if not namedTypes: asn1Object.verifySizeSpec() return asn1Object, tail diff --git a/pyasn1/type/namedtype.py b/pyasn1/type/namedtype.py index 7a51f18..3cdb2a6 100644 --- a/pyasn1/type/namedtype.py +++ b/pyasn1/type/namedtype.py @@ -34,6 +34,8 @@ class NamedType(object): self.__name = name self.__type = asn1Object self.__nameAndType = name, asn1Object + self.__governingName = None + self.__typesMap = None def __repr__(self): return '%s(%r, %r)' % (self.__class__.__name__, self.__name, self.__type) @@ -73,6 +75,19 @@ class NamedType(object): def asn1Object(self): return self.__type + def definedBy(self, governingName, typesMap): + self.__governingName = governingName + self.__typesMap = typesMap + return self + + @property + def governingName(self): + return self.__governingName + + @property + def typesMap(self): + return self.__typesMap + # Backward compatibility def getName(self): @@ -123,6 +138,7 @@ class NamedTypes(object): self.__keys = frozenset([namedType.name for namedType in self.__namedTypes]) self.__values = tuple([namedType.asn1Object for namedType in self.__namedTypes]) self.__items = tuple([(namedType.name, namedType.asn1Object) for namedType in self.__namedTypes]) + self.__holes = None def __repr__(self): return '%s(%s)' % ( @@ -509,3 +525,15 @@ class NamedTypes(object): @property def requiredComponents(self): return self.__requiredComponents + + @property + def holes(self): + if self.__holes is None: + holes = [] + for namedType in self.__namedTypes: + if namedType.governingName: + holes.append((namedType.name, namedType.governingName, namedType.typesMap)) + + self.__holes = holes + + return self.__holes -- cgit v1.2.1 From 7483bbfebf55a8dd3c74e3af93311b759186991c Mon Sep 17 00:00:00 2001 From: Ilya Etingof Date: Fri, 7 Jul 2017 10:03:44 +0200 Subject: run hole type substitution only when components are in place --- pyasn1/codec/ber/decoder.py | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/pyasn1/codec/ber/decoder.py b/pyasn1/codec/ber/decoder.py index 306f4b4..c080b96 100644 --- a/pyasn1/codec/ber/decoder.py +++ b/pyasn1/codec/ber/decoder.py @@ -529,18 +529,19 @@ class UniversalConstructedTypeDecoder(AbstractConstructedDecoder): ) idx += 1 - for holeName, governingName, typesMap in namedTypes.holes: - holeComponent = asn1Object[holeName] - if holeComponent.isValue: - governingComponent = asn1Object[governingName] - if governingComponent in typesMap: - component, rest = decodeFun( - holeComponent.asOctets(), - asn1Spec=typesMap[governingComponent] - ) + if namedTypes: + for holeName, governingName, typesMap in namedTypes.holes: + holeComponent = asn1Object[holeName] + if holeComponent.isValue: + governingComponent = asn1Object[governingName] + if governingComponent in typesMap: + component, rest = decodeFun( + holeComponent.asOctets(), + asn1Spec=typesMap[governingComponent] + ) asn1Object.setComponentByName(holeName, component, matchTags=False, matchConstraints=False) - if not namedTypes: + else: asn1Object.verifySizeSpec() return asn1Object, tail @@ -643,6 +644,20 @@ class UniversalConstructedTypeDecoder(AbstractConstructedDecoder): raise error.SubstrateUnderrunError( 'No EOO seen before substrate ends' ) + + if namedTypes: + for holeName, governingName, typesMap in namedTypes.holes: + holeComponent = asn1Object[holeName] + if holeComponent.isValue: + governingComponent = asn1Object[governingName] + if governingComponent in typesMap: + component, rest = decodeFun( + holeComponent.asOctets(), + asn1Spec=typesMap[governingComponent] + ) + asn1Object.setComponentByName(holeName, component, matchTags=False, matchConstraints=False) + + else: asn1Object.verifySizeSpec() return asn1Object, substrate -- cgit v1.2.1 From 22f9942cddb972c9f00ea8fff998b9ed7537d59f Mon Sep 17 00:00:00 2001 From: Ilya Etingof Date: Fri, 21 Apr 2017 01:09:10 +0200 Subject: ANY DEFINED BY decoding implemented --- CHANGES.rst | 5 +++++ pyasn1/codec/ber/decoder.py | 21 ++++++++++----------- pyasn1/type/namedtype.py | 16 ++++++++-------- 3 files changed, 23 insertions(+), 19 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index b1bfea4..72f7526 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,4 +1,9 @@ +Revision 0.4.1, released XX-09-2017 +----------------------------------- + +- ANY DEFINED BY clause support implemented + Revision 0.3.5, released XX-09-2017 ----------------------------------- diff --git a/pyasn1/codec/ber/decoder.py b/pyasn1/codec/ber/decoder.py index c080b96..fad6eea 100644 --- a/pyasn1/codec/ber/decoder.py +++ b/pyasn1/codec/ber/decoder.py @@ -529,19 +529,18 @@ class UniversalConstructedTypeDecoder(AbstractConstructedDecoder): ) idx += 1 - if namedTypes: - for holeName, governingName, typesMap in namedTypes.holes: - holeComponent = asn1Object[holeName] - if holeComponent.isValue: - governingComponent = asn1Object[governingName] - if governingComponent in typesMap: - component, rest = decodeFun( - holeComponent.asOctets(), - asn1Spec=typesMap[governingComponent] - ) + for holeName, governingName, typesMap in namedTypes.holes: + holeComponent = asn1Object[holeName] + if holeComponent.isValue: + governingComponent = asn1Object[governingName] + if governingComponent in typesMap: + component, rest = decodeFun( + holeComponent.asOctets(), + asn1Spec=typesMap[governingComponent] + ) asn1Object.setComponentByName(holeName, component, matchTags=False, matchConstraints=False) - else: + if not namedTypes: asn1Object.verifySizeSpec() return asn1Object, tail diff --git a/pyasn1/type/namedtype.py b/pyasn1/type/namedtype.py index 3cdb2a6..6bf82f4 100644 --- a/pyasn1/type/namedtype.py +++ b/pyasn1/type/namedtype.py @@ -138,7 +138,7 @@ class NamedTypes(object): self.__keys = frozenset([namedType.name for namedType in self.__namedTypes]) self.__values = tuple([namedType.asn1Object for namedType in self.__namedTypes]) self.__items = tuple([(namedType.name, namedType.asn1Object) for namedType in self.__namedTypes]) - self.__holes = None + self.__holes = self.__computeTypeHoles() def __repr__(self): return '%s(%s)' % ( @@ -528,12 +528,12 @@ class NamedTypes(object): @property def holes(self): - if self.__holes is None: - holes = [] - for namedType in self.__namedTypes: - if namedType.governingName: - holes.append((namedType.name, namedType.governingName, namedType.typesMap)) + return self.__holes - self.__holes = holes + def __computeTypeHoles(self): + holes = [] + for namedType in self.__namedTypes: + if namedType.governingName: + holes.append((namedType.name, namedType.governingName, namedType.typesMap)) - return self.__holes + return holes -- cgit v1.2.1 From c324055b318fa2c01249819c44836214efdfb90e Mon Sep 17 00:00:00 2001 From: Ilya Etingof Date: Fri, 7 Jul 2017 10:03:44 +0200 Subject: run hole type substitution only when components are in place --- pyasn1/codec/ber/decoder.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/pyasn1/codec/ber/decoder.py b/pyasn1/codec/ber/decoder.py index fad6eea..c080b96 100644 --- a/pyasn1/codec/ber/decoder.py +++ b/pyasn1/codec/ber/decoder.py @@ -529,18 +529,19 @@ class UniversalConstructedTypeDecoder(AbstractConstructedDecoder): ) idx += 1 - for holeName, governingName, typesMap in namedTypes.holes: - holeComponent = asn1Object[holeName] - if holeComponent.isValue: - governingComponent = asn1Object[governingName] - if governingComponent in typesMap: - component, rest = decodeFun( - holeComponent.asOctets(), - asn1Spec=typesMap[governingComponent] - ) + if namedTypes: + for holeName, governingName, typesMap in namedTypes.holes: + holeComponent = asn1Object[holeName] + if holeComponent.isValue: + governingComponent = asn1Object[governingName] + if governingComponent in typesMap: + component, rest = decodeFun( + holeComponent.asOctets(), + asn1Spec=typesMap[governingComponent] + ) asn1Object.setComponentByName(holeName, component, matchTags=False, matchConstraints=False) - if not namedTypes: + else: asn1Object.verifySizeSpec() return asn1Object, tail -- cgit v1.2.1 From d35f412398a54a93ac141d88c41dac411bd05453 Mon Sep 17 00:00:00 2001 From: Ilya Etingof Date: Fri, 8 Sep 2017 20:52:36 +0200 Subject: WIP: hole types implementation --- pyasn1/codec/ber/decoder.py | 84 ++++++++++++++++++++++++++--------------- pyasn1/type/definedby.py | 54 ++++++++++++++++++++++++++ pyasn1/type/namedtype.py | 31 ++------------- tests/codec/ber/test_decoder.py | 57 +++++++++++++++++++++++++++- 4 files changed, 167 insertions(+), 59 deletions(-) create mode 100644 pyasn1/type/definedby.py diff --git a/pyasn1/codec/ber/decoder.py b/pyasn1/codec/ber/decoder.py index c080b96..f8f0587 100644 --- a/pyasn1/codec/ber/decoder.py +++ b/pyasn1/codec/ber/decoder.py @@ -514,6 +514,33 @@ class UniversalConstructedTypeDecoder(AbstractConstructedDecoder): if namedTypes: if not namedTypes.requiredComponents.issubset(seenIndices): raise error.PyAsn1Error('ASN.1 object %s has uninitialized components' % asn1Object.__class__.__name__) + + + for idx, namedType in enumerate(namedTypes.namedTypes): + if not namedType.definedBy: + continue + + governingValue = asn1Object.getComponentByName( + namedType.definedBy.name + ) + + try: + asn1Spec = namedType.definedBy[governingValue] + + except KeyError: + continue + + component, rest = decodeFun( + asn1Object.getComponentByPosition(idx).asOctets(), + asn1Spec=asn1Spec + ) + + asn1Object.setComponentByPosition( + idx, component, + matchTags=False, + matchConstraints=False + ) + else: asn1Object.verifySizeSpec() @@ -529,21 +556,6 @@ class UniversalConstructedTypeDecoder(AbstractConstructedDecoder): ) idx += 1 - if namedTypes: - for holeName, governingName, typesMap in namedTypes.holes: - holeComponent = asn1Object[holeName] - if holeComponent.isValue: - governingComponent = asn1Object[governingName] - if governingComponent in typesMap: - component, rest = decodeFun( - holeComponent.asOctets(), - asn1Spec=typesMap[governingComponent] - ) - asn1Object.setComponentByName(holeName, component, matchTags=False, matchConstraints=False) - - else: - asn1Object.verifySizeSpec() - return asn1Object, tail def indefLenValueDecoder(self, substrate, asn1Spec, @@ -624,6 +636,33 @@ class UniversalConstructedTypeDecoder(AbstractConstructedDecoder): if namedTypes: if not namedTypes.requiredComponents.issubset(seenIndices): raise error.PyAsn1Error('ASN.1 object %s has uninitialized components' % asn1Object.__class__.__name__) + + for idx, namedType in enumerate(namedTypes.namedTypes): + if not namedType.definedBy: + continue + + governingValue = asn1Object.getComponentByName( + namedType.definedBy.name + ) + + try: + asn1Spec = namedType.definedBy[governingValue] + + except KeyError: + continue + + component, rest = decodeFun( + asn1Object.getComponentByPosition(idx).asOctets(), + asn1Spec=asn1Spec, allowEoo=True + ) + + if component is not eoo.endOfOctets: + asn1Object.setComponentByPosition( + idx, component, + matchTags=False, + matchConstraints=False + ) + else: asn1Object.verifySizeSpec() @@ -645,21 +684,6 @@ class UniversalConstructedTypeDecoder(AbstractConstructedDecoder): 'No EOO seen before substrate ends' ) - if namedTypes: - for holeName, governingName, typesMap in namedTypes.holes: - holeComponent = asn1Object[holeName] - if holeComponent.isValue: - governingComponent = asn1Object[governingName] - if governingComponent in typesMap: - component, rest = decodeFun( - holeComponent.asOctets(), - asn1Spec=typesMap[governingComponent] - ) - asn1Object.setComponentByName(holeName, component, matchTags=False, matchConstraints=False) - - else: - asn1Object.verifySizeSpec() - return asn1Object, substrate class SequenceOrSequenceOfDecoder(UniversalConstructedTypeDecoder): diff --git a/pyasn1/type/definedby.py b/pyasn1/type/definedby.py new file mode 100644 index 0000000..e22d394 --- /dev/null +++ b/pyasn1/type/definedby.py @@ -0,0 +1,54 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2017, Ilya Etingof +# License: http://pyasn1.sf.net/license.html +# + +__all__ = ['DefinedBy'] + + +class DefinedBy(object): + """Create ASN.1 type map indexed by a value + + The *DefinedBy* object models the ASN.1 *DEFINED BY* clause which maps + values to ASN.1 types in the context of the ASN.1 SEQUENCE/SET type. + + DefinedBy objects are immutable and duck-type Python :class:`dict` objects + + Parameters + ---------- + name: :py:class:`str` + Field name + + *choices: + Sequence of (*value*, *type*) tuples representing the mapping + """ + + def __init__(self, name, args, **kwargs): + self.__name = name + self.__choices = dict(args, **kwargs) + + @property + def name(self): + return self.__name + + # Python dict protocol + + def values(self): + return self.__choices.values() + + def keys(self): + return self.__choices + + def items(self): + return self.__choices.items() + + def __contains__(self, key): + return key in self.__choices + + def __getitem__(self, key): + return self.__choices[key] + + def __iter__(self): + return iter(self.__choices) diff --git a/pyasn1/type/namedtype.py b/pyasn1/type/namedtype.py index 6bf82f4..69b4422 100644 --- a/pyasn1/type/namedtype.py +++ b/pyasn1/type/namedtype.py @@ -30,12 +30,11 @@ class NamedType(object): isOptional = False isDefaulted = False - def __init__(self, name, asn1Object): + def __init__(self, name, asn1Object, definedBy=None): self.__name = name self.__type = asn1Object self.__nameAndType = name, asn1Object - self.__governingName = None - self.__typesMap = None + self.__definedBy = definedBy def __repr__(self): return '%s(%r, %r)' % (self.__class__.__name__, self.__name, self.__type) @@ -75,18 +74,9 @@ class NamedType(object): def asn1Object(self): return self.__type - def definedBy(self, governingName, typesMap): - self.__governingName = governingName - self.__typesMap = typesMap - return self - - @property - def governingName(self): - return self.__governingName - @property - def typesMap(self): - return self.__typesMap + def definedBy(self): + return self.__definedBy # Backward compatibility @@ -138,7 +128,6 @@ class NamedTypes(object): self.__keys = frozenset([namedType.name for namedType in self.__namedTypes]) self.__values = tuple([namedType.asn1Object for namedType in self.__namedTypes]) self.__items = tuple([(namedType.name, namedType.asn1Object) for namedType in self.__namedTypes]) - self.__holes = self.__computeTypeHoles() def __repr__(self): return '%s(%s)' % ( @@ -525,15 +514,3 @@ class NamedTypes(object): @property def requiredComponents(self): return self.__requiredComponents - - @property - def holes(self): - return self.__holes - - def __computeTypeHoles(self): - holes = [] - for namedType in self.__namedTypes: - if namedType.governingName: - holes.append((namedType.name, namedType.governingName, namedType.typesMap)) - - return holes diff --git a/tests/codec/ber/test_decoder.py b/tests/codec/ber/test_decoder.py index d2f02ad..45cd530 100644 --- a/tests/codec/ber/test_decoder.py +++ b/tests/codec/ber/test_decoder.py @@ -10,7 +10,7 @@ try: except ImportError: import unittest -from pyasn1.type import tag, namedtype, univ, char +from pyasn1.type import tag, namedtype, univ, char, definedby from pyasn1.codec.ber import decoder, eoo from pyasn1.compat.octets import ints2octs, str2octs, null from pyasn1.error import PyAsn1Error @@ -720,7 +720,7 @@ class SequenceDecoderWithSchemaTestCase(unittest.TestCase): def testDefMode(self): self.__init() assert decoder.decode( - ints2octs((48, 128, 5, 0, 0, 0)), asn1Spec=self.s + ints2octs((48, 2, 5, 0)), asn1Spec=self.s ) == (self.s, null) def testIndefMode(self): @@ -823,6 +823,59 @@ class SequenceDecoderWithSchemaTestCase(unittest.TestCase): ) == (self.s, null) +class SequenceDecoderWithIntegerHoleTypesTestCase(unittest.TestCase): + def setUp(self): + definedBy = definedby.DefinedBy( + 'id', + [(1, univ.Integer()), + (2, univ.OctetString())] + ) + self.s = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.NamedType('id', univ.Integer()), + namedtype.NamedType('blob', univ.Any(), definedBy=definedBy) + ) + ) + + # def testChoiceOne(self): + # s, r = decoder.decode( + # ints2octs((48, 6, 2, 1, 1, 2, 1, 12)), + # asn1Spec=self.s + # ) + # assert not r + # assert s[0] == 1 + # assert s[1] == ints2octs((2, 1, 12)) + # + # def testChoiceTwo(self): + # s, r = decoder.decode( + # ints2octs((48, 16, 2, 1, 2, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)), + # asn1Spec=self.s + # ) + # assert not r + # assert s[0] == 1 + # assert s[1] == ints2octs((4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)) + + def testChoiceOneResolveHoles(self): + s, r = decoder.decode( + ints2octs((48, 6, 2, 1, 1, 2, 1, 12)), asn1Spec=self.s +# TODO +# resolveHoleTypes=True + ) + assert not r + assert s[0] == 1 + assert s[1] == 12 + + def testChoiceTwoResolveHoles(self): + s, r = decoder.decode( + ints2octs((48, 16, 2, 1, 2, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)), asn1Spec=self.s +# TODO +# resolveHoleTypes = True + ) + assert not r + assert s[0] == 2 + assert s[1] == univ.OctetString('quick brown') + + class SetDecoderTestCase(unittest.TestCase): def setUp(self): self.s = univ.Set( -- cgit v1.2.1 From c550820832cc8593eed2398e87d27d323dfc39a3 Mon Sep 17 00:00:00 2001 From: Ilya Etingof Date: Sun, 10 Sep 2017 14:35:31 +0200 Subject: fixes following bad merge --- pyasn1/type/namedtype.py | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/pyasn1/type/namedtype.py b/pyasn1/type/namedtype.py index f25af99..69b4422 100644 --- a/pyasn1/type/namedtype.py +++ b/pyasn1/type/namedtype.py @@ -128,7 +128,6 @@ class NamedTypes(object): self.__keys = frozenset([namedType.name for namedType in self.__namedTypes]) self.__values = tuple([namedType.asn1Object for namedType in self.__namedTypes]) self.__items = tuple([(namedType.name, namedType.asn1Object) for namedType in self.__namedTypes]) - self.__holes = self.__computeTypeHoles() def __repr__(self): return '%s(%s)' % ( @@ -515,15 +514,3 @@ class NamedTypes(object): @property def requiredComponents(self): return self.__requiredComponents - - @property - def holes(self): - return self.__holes - - def __computeTypeHoles(self): - holes = [] - for namedType in self.__namedTypes: - if namedType.governingName: - holes.append((namedType.name, namedType.governingName, namedType.typesMap)) - - return holes -- cgit v1.2.1 From 9ca6884c92d68e15942539c6126c0e5b00643c41 Mon Sep 17 00:00:00 2001 From: Ilya Etingof Date: Sun, 10 Sep 2017 17:57:08 +0200 Subject: refer to open types by open types, not hole types --- pyasn1/codec/ber/decoder.py | 14 +++++------ pyasn1/type/definedby.py | 54 ----------------------------------------- pyasn1/type/namedtype.py | 8 +++--- pyasn1/type/opentype.py | 54 +++++++++++++++++++++++++++++++++++++++++ tests/codec/ber/test_decoder.py | 54 +++++++++++++++++++---------------------- 5 files changed, 90 insertions(+), 94 deletions(-) delete mode 100644 pyasn1/type/definedby.py create mode 100644 pyasn1/type/opentype.py diff --git a/pyasn1/codec/ber/decoder.py b/pyasn1/codec/ber/decoder.py index f8f0587..73167a2 100644 --- a/pyasn1/codec/ber/decoder.py +++ b/pyasn1/codec/ber/decoder.py @@ -511,21 +511,21 @@ class UniversalConstructedTypeDecoder(AbstractConstructedDecoder): seenIndices.add(idx) idx += 1 - if namedTypes: + if namedTypes and options.get('decodeOpenTypes', False): if not namedTypes.requiredComponents.issubset(seenIndices): raise error.PyAsn1Error('ASN.1 object %s has uninitialized components' % asn1Object.__class__.__name__) for idx, namedType in enumerate(namedTypes.namedTypes): - if not namedType.definedBy: + if not namedType.openType: continue governingValue = asn1Object.getComponentByName( - namedType.definedBy.name + namedType.openType.name ) try: - asn1Spec = namedType.definedBy[governingValue] + asn1Spec = namedType.openType[governingValue] except KeyError: continue @@ -638,15 +638,15 @@ class UniversalConstructedTypeDecoder(AbstractConstructedDecoder): raise error.PyAsn1Error('ASN.1 object %s has uninitialized components' % asn1Object.__class__.__name__) for idx, namedType in enumerate(namedTypes.namedTypes): - if not namedType.definedBy: + if not namedType.openType: continue governingValue = asn1Object.getComponentByName( - namedType.definedBy.name + namedType.openType.name ) try: - asn1Spec = namedType.definedBy[governingValue] + asn1Spec = namedType.openType[governingValue] except KeyError: continue diff --git a/pyasn1/type/definedby.py b/pyasn1/type/definedby.py deleted file mode 100644 index e22d394..0000000 --- a/pyasn1/type/definedby.py +++ /dev/null @@ -1,54 +0,0 @@ -# -# This file is part of pyasn1 software. -# -# Copyright (c) 2005-2017, Ilya Etingof -# License: http://pyasn1.sf.net/license.html -# - -__all__ = ['DefinedBy'] - - -class DefinedBy(object): - """Create ASN.1 type map indexed by a value - - The *DefinedBy* object models the ASN.1 *DEFINED BY* clause which maps - values to ASN.1 types in the context of the ASN.1 SEQUENCE/SET type. - - DefinedBy objects are immutable and duck-type Python :class:`dict` objects - - Parameters - ---------- - name: :py:class:`str` - Field name - - *choices: - Sequence of (*value*, *type*) tuples representing the mapping - """ - - def __init__(self, name, args, **kwargs): - self.__name = name - self.__choices = dict(args, **kwargs) - - @property - def name(self): - return self.__name - - # Python dict protocol - - def values(self): - return self.__choices.values() - - def keys(self): - return self.__choices - - def items(self): - return self.__choices.items() - - def __contains__(self, key): - return key in self.__choices - - def __getitem__(self, key): - return self.__choices[key] - - def __iter__(self): - return iter(self.__choices) diff --git a/pyasn1/type/namedtype.py b/pyasn1/type/namedtype.py index 69b4422..cba9524 100644 --- a/pyasn1/type/namedtype.py +++ b/pyasn1/type/namedtype.py @@ -30,11 +30,11 @@ class NamedType(object): isOptional = False isDefaulted = False - def __init__(self, name, asn1Object, definedBy=None): + def __init__(self, name, asn1Object, openType=None): self.__name = name self.__type = asn1Object self.__nameAndType = name, asn1Object - self.__definedBy = definedBy + self.__openType = openType def __repr__(self): return '%s(%r, %r)' % (self.__class__.__name__, self.__name, self.__type) @@ -75,8 +75,8 @@ class NamedType(object): return self.__type @property - def definedBy(self): - return self.__definedBy + def openType(self): + return self.__openType # Backward compatibility diff --git a/pyasn1/type/opentype.py b/pyasn1/type/opentype.py new file mode 100644 index 0000000..9788a56 --- /dev/null +++ b/pyasn1/type/opentype.py @@ -0,0 +1,54 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2017, Ilya Etingof +# License: http://pyasn1.sf.net/license.html +# + +__all__ = ['OpenType'] + + +class OpenType(object): + """Create ASN.1 type map indexed by a value + + The *DefinedBy* object models the ASN.1 *DEFINED BY* clause which maps + values to ASN.1 types in the context of the ASN.1 SEQUENCE/SET type. + + DefinedBy objects are immutable and duck-type Python :class:`dict` objects + + Parameters + ---------- + name: :py:class:`str` + Field name + + *choices: + Sequence of (*value*, *type*) tuples representing the mapping + """ + + def __init__(self, name, args, **kwargs): + self.__name = name + self.__choices = dict(args, **kwargs) + + @property + def name(self): + return self.__name + + # Python dict protocol + + def values(self): + return self.__choices.values() + + def keys(self): + return self.__choices + + def items(self): + return self.__choices.items() + + def __contains__(self, key): + return key in self.__choices + + def __getitem__(self, key): + return self.__choices[key] + + def __iter__(self): + return iter(self.__choices) diff --git a/tests/codec/ber/test_decoder.py b/tests/codec/ber/test_decoder.py index 45cd530..85c71fb 100644 --- a/tests/codec/ber/test_decoder.py +++ b/tests/codec/ber/test_decoder.py @@ -10,7 +10,7 @@ try: except ImportError: import unittest -from pyasn1.type import tag, namedtype, univ, char, definedby +from pyasn1.type import tag, namedtype, opentype, univ, char from pyasn1.codec.ber import decoder, eoo from pyasn1.compat.octets import ints2octs, str2octs, null from pyasn1.error import PyAsn1Error @@ -825,7 +825,7 @@ class SequenceDecoderWithSchemaTestCase(unittest.TestCase): class SequenceDecoderWithIntegerHoleTypesTestCase(unittest.TestCase): def setUp(self): - definedBy = definedby.DefinedBy( + openType = opentype.OpenType( 'id', [(1, univ.Integer()), (2, univ.OctetString())] @@ -833,48 +833,44 @@ class SequenceDecoderWithIntegerHoleTypesTestCase(unittest.TestCase): self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('id', univ.Integer()), - namedtype.NamedType('blob', univ.Any(), definedBy=definedBy) + namedtype.NamedType('blob', univ.Any(), openType=openType) ) ) - # def testChoiceOne(self): - # s, r = decoder.decode( - # ints2octs((48, 6, 2, 1, 1, 2, 1, 12)), - # asn1Spec=self.s - # ) - # assert not r - # assert s[0] == 1 - # assert s[1] == ints2octs((2, 1, 12)) - # - # def testChoiceTwo(self): - # s, r = decoder.decode( - # ints2octs((48, 16, 2, 1, 2, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)), - # asn1Spec=self.s - # ) - # assert not r - # assert s[0] == 1 - # assert s[1] == ints2octs((4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)) - - def testChoiceOneResolveHoles(self): + def testChoiceOneDecodeHoles(self): s, r = decoder.decode( - ints2octs((48, 6, 2, 1, 1, 2, 1, 12)), asn1Spec=self.s -# TODO -# resolveHoleTypes=True + ints2octs((48, 6, 2, 1, 1, 2, 1, 12)), asn1Spec=self.s, + decodeOpenTypes=True ) assert not r assert s[0] == 1 assert s[1] == 12 - def testChoiceTwoResolveHoles(self): + def testChoiceTwoDecodeHoles(self): s, r = decoder.decode( - ints2octs((48, 16, 2, 1, 2, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)), asn1Spec=self.s -# TODO -# resolveHoleTypes = True + ints2octs((48, 16, 2, 1, 2, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)), asn1Spec=self.s, + decodeOpenTypes = True ) assert not r assert s[0] == 2 assert s[1] == univ.OctetString('quick brown') + def testChoiceOneDontDecodeHoles(self): + s, r = decoder.decode( + ints2octs((48, 6, 2, 1, 1, 2, 1, 12)), asn1Spec=self.s + ) + assert not r + assert s[0] == 1 + assert s[1] == ints2octs((2, 1, 12)) + + def testChoiceTwoDontDecodeHoles(self): + s, r = decoder.decode( + ints2octs((48, 16, 2, 1, 2, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)), asn1Spec=self.s + ) + assert not r + assert s[0] == 2 + assert s[1] == ints2octs((4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)) + class SetDecoderTestCase(unittest.TestCase): def setUp(self): -- cgit v1.2.1 From 3db65dde5e9dc7e0f2c594bcfb779d61efc6c952 Mon Sep 17 00:00:00 2001 From: Ilya Etingof Date: Sun, 10 Sep 2017 20:58:35 +0200 Subject: fixes to debug message interpolation --- pyasn1/codec/ber/decoder.py | 4 +++- pyasn1/codec/ber/encoder.py | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/pyasn1/codec/ber/decoder.py b/pyasn1/codec/ber/decoder.py index 73167a2..8aac8c9 100644 --- a/pyasn1/codec/ber/decoder.py +++ b/pyasn1/codec/ber/decoder.py @@ -1209,8 +1209,10 @@ class Decoder(object): self, substrateFun, **options ) + if logger: - logger('codec %s yields type %s, value:\n%s\n...remaining substrate is: %s' % (concreteDecoder.__class__.__name__, value.__class__.__name__, value.prettyPrint(), substrate and debug.hexdump(substrate) or '')) + logger('codec %s yields type %s, value:\n%s\n...remaining substrate is: %s' % (concreteDecoder.__class__.__name__, value.__class__.__name__, isinstance(value, base.Asn1Item) and value.prettyPrint() or repr(value), substrate and debug.hexdump(substrate) or '')) + state = stStop break if state is stTryAsExplicitTag: diff --git a/pyasn1/codec/ber/encoder.py b/pyasn1/codec/ber/encoder.py index dee13e5..c97efd2 100644 --- a/pyasn1/codec/ber/encoder.py +++ b/pyasn1/codec/ber/encoder.py @@ -477,7 +477,7 @@ class Encoder(object): logger = None if logger: - logger('encoder called in %sdef mode, chunk size %s for type %s, value:\n%s' % (not defMode and 'in' or '', maxChunkSize, value.prettyPrintType(), value.prettyPrint())) + logger('encoder called in %sdef mode, chunk size %s for type %s, value:\n%s' % (not options.get('defMode', True) and 'in' or '', options.get('maxChunkSize', 0), value.prettyPrintType(), value.prettyPrint())) tagSet = value.tagSet -- cgit v1.2.1 From 68e26963ae5da07d6f8eceabf5df168b92851d0c Mon Sep 17 00:00:00 2001 From: Ilya Etingof Date: Sun, 10 Sep 2017 20:58:50 +0200 Subject: debug flag 'none' added --- pyasn1/debug.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pyasn1/debug.py b/pyasn1/debug.py index 04a9da5..b5d17e4 100644 --- a/pyasn1/debug.py +++ b/pyasn1/debug.py @@ -17,6 +17,7 @@ flagDecoder = 0x0002 flagAll = 0xffff flagMap = { + 'none': flagNone, 'encoder': flagEncoder, 'decoder': flagDecoder, 'all': flagAll -- cgit v1.2.1 From 789a4e2f4f921fdac37f28df557319b89df3050c Mon Sep 17 00:00:00 2001 From: Ilya Etingof Date: Sun, 10 Sep 2017 21:37:33 +0200 Subject: wrap open type blob on encoding if needed --- pyasn1/codec/ber/encoder.py | 16 +++++++++++++--- pyasn1/codec/cer/encoder.py | 17 +++++++++++++---- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/pyasn1/codec/ber/encoder.py b/pyasn1/codec/ber/encoder.py index c97efd2..0d48a90 100644 --- a/pyasn1/codec/ber/encoder.py +++ b/pyasn1/codec/ber/encoder.py @@ -361,11 +361,21 @@ class SequenceEncoder(AbstractItemEncoder): while idx > 0: idx -= 1 if namedTypes: - if namedTypes[idx].isOptional and not value[idx].isValue: + namedType = namedTypes[idx] + if namedType.isOptional and not value[idx].isValue: continue - if namedTypes[idx].isDefaulted and value[idx] == namedTypes[idx].asn1Object: + if namedType.isDefaulted and value[idx] == namedType.asn1Object: continue - substrate = encodeFun(value[idx], **options) + substrate + + chunk = encodeFun(value[idx], **options) + + # wrap open type blob if needed + if namedTypes and namedType.openType: + asn1Spec = namedType.asn1Object + if asn1Spec.tagSet and not asn1Spec.isSameTypeWith(value[idx]): + chunk = encodeFun(asn1Spec.clone(chunk), **options) + + substrate = chunk + substrate return substrate, True, True diff --git a/pyasn1/codec/cer/encoder.py b/pyasn1/codec/cer/encoder.py index 50cb346..e305a6d 100644 --- a/pyasn1/codec/cer/encoder.py +++ b/pyasn1/codec/cer/encoder.py @@ -151,14 +151,23 @@ class SequenceEncoder(encoder.SequenceEncoder): while idx > 0: idx -= 1 if namedTypes: - if namedTypes[idx].isOptional and not value[idx].isValue: + namedType = namedTypes[idx] + if namedType.isOptional and not value[idx].isValue: continue - if namedTypes[idx].isDefaulted and value[idx] == namedTypes[idx].asn1Object: + if namedType.isDefaulted and value[idx] == namedType.asn1Object: continue - options.update(ifNotEmpty=namedTypes and namedTypes[idx].isOptional) + options.update(ifNotEmpty=namedTypes and namedType.isOptional) - substrate = encodeFun(value[idx], **options) + substrate + chunk = encodeFun(value[idx], **options) + + # wrap open type blob if needed + if namedTypes and namedType.openType: + asn1Spec = namedType.asn1Object + if asn1Spec.tagSet and not asn1Spec.isSameTypeWith(value[idx]): + chunk = encodeFun(asn1Spec.clone(chunk), **options) + + substrate = chunk + substrate return substrate, True, True -- cgit v1.2.1 From c40b8c22c9679e017871617d7cf558b1b7f0ff84 Mon Sep 17 00:00:00 2001 From: Ilya Etingof Date: Wed, 13 Sep 2017 01:10:42 +0200 Subject: refactored OpenType() into a mutable object --- pyasn1/codec/ber/decoder.py | 101 ++++++++++++++++++++++++---------------- pyasn1/type/namedtype.py | 19 ++++++-- pyasn1/type/opentype.py | 24 ++++++---- tests/codec/ber/test_decoder.py | 14 +++--- 4 files changed, 98 insertions(+), 60 deletions(-) diff --git a/pyasn1/codec/ber/decoder.py b/pyasn1/codec/ber/decoder.py index 8aac8c9..4a1ef01 100644 --- a/pyasn1/codec/ber/decoder.py +++ b/pyasn1/codec/ber/decoder.py @@ -511,35 +511,45 @@ class UniversalConstructedTypeDecoder(AbstractConstructedDecoder): seenIndices.add(idx) idx += 1 - if namedTypes and options.get('decodeOpenTypes', False): + if namedTypes: if not namedTypes.requiredComponents.issubset(seenIndices): raise error.PyAsn1Error('ASN.1 object %s has uninitialized components' % asn1Object.__class__.__name__) + if namedTypes.hasOpenTypes: - for idx, namedType in enumerate(namedTypes.namedTypes): - if not namedType.openType: - continue + openTypes = options.get('openTypes', {}) - governingValue = asn1Object.getComponentByName( - namedType.openType.name - ) + if openTypes or options.get('decodeOpenTypes', False): - try: - asn1Spec = namedType.openType[governingValue] + for idx, namedType in enumerate(namedTypes.namedTypes): + if not namedType.openType: + continue - except KeyError: - continue + governingValue = asn1Object.getComponentByName( + namedType.openType.name + ) - component, rest = decodeFun( - asn1Object.getComponentByPosition(idx).asOctets(), - asn1Spec=asn1Spec - ) + try: + asn1Spec = openTypes[governingValue] - asn1Object.setComponentByPosition( - idx, component, - matchTags=False, - matchConstraints=False - ) + except KeyError: + + try: + asn1Spec = namedType.openType[governingValue] + + except KeyError: + continue + + component, rest = decodeFun( + asn1Object.getComponentByPosition(idx).asOctets(), + asn1Spec=asn1Spec + ) + + asn1Object.setComponentByPosition( + idx, component, + matchTags=False, + matchConstraints=False + ) else: asn1Object.verifySizeSpec() @@ -637,31 +647,42 @@ class UniversalConstructedTypeDecoder(AbstractConstructedDecoder): if not namedTypes.requiredComponents.issubset(seenIndices): raise error.PyAsn1Error('ASN.1 object %s has uninitialized components' % asn1Object.__class__.__name__) - for idx, namedType in enumerate(namedTypes.namedTypes): - if not namedType.openType: - continue + if namedTypes.hasOpenTypes: - governingValue = asn1Object.getComponentByName( - namedType.openType.name - ) + openTypes = options.get('openTypes', None) - try: - asn1Spec = namedType.openType[governingValue] + if openTypes or options.get('decodeOpenTypes', False): - except KeyError: - continue + for idx, namedType in enumerate(namedTypes.namedTypes): + if not namedType.openType: + continue - component, rest = decodeFun( - asn1Object.getComponentByPosition(idx).asOctets(), - asn1Spec=asn1Spec, allowEoo=True - ) + governingValue = asn1Object.getComponentByName( + namedType.openType.name + ) - if component is not eoo.endOfOctets: - asn1Object.setComponentByPosition( - idx, component, - matchTags=False, - matchConstraints=False - ) + try: + asn1Spec = openTypes[governingValue] + + except KeyError: + + try: + asn1Spec = namedType.openType[governingValue] + + except KeyError: + continue + + component, rest = decodeFun( + asn1Object.getComponentByPosition(idx).asOctets(), + asn1Spec=asn1Spec, allowEoo=True + ) + + if component is not eoo.endOfOctets: + asn1Object.setComponentByPosition( + idx, component, + matchTags=False, + matchConstraints=False + ) else: asn1Object.verifySizeSpec() diff --git a/pyasn1/type/namedtype.py b/pyasn1/type/namedtype.py index cba9524..edcf3ce 100644 --- a/pyasn1/type/namedtype.py +++ b/pyasn1/type/namedtype.py @@ -10,6 +10,12 @@ from pyasn1 import error __all__ = ['NamedType', 'OptionalNamedType', 'DefaultedNamedType', 'NamedTypes'] +try: + any + +except AttributeError: + any = lambda x: bool(filter(bool, x)) + class NamedType(object): """Create named field object for a constructed ASN.1 type. @@ -120,8 +126,11 @@ class NamedTypes(object): self.__ambiguousTypes = 'terminal' not in kwargs and self.__computeAmbiguousTypes() or {} self.__uniqueTagMap = self.__computeTagMaps(unique=True) self.__nonUniqueTagMap = self.__computeTagMaps(unique=False) - self.__hasOptionalOrDefault = bool([True for namedType in self.__namedTypes - if namedType.isDefaulted or namedType.isOptional]) + self.__hasOptionalOrDefault = any([True for namedType in self.__namedTypes + if namedType.isDefaulted or namedType.isOptional]) + self.__hasOpenTypes = any([True for namedType in self.__namedTypes + if namedType.openType]) + self.__requiredComponents = frozenset( [idx for idx, nt in enumerate(self.__namedTypes) if not nt.isOptional and not nt.isDefaulted] ) @@ -507,9 +516,13 @@ class NamedTypes(object): def hasOptionalOrDefault(self): return self.__hasOptionalOrDefault + @property + def hasOpenTypes(self): + return self.__hasOpenTypes + @property def namedTypes(self): - return iter(self.__namedTypes) + return tuple(self.__namedTypes) @property def requiredComponents(self): diff --git a/pyasn1/type/opentype.py b/pyasn1/type/opentype.py index 9788a56..c8f0e64 100644 --- a/pyasn1/type/opentype.py +++ b/pyasn1/type/opentype.py @@ -21,13 +21,17 @@ class OpenType(object): name: :py:class:`str` Field name - *choices: - Sequence of (*value*, *type*) tuples representing the mapping + typeMap: :py:class:`dict`: + A map of value->ASN.1 type. It's stored by reference and can be + mutated later to register new mappings. """ - def __init__(self, name, args, **kwargs): + def __init__(self, name, typeMap=None): self.__name = name - self.__choices = dict(args, **kwargs) + if typeMap is None: + self.__typeMap = {} + else: + self.__typeMap = typeMap @property def name(self): @@ -36,19 +40,19 @@ class OpenType(object): # Python dict protocol def values(self): - return self.__choices.values() + return self.__typeMap.values() def keys(self): - return self.__choices + return self.__typeMap.keys() def items(self): - return self.__choices.items() + return self.__typeMap.items() def __contains__(self, key): - return key in self.__choices + return key in self.__typeMap def __getitem__(self, key): - return self.__choices[key] + return self.__typeMap[key] def __iter__(self): - return iter(self.__choices) + return iter(self.__typeMap) diff --git a/tests/codec/ber/test_decoder.py b/tests/codec/ber/test_decoder.py index 85c71fb..c1ced34 100644 --- a/tests/codec/ber/test_decoder.py +++ b/tests/codec/ber/test_decoder.py @@ -823,12 +823,12 @@ class SequenceDecoderWithSchemaTestCase(unittest.TestCase): ) == (self.s, null) -class SequenceDecoderWithIntegerHoleTypesTestCase(unittest.TestCase): +class SequenceDecoderWithIntegerOpenTypesTestCase(unittest.TestCase): def setUp(self): openType = opentype.OpenType( 'id', - [(1, univ.Integer()), - (2, univ.OctetString())] + {1: univ.Integer(), + 2: univ.OctetString()} ) self.s = univ.Sequence( componentType=namedtype.NamedTypes( @@ -837,7 +837,7 @@ class SequenceDecoderWithIntegerHoleTypesTestCase(unittest.TestCase): ) ) - def testChoiceOneDecodeHoles(self): + def testDecodeOpenTypesChoiceOne(self): s, r = decoder.decode( ints2octs((48, 6, 2, 1, 1, 2, 1, 12)), asn1Spec=self.s, decodeOpenTypes=True @@ -846,7 +846,7 @@ class SequenceDecoderWithIntegerHoleTypesTestCase(unittest.TestCase): assert s[0] == 1 assert s[1] == 12 - def testChoiceTwoDecodeHoles(self): + def testDecodeOpenTypesChoiceTwo(self): s, r = decoder.decode( ints2octs((48, 16, 2, 1, 2, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)), asn1Spec=self.s, decodeOpenTypes = True @@ -855,7 +855,7 @@ class SequenceDecoderWithIntegerHoleTypesTestCase(unittest.TestCase): assert s[0] == 2 assert s[1] == univ.OctetString('quick brown') - def testChoiceOneDontDecodeHoles(self): + def testDontDecodeOpenTypesChoiceOne(self): s, r = decoder.decode( ints2octs((48, 6, 2, 1, 1, 2, 1, 12)), asn1Spec=self.s ) @@ -863,7 +863,7 @@ class SequenceDecoderWithIntegerHoleTypesTestCase(unittest.TestCase): assert s[0] == 1 assert s[1] == ints2octs((2, 1, 12)) - def testChoiceTwoDontDecodeHoles(self): + def testDontDecodeOpenTypesChoiceTwo(self): s, r = decoder.decode( ints2octs((48, 16, 2, 1, 2, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)), asn1Spec=self.s ) -- cgit v1.2.1 From 1183c6c9724de537971903a66b537144fe39111f Mon Sep 17 00:00:00 2001 From: Ilya Etingof Date: Wed, 13 Sep 2017 15:55:06 +0200 Subject: ASN.1 codecs to silently enforce proper length/chunk modes --- CHANGES.rst | 3 +++ pyasn1/codec/ber/encoder.py | 11 ++++++++--- pyasn1/codec/cer/encoder.py | 25 +++---------------------- pyasn1/codec/der/encoder.py | 24 ++---------------------- tests/codec/der/test_encoder.py | 23 ++++++++++------------- 5 files changed, 26 insertions(+), 60 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index b1bfea4..7d7ff33 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -5,6 +5,9 @@ Revision 0.3.5, released XX-09-2017 - Codecs signatures unified and pass **options through the call chain - Explicit tag encoding optimized to avoid unnecessary copying - End-of-octets sentinel encoding optimized +- Refactored ASN.1 codecs properties to silently enforce proper length and + chunk size encoding modes +- Fixed DER encoder to always produce primitive encoding Revision 0.3.4, released 07-09-2017 ----------------------------------- diff --git a/pyasn1/codec/ber/encoder.py b/pyasn1/codec/ber/encoder.py index dee13e5..b43e209 100644 --- a/pyasn1/codec/ber/encoder.py +++ b/pyasn1/codec/ber/encoder.py @@ -460,7 +460,8 @@ typeMap = { class Encoder(object): - supportIndefLength = True + fixedDefLengthMode = None + fixedChunkSize = None # noinspection PyDefaultArgument def __init__(self, tagMap, typeMap={}): @@ -468,8 +469,6 @@ class Encoder(object): self.__typeMap = typeMap def __call__(self, value, **options): - if not options.get('defMode', True) and not self.supportIndefLength: - raise error.PyAsn1Error('Indefinite length encoding not supported by this codec') if debug.logger & debug.flagEncoder: logger = debug.logger @@ -479,6 +478,12 @@ class Encoder(object): if logger: logger('encoder called in %sdef mode, chunk size %s for type %s, value:\n%s' % (not defMode and 'in' or '', maxChunkSize, value.prettyPrintType(), value.prettyPrint())) + if self.fixedDefLengthMode is not None: + options.update(defMode=self.fixedDefLengthMode) + + if self.fixedChunkSize is not None: + options.update(maxChunkSize=self.fixedChunkSize) + tagSet = value.tagSet try: diff --git a/pyasn1/codec/cer/encoder.py b/pyasn1/codec/cer/encoder.py index 50cb346..dd3e2b4 100644 --- a/pyasn1/codec/cer/encoder.py +++ b/pyasn1/codec/cer/encoder.py @@ -22,22 +22,6 @@ class BooleanEncoder(encoder.IntegerEncoder): return substrate, False, False -class BitStringEncoder(encoder.BitStringEncoder): - def encodeValue(self, value, encodeFun, **options): - options.update(maxChunkSize=1000) - return encoder.BitStringEncoder.encodeValue( - self, value, encodeFun, **options - ) - - -class OctetStringEncoder(encoder.OctetStringEncoder): - def encodeValue(self, value, encodeFun, **options): - options.update(maxChunkSize=1000) - return encoder.OctetStringEncoder.encodeValue( - self, value, encodeFun, **options - ) - - class RealEncoder(encoder.RealEncoder): def _chooseEncBase(self, value): m, b, e = value @@ -83,7 +67,7 @@ class TimeEncoderMixIn(object): ) -class GeneralizedTimeEncoder(TimeEncoderMixIn, OctetStringEncoder): +class GeneralizedTimeEncoder(TimeEncoderMixIn, encoder.OctetStringEncoder): minLength = 12 maxLength = 19 @@ -181,8 +165,6 @@ class SequenceOfEncoder(encoder.SequenceOfEncoder): tagMap = encoder.tagMap.copy() tagMap.update({ univ.Boolean.tagSet: BooleanEncoder(), - univ.BitString.tagSet: BitStringEncoder(), - univ.OctetString.tagSet: OctetStringEncoder(), univ.Real.tagSet: RealEncoder(), useful.GeneralizedTime.tagSet: GeneralizedTimeEncoder(), useful.UTCTime.tagSet: UTCTimeEncoder(), @@ -194,8 +176,6 @@ tagMap.update({ typeMap = encoder.typeMap.copy() typeMap.update({ univ.Boolean.typeId: BooleanEncoder(), - univ.BitString.typeId: BitStringEncoder(), - univ.OctetString.typeId: OctetStringEncoder(), univ.Real.typeId: RealEncoder(), useful.GeneralizedTime.typeId: GeneralizedTimeEncoder(), useful.UTCTime.typeId: UTCTimeEncoder(), @@ -208,7 +188,8 @@ typeMap.update({ class Encoder(encoder.Encoder): - supportIndefLength = True + fixedDefLengthMode = False + fixedChunkSize = 1000 def __call__(self, value, **options): if 'defMode' not in options: diff --git a/pyasn1/codec/der/encoder.py b/pyasn1/codec/der/encoder.py index 59dd512..d2992a9 100644 --- a/pyasn1/codec/der/encoder.py +++ b/pyasn1/codec/der/encoder.py @@ -10,18 +10,6 @@ from pyasn1.codec.cer import encoder __all__ = ['encode'] -class BitStringEncoder(encoder.BitStringEncoder): - def encodeValue(self, value, encodeFun, **options): - return encoder.BitStringEncoder.encodeValue( - self, value, encodeFun, **options - ) - -class OctetStringEncoder(encoder.OctetStringEncoder): - def encodeValue(self, value, encodeFun, **options): - return encoder.OctetStringEncoder.encodeValue( - self, value, encodeFun, **options - ) - class SetOfEncoder(encoder.SetOfEncoder): @staticmethod def _sortComponents(components): @@ -30,16 +18,12 @@ class SetOfEncoder(encoder.SetOfEncoder): tagMap = encoder.tagMap.copy() tagMap.update({ - univ.BitString.tagSet: BitStringEncoder(), - univ.OctetString.tagSet: OctetStringEncoder(), # Set & SetOf have same tags univ.SetOf.tagSet: SetOfEncoder() }) typeMap = encoder.typeMap.copy() typeMap.update({ - univ.BitString.typeId: BitStringEncoder(), - univ.OctetString.typeId: OctetStringEncoder(), # Set & SetOf have same tags univ.Set.typeId: SetOfEncoder(), univ.SetOf.typeId: SetOfEncoder() @@ -47,12 +31,8 @@ typeMap.update({ class Encoder(encoder.Encoder): - supportIndefLength = False - - def __call__(self, value, **options): - if 'defMode' not in options: - options.update(defMode=True) - return encoder.Encoder.__call__(self, value, **options) + fixedDefLengthMode = True + fixedChunkSize = 0 #: Turns ASN.1 object into DER octet stream. #: diff --git a/tests/codec/der/test_encoder.py b/tests/codec/der/test_encoder.py index d30dfc1..354781a 100644 --- a/tests/codec/der/test_encoder.py +++ b/tests/codec/der/test_encoder.py @@ -17,31 +17,28 @@ from pyasn1.error import PyAsn1Error class OctetStringEncoderTestCase(unittest.TestCase): - def testShortMode(self): + def testDefModeShort(self): assert encoder.encode( univ.OctetString('Quick brown fox') ) == ints2octs((4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120)) - def testIndefMode(self): - try: - encoder.encode(univ.OctetString('Quick brown'), defMode=False) - except PyAsn1Error: - pass - else: - assert 0, 'Indefinite length encoding tolerated' - - def testChunkedMode(self): + def testDefModeLong(self): assert encoder.encode( - univ.OctetString('Quick brown'), maxChunkSize=2 - ) == ints2octs((4, 11, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110)) + univ.OctetString('Q' * 10000) + ) == ints2octs((4, 130, 39, 16) + (81,) * 10000) class BitStringEncoderTestCase(unittest.TestCase): - def testShortMode(self): + def testDefModeShort(self): assert encoder.encode( univ.BitString((1,)) ) == ints2octs((3, 2, 7, 128)) + def testDefModeLong(self): + assert encoder.encode( + univ.BitString((1,) * 80000) + ) == ints2octs((3, 130, 39, 17, 0) + (255,) * 10000) + class SetOfEncoderTestCase(unittest.TestCase): def setUp(self): -- cgit v1.2.1 From 154c55b30e335482a074ac76ad4e5abdc41ccc8b Mon Sep 17 00:00:00 2001 From: Ilya Etingof Date: Thu, 14 Sep 2017 10:02:29 +0200 Subject: removed stray __call__ method from CER encoder --- pyasn1/codec/cer/encoder.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/pyasn1/codec/cer/encoder.py b/pyasn1/codec/cer/encoder.py index dd3e2b4..4700de0 100644 --- a/pyasn1/codec/cer/encoder.py +++ b/pyasn1/codec/cer/encoder.py @@ -191,11 +191,6 @@ class Encoder(encoder.Encoder): fixedDefLengthMode = False fixedChunkSize = 1000 - def __call__(self, value, **options): - if 'defMode' not in options: - options.update(defMode=False) - return encoder.Encoder.__call__(self, value, **options) - #: Turns ASN.1 object into CER octet stream. #: #: Takes any ASN.1 object (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative) -- cgit v1.2.1 From c01e1e3be03537451e332031cde07c286582f826 Mon Sep 17 00:00:00 2001 From: Ilya Etingof Date: Thu, 14 Sep 2017 22:33:47 +0200 Subject: docs on OpenType added --- doc/source/docs/api-reference.rst | 1 + doc/source/docs/type/opentype/contents.rst | 8 ++++++++ doc/source/docs/type/opentype/opentype.rst | 14 ++++++++++++++ pyasn1/type/opentype.py | 20 +++++++++++++++++++- 4 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 doc/source/docs/type/opentype/contents.rst create mode 100644 doc/source/docs/type/opentype/opentype.rst diff --git a/doc/source/docs/api-reference.rst b/doc/source/docs/api-reference.rst index 0f98527..d80c45a 100644 --- a/doc/source/docs/api-reference.rst +++ b/doc/source/docs/api-reference.rst @@ -16,6 +16,7 @@ ASN.1 types /docs/type/useful/contents /docs/type/tag/contents /docs/type/namedtype/contents + /docs/type/opentype/contents /docs/type/namedval/contents Transformation codecs diff --git a/doc/source/docs/type/opentype/contents.rst b/doc/source/docs/type/opentype/contents.rst new file mode 100644 index 0000000..78f5a78 --- /dev/null +++ b/doc/source/docs/type/opentype/contents.rst @@ -0,0 +1,8 @@ + +Untyped fields of constructed types +----------------------------------- + +.. toctree:: + :maxdepth: 2 + + /docs/type/opentype/opentype diff --git a/doc/source/docs/type/opentype/opentype.rst b/doc/source/docs/type/opentype/opentype.rst new file mode 100644 index 0000000..2660bd9 --- /dev/null +++ b/doc/source/docs/type/opentype/opentype.rst @@ -0,0 +1,14 @@ + +.. |OpenType| replace:: OpenType + +|OpenType| +----------- + +.. autoclass:: pyasn1.type.opentype.OpenType + :members: + + .. note:: + + The |OpenType| class models an untyped field of a constructed ASN.1 + type. In ASN.1 syntax it is usually represented by the + `ANY DEFINED BY` clause. diff --git a/pyasn1/type/opentype.py b/pyasn1/type/opentype.py index c8f0e64..4e093d6 100644 --- a/pyasn1/type/opentype.py +++ b/pyasn1/type/opentype.py @@ -14,7 +14,8 @@ class OpenType(object): The *DefinedBy* object models the ASN.1 *DEFINED BY* clause which maps values to ASN.1 types in the context of the ASN.1 SEQUENCE/SET type. - DefinedBy objects are immutable and duck-type Python :class:`dict` objects + OpenType objects are duck-type a read-only Python :class:`dict` objects, + however the passed `typeMap` is stored by reference. Parameters ---------- @@ -24,6 +25,23 @@ class OpenType(object): typeMap: :py:class:`dict`: A map of value->ASN.1 type. It's stored by reference and can be mutated later to register new mappings. + + Examples + -------- + + .. code-block:: + + openType = OpenType( + 'id', + {1: Integer(), + 2: OctetString()} + ) + Sequence( + componentType=NamedTypes( + NamedType('id', Integer()), + NamedType('blob', Any(), openType=openType) + ) + ) """ def __init__(self, name, typeMap=None): -- cgit v1.2.1 From 3082b398fd2074a9fe9d5ba49964cbf0353df081 Mon Sep 17 00:00:00 2001 From: Ilya Etingof Date: Thu, 14 Sep 2017 22:57:13 +0200 Subject: minor PEP8 edits --- pyasn1/codec/ber/decoder.py | 5 +++-- pyasn1/codec/ber/encoder.py | 8 ++++---- pyasn1/compat/calling.py | 3 ++- pyasn1/compat/integer.py | 1 - pyasn1/compat/string.py | 2 +- 5 files changed, 10 insertions(+), 9 deletions(-) diff --git a/pyasn1/codec/ber/decoder.py b/pyasn1/codec/ber/decoder.py index 5424195..3c3be9c 100644 --- a/pyasn1/codec/ber/decoder.py +++ b/pyasn1/codec/ber/decoder.py @@ -635,6 +635,7 @@ class UniversalConstructedTypeDecoder(AbstractConstructedDecoder): return asn1Object, substrate + class SequenceOrSequenceOfDecoder(UniversalConstructedTypeDecoder): protoRecordComponent = univ.Sequence() protoSequenceComponent = univ.SequenceOf() @@ -737,7 +738,7 @@ class AnyDecoder(AbstractSimpleDecoder): decodeFun=None, substrateFun=None, **options): if asn1Spec is None or asn1Spec is not None and tagSet != asn1Spec.tagSet: - fullSubstrate=options['fullSubstrate'] + fullSubstrate = options['fullSubstrate'] # untagged Any container, recover inner header substrate length += len(fullSubstrate) - len(substrate) @@ -759,7 +760,7 @@ class AnyDecoder(AbstractSimpleDecoder): # tagged Any type -- consume header substrate header = null else: - fullSubstrate=options['fullSubstrate'] + fullSubstrate = options['fullSubstrate'] # untagged Any, recover header substrate header = fullSubstrate[:-len(substrate)] diff --git a/pyasn1/codec/ber/encoder.py b/pyasn1/codec/ber/encoder.py index b43e209..e52bb49 100644 --- a/pyasn1/codec/ber/encoder.py +++ b/pyasn1/codec/ber/encoder.py @@ -23,9 +23,9 @@ class AbstractItemEncoder(object): if isConstructed: encodedTag |= tag.tagFormatConstructed if tagId < 31: - return (encodedTag | tagId,) + return encodedTag | tagId, else: - substrate = (tagId & 0x7f,) + substrate = tagId & 0x7f, tagId >>= 7 while tagId: substrate = (0x80 | (tagId & 0x7f),) + substrate @@ -36,7 +36,7 @@ class AbstractItemEncoder(object): if not defMode and self.supportIndefLenMode: return (0x80,) if length < 0x80: - return (length,) + return length, else: substrate = () while length: @@ -388,7 +388,7 @@ class ChoiceEncoder(AbstractItemEncoder): class AnyEncoder(OctetStringEncoder): def encodeValue(self, value, encodeFun, **options): - return value.asOctets(), options.get('defMode', True) == False, True + return value.asOctets(), not options.get('defMode', True), True tagMap = { diff --git a/pyasn1/compat/calling.py b/pyasn1/compat/calling.py index 0b2c464..fde25d8 100644 --- a/pyasn1/compat/calling.py +++ b/pyasn1/compat/calling.py @@ -12,7 +12,8 @@ __all__ = ['callable'] if (2, 7) < version_info[:2] < (3, 2): import collections - callable = lambda x: isinstance(x, collections.Callable) + def callable(x): + return isinstance(x, collections.Callable) else: diff --git a/pyasn1/compat/integer.py b/pyasn1/compat/integer.py index 11992c3..0c426a2 100644 --- a/pyasn1/compat/integer.py +++ b/pyasn1/compat/integer.py @@ -106,4 +106,3 @@ else: def bitLength(number): return int(number).bit_length() - diff --git a/pyasn1/compat/string.py b/pyasn1/compat/string.py index 058eb48..24e64b6 100644 --- a/pyasn1/compat/string.py +++ b/pyasn1/compat/string.py @@ -23,4 +23,4 @@ if version_info[:2] <= (2, 5): else: def partition(string, sep): - return string.partition(sep) \ No newline at end of file + return string.partition(sep) -- cgit v1.2.1 From 218acc52cd4574df07536e1bc81bc1eb7a410573 Mon Sep 17 00:00:00 2001 From: Ilya Etingof Date: Fri, 15 Sep 2017 17:01:00 +0200 Subject: fixed crash at SequenceOf native decoder --- CHANGES.rst | 1 + pyasn1/codec/native/decoder.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGES.rst b/CHANGES.rst index 7d7ff33..f8999b7 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -8,6 +8,7 @@ Revision 0.3.5, released XX-09-2017 - Refactored ASN.1 codecs properties to silently enforce proper length and chunk size encoding modes - Fixed DER encoder to always produce primitive encoding +- Fixed crash at SequenceOf native decoder Revision 0.3.4, released 07-09-2017 ----------------------------------- diff --git a/pyasn1/codec/native/decoder.py b/pyasn1/codec/native/decoder.py index ba9811b..70b22a8 100644 --- a/pyasn1/codec/native/decoder.py +++ b/pyasn1/codec/native/decoder.py @@ -38,7 +38,7 @@ class SequenceOfOrSetOfDecoder(object): asn1Value = asn1Spec.clone() for pyValue in pyObject: - asn1Value.append(decodeFun(pyValue, asn1Spec.componentType.asn1Object), **options) + asn1Value.append(decodeFun(pyValue, asn1Spec.componentType), **options) return asn1Value -- cgit v1.2.1 From e337ff621e43666fc707600c7601d154dd799d08 Mon Sep 17 00:00:00 2001 From: Ilya Etingof Date: Fri, 15 Sep 2017 16:55:16 +0200 Subject: run unit tests with full debugging enabled (and ignored) Also fixed a couple of crashes in debug messages --- CHANGES.rst | 2 + pyasn1/codec/ber/decoder.py | 2 +- pyasn1/codec/ber/encoder.py | 2 +- pyasn1/debug.py | 47 +++++++++----- pyasn1/type/univ.py | 6 +- tests/base.py | 22 +++++++ tests/codec/ber/test_decoder.py | 125 +++++++++++++++++++++---------------- tests/codec/ber/test_encoder.py | 73 +++++++++++++--------- tests/codec/cer/test_decoder.py | 9 ++- tests/codec/cer/test_encoder.py | 50 +++++++++------ tests/codec/der/test_decoder.py | 7 ++- tests/codec/der/test_encoder.py | 29 ++++++--- tests/codec/native/test_decoder.py | 33 ++++++---- tests/codec/native/test_encoder.py | 48 +++++++++----- tests/compat/test_binary.py | 7 ++- tests/compat/test_integer.py | 7 ++- tests/compat/test_octets.py | 7 ++- tests/test_debug.py | 7 ++- tests/type/test_char.py | 23 ++++--- tests/type/test_constraint.py | 43 +++++++++---- tests/type/test_namedtype.py | 29 ++++++--- tests/type/test_namedval.py | 6 +- tests/type/test_tag.py | 11 +++- tests/type/test_univ.py | 94 +++++++++++++++++----------- tests/type/test_useful.py | 12 ++-- 25 files changed, 459 insertions(+), 242 deletions(-) create mode 100644 tests/base.py diff --git a/CHANGES.rst b/CHANGES.rst index f8999b7..644f2fe 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -9,6 +9,8 @@ Revision 0.3.5, released XX-09-2017 chunk size encoding modes - Fixed DER encoder to always produce primitive encoding - Fixed crash at SequenceOf native decoder +- Fixed Real.prettyPrint() to fail gracefully on overflow +- Fixed a couple of crashes when debug mode is enabled Revision 0.3.4, released 07-09-2017 ----------------------------------- diff --git a/pyasn1/codec/ber/decoder.py b/pyasn1/codec/ber/decoder.py index 3c3be9c..ee3064f 100644 --- a/pyasn1/codec/ber/decoder.py +++ b/pyasn1/codec/ber/decoder.py @@ -1160,7 +1160,7 @@ class Decoder(object): **options ) if logger: - logger('codec %s yields type %s, value:\n%s\n...remaining substrate is: %s' % (concreteDecoder.__class__.__name__, value.__class__.__name__, value.prettyPrint(), substrate and debug.hexdump(substrate) or '')) + logger('codec %s yields type %s, value:\n%s\n...remaining substrate is: %s' % (concreteDecoder.__class__.__name__, value.__class__.__name__, isinstance(value, base.Asn1Item) and value.prettyPrint() or value, substrate and debug.hexdump(substrate) or '')) state = stStop break if state is stTryAsExplicitTag: diff --git a/pyasn1/codec/ber/encoder.py b/pyasn1/codec/ber/encoder.py index e52bb49..3ac2ef8 100644 --- a/pyasn1/codec/ber/encoder.py +++ b/pyasn1/codec/ber/encoder.py @@ -476,7 +476,7 @@ class Encoder(object): logger = None if logger: - logger('encoder called in %sdef mode, chunk size %s for type %s, value:\n%s' % (not defMode and 'in' or '', maxChunkSize, value.prettyPrintType(), value.prettyPrint())) + logger('encoder called in %sdef mode, chunk size %s for type %s, value:\n%s' % (not options.get('defMode', True) and 'in' or '', options.get('maxChunkSize', 0), value.prettyPrintType(), value.prettyPrint())) if self.fixedDefLengthMode is not None: options.update(defMode=self.fixedDefLengthMode) diff --git a/pyasn1/debug.py b/pyasn1/debug.py index 04a9da5..24ac5ce 100644 --- a/pyasn1/debug.py +++ b/pyasn1/debug.py @@ -28,25 +28,31 @@ class Printer(object): def __init__(self, logger=None, handler=None, formatter=None): if logger is None: logger = logging.getLogger('pyasn1') + logger.setLevel(logging.DEBUG) + if handler is None: handler = logging.StreamHandler() + if formatter is None: formatter = logging.Formatter('%(asctime)s %(name)s: %(message)s') + handler.setFormatter(formatter) handler.setLevel(logging.DEBUG) logger.addHandler(handler) + self.__logger = logger def __call__(self, msg): self.__logger.debug(msg) def __str__(self): - return '' + return '' if hasattr(logging, 'NullHandler'): NullHandler = logging.NullHandler + else: # Python 2.6 and older class NullHandler(logging.Handler): @@ -55,36 +61,39 @@ else: class Debug(object): - defaultPrinter = None + defaultPrinter = Printer() def __init__(self, *flags, **options): self._flags = flagNone - if options.get('printer') is not None: - self._printer = options.get('printer') - elif self.defaultPrinter is not None: - self._printer = self.defaultPrinter + if 'loggerName' in options: # route our logs to parent logger self._printer = Printer( logger=logging.getLogger(options['loggerName']), handler=NullHandler() ) + + elif 'printer' in options: + self._printer = options.get('printer') + else: - self._printer = Printer() - self('running pyasn1 version %s' % __version__) - for f in flags: - inverse = f and f[0] in ('!', '~') + self._printer = self.defaultPrinter + + self._printer('running pyasn1 %s, debug flags %s' % (__version__, ', '.join(flags))) + + for flag in flags: + inverse = flag and flag[0] in ('!', '~') if inverse: - f = f[1:] + flag = flag[1:] try: if inverse: - self._flags &= ~flagMap[f] + self._flags &= ~flagMap[flag] else: - self._flags |= flagMap[f] + self._flags |= flagMap[flag] except KeyError: - raise error.PyAsn1Error('bad debug flag %s' % f) + raise error.PyAsn1Error('bad debug flag %s' % flag) - self('debug category \'%s\' %s' % (f, inverse and 'disabled' or 'enabled')) + self._printer("debug category '%s' %s" % (flag, inverse and 'disabled' or 'enabled')) def __str__(self): return 'logger %s, flags %x' % (self._printer, self._flags) @@ -102,9 +111,13 @@ class Debug(object): logger = 0 -def setLogger(l): +def setLogger(userLogger): global logger - logger = l + + if userLogger: + logger = userLogger + else: + logger = 0 def hexdump(octets): diff --git a/pyasn1/type/univ.py b/pyasn1/type/univ.py index 63c21eb..1e7c8ce 100644 --- a/pyasn1/type/univ.py +++ b/pyasn1/type/univ.py @@ -1498,7 +1498,11 @@ class Real(base.AbstractSimpleAsn1Item): if self.isInf: return self.prettyOut(self._value) else: - return str(float(self)) + try: + return str(float(self)) + + except OverflowError: + return '' @property def isPlusInf(self): diff --git a/tests/base.py b/tests/base.py new file mode 100644 index 0000000..6faef6e --- /dev/null +++ b/tests/base.py @@ -0,0 +1,22 @@ +# +# This file is part of pyasn1 software. +# +# Copyright (c) 2005-2017, Ilya Etingof +# License: http://pyasn1.sf.net/license.html +# +import sys +try: + import unittest2 as unittest +except ImportError: + import unittest + +from pyasn1 import debug + + +class BaseTestCase(unittest.TestCase): + + def setUp(self): + debug.setLogger(debug.Debug('all', printer=lambda *x: None)) + + def tearDown(self): + debug.setLogger(None) diff --git a/tests/codec/ber/test_decoder.py b/tests/codec/ber/test_decoder.py index d2f02ad..5ec3a5f 100644 --- a/tests/codec/ber/test_decoder.py +++ b/tests/codec/ber/test_decoder.py @@ -10,13 +10,15 @@ try: except ImportError: import unittest +from tests.base import BaseTestCase + from pyasn1.type import tag, namedtype, univ, char from pyasn1.codec.ber import decoder, eoo from pyasn1.compat.octets import ints2octs, str2octs, null from pyasn1.error import PyAsn1Error -class LargeTagDecoderTestCase(unittest.TestCase): +class LargeTagDecoderTestCase(BaseTestCase): def testLargeTag(self): assert decoder.decode(ints2octs((127, 141, 245, 182, 253, 47, 3, 2, 1, 1))) == (1, null) @@ -29,12 +31,12 @@ class LargeTagDecoderTestCase(unittest.TestCase): ints2octs((0x9f, 0x00, 0x02, 0x01, 0x02)), asn1Spec=integer) -class DecoderCacheTestCase(unittest.TestCase): +class DecoderCacheTestCase(BaseTestCase): def testCache(self): assert decoder.decode(ints2octs((0x1f, 2, 1, 0))) == decoder.decode(ints2octs((0x1f, 2, 1, 0))) -class IntegerDecoderTestCase(unittest.TestCase): +class IntegerDecoderTestCase(BaseTestCase): def testPosInt(self): assert decoder.decode(ints2octs((2, 1, 12))) == (12, null) @@ -82,7 +84,7 @@ class IntegerDecoderTestCase(unittest.TestCase): assert 0, 'wrong tagFormat worked out' -class BooleanDecoderTestCase(unittest.TestCase): +class BooleanDecoderTestCase(BaseTestCase): def testTrue(self): assert decoder.decode(ints2octs((1, 1, 1))) == (1, null) @@ -104,7 +106,7 @@ class BooleanDecoderTestCase(unittest.TestCase): assert 0, 'wrong tagFormat worked out' -class BitStringDecoderTestCase(unittest.TestCase): +class BitStringDecoderTestCase(BaseTestCase): def testDefMode(self): assert decoder.decode( ints2octs((3, 3, 1, 169, 138)) @@ -128,14 +130,14 @@ class BitStringDecoderTestCase(unittest.TestCase): def testDefModeChunkedSubst(self): assert decoder.decode( ints2octs((35, 8, 3, 2, 0, 169, 3, 2, 1, 138)), - substrateFun=lambda a, b, c: (b, c) - ) == (ints2octs((3, 2, 0, 169, 3, 2, 1, 138)), 8) + substrateFun=lambda a, b, c: (b, b[c:]) + ) == (ints2octs((3, 2, 0, 169, 3, 2, 1, 138)), str2octs('')) def testIndefModeChunkedSubst(self): assert decoder.decode( ints2octs((35, 128, 3, 2, 0, 169, 3, 2, 1, 138, 0, 0)), - substrateFun=lambda a, b, c: (b, c) - ) == (ints2octs((3, 2, 0, 169, 3, 2, 1, 138, 0, 0)), -1) + substrateFun=lambda a, b, c: (b, str2octs('')) + ) == (ints2octs((3, 2, 0, 169, 3, 2, 1, 138, 0, 0)), str2octs('')) def testTypeChecking(self): try: @@ -146,7 +148,7 @@ class BitStringDecoderTestCase(unittest.TestCase): assert 0, 'accepted mis-encoded bit-string constructed out of an integer' -class OctetStringDecoderTestCase(unittest.TestCase): +class OctetStringDecoderTestCase(BaseTestCase): def testDefMode(self): assert decoder.decode( ints2octs((4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120)) @@ -173,21 +175,21 @@ class OctetStringDecoderTestCase(unittest.TestCase): assert decoder.decode( ints2octs( (36, 23, 4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, 110, 32, 4, 3, 102, 111, 120)), - substrateFun=lambda a, b, c: (b, c) - ) == (ints2octs((4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, 110, 32, 4, 3, 102, 111, 120)), - 23) + substrateFun=lambda a, b, c: (b, b[c:]) + ) == (ints2octs((4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, 110, 32, 4, 3, 102, 111, 120)), str2octs('')) def testIndefModeChunkedSubst(self): assert decoder.decode( ints2octs((36, 128, 4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, 110, 32, 4, 3, 102, 111, 120, 0, 0)), - substrateFun=lambda a, b, c: (b, c) + substrateFun=lambda a, b, c: (b, str2octs('')) ) == (ints2octs( - (4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, 110, 32, 4, 3, 102, 111, 120, 0, 0)), -1) + (4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, 110, 32, 4, 3, 102, 111, 120, 0, 0)), str2octs('')) -class ExpTaggedOctetStringDecoderTestCase(unittest.TestCase): +class ExpTaggedOctetStringDecoderTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) self.o = univ.OctetString( 'Quick brown fox', tagSet=univ.OctetString.tagSet.tagExplicitly( @@ -233,20 +235,20 @@ class ExpTaggedOctetStringDecoderTestCase(unittest.TestCase): def testDefModeSubst(self): assert decoder.decode( ints2octs((101, 17, 4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120)), - substrateFun=lambda a, b, c: (b, c) - ) == (ints2octs((4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120)), 17) + substrateFun=lambda a, b, c: (b, b[c:]) + ) == (ints2octs((4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120)), str2octs('')) def testIndefModeSubst(self): assert decoder.decode( ints2octs(( 101, 128, 36, 128, 4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120, 0, 0, 0, 0)), - substrateFun=lambda a, b, c: (b, c) + substrateFun=lambda a, b, c: (b, str2octs('')) ) == (ints2octs( - (36, 128, 4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120, 0, 0, 0, 0)), -1) + (36, 128, 4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120, 0, 0, 0, 0)), str2octs('')) -class NullDecoderTestCase(unittest.TestCase): +class NullDecoderTestCase(BaseTestCase): def testNull(self): assert decoder.decode(ints2octs((5, 0))) == (null, null) @@ -261,7 +263,7 @@ class NullDecoderTestCase(unittest.TestCase): # Useful analysis of OID encoding issues could be found here: # http://www.viathinksoft.de/~daniel-marschall/asn.1/oid_facts.html -class ObjectIdentifierDecoderTestCase(unittest.TestCase): +class ObjectIdentifierDecoderTestCase(BaseTestCase): def testOne(self): assert decoder.decode( ints2octs((6, 6, 43, 6, 0, 191, 255, 126)) @@ -402,7 +404,7 @@ class ObjectIdentifierDecoderTestCase(unittest.TestCase): ) == ((2, 999, 18446744073709551535184467440737095), null) -class RealDecoderTestCase(unittest.TestCase): +class RealDecoderTestCase(BaseTestCase): def testChar(self): assert decoder.decode( ints2octs((9, 7, 3, 49, 50, 51, 69, 49, 49)) @@ -478,23 +480,25 @@ class RealDecoderTestCase(unittest.TestCase): if sys.version_info[0:2] > (2, 5): - class UniversalStringDecoderTestCase(unittest.TestCase): + class UniversalStringDecoderTestCase(BaseTestCase): def testDecoder(self): assert decoder.decode(ints2octs((28, 12, 0, 0, 0, 97, 0, 0, 0, 98, 0, 0, 0, 99))) == (char.UniversalString(sys.version_info[0] == 3 and 'abc' or unicode('abc')), null) -class BMPStringDecoderTestCase(unittest.TestCase): +class BMPStringDecoderTestCase(BaseTestCase): def testDecoder(self): assert decoder.decode(ints2octs((30, 6, 0, 97, 0, 98, 0, 99))) == (char.BMPString(sys.version_info[0] == 3 and 'abc' or unicode('abc')), null) -class UTF8StringDecoderTestCase(unittest.TestCase): +class UTF8StringDecoderTestCase(BaseTestCase): def testDecoder(self): assert decoder.decode(ints2octs((12, 3, 97, 98, 99))) == (char.UTF8String(sys.version_info[0] == 3 and 'abc' or unicode('abc')), null) -class SequenceOfDecoderTestCase(unittest.TestCase): +class SequenceOfDecoderTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) + self.s = univ.SequenceOf(componentType=univ.OctetString()) self.s.setComponentByPosition(0, univ.OctetString('quick brown')) @@ -524,7 +528,7 @@ class SequenceOfDecoderTestCase(unittest.TestCase): ) == (self.s, null) -class ExpTaggedSequenceOfDecoderTestCase(unittest.TestCase): +class ExpTaggedSequenceOfDecoderTestCase(BaseTestCase): def testWithSchema(self): s = univ.SequenceOf().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 3)) @@ -545,8 +549,9 @@ class ExpTaggedSequenceOfDecoderTestCase(unittest.TestCase): assert s.tagSet == s2.tagSet -class SequenceOfDecoderWithSchemaTestCase(unittest.TestCase): +class SequenceOfDecoderWithSchemaTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) self.s = univ.SequenceOf(componentType=univ.OctetString()) self.s.setComponentByPosition(0, univ.OctetString('quick brown')) @@ -571,8 +576,9 @@ class SequenceOfDecoderWithSchemaTestCase(unittest.TestCase): ) == (self.s, null) -class SetOfDecoderTestCase(unittest.TestCase): +class SetOfDecoderTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) self.s = univ.SetOf(componentType=univ.OctetString()) self.s.setComponentByPosition(0, univ.OctetString('quick brown')) @@ -602,8 +608,9 @@ class SetOfDecoderTestCase(unittest.TestCase): ) == (self.s, null) -class SetOfDecoderWithSchemaTestCase(unittest.TestCase): +class SetOfDecoderWithSchemaTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) self.s = univ.SetOf(componentType=univ.OctetString()) self.s.setComponentByPosition(0, univ.OctetString('quick brown')) @@ -628,8 +635,9 @@ class SetOfDecoderWithSchemaTestCase(unittest.TestCase): ) == (self.s, null) -class SequenceDecoderTestCase(unittest.TestCase): +class SequenceDecoderTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('place-holder', univ.Null(null)), @@ -665,16 +673,15 @@ class SequenceDecoderTestCase(unittest.TestCase): def testWithOptionalAndDefaultedDefModeSubst(self): assert decoder.decode( ints2octs((48, 18, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1)), - substrateFun=lambda a, b, c: (b, c) - ) == (ints2octs((5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1)), 18) + substrateFun=lambda a, b, c: (b, b[c:]) + ) == (ints2octs((5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1)), str2octs('')) def testWithOptionalAndDefaultedIndefModeSubst(self): assert decoder.decode( - ints2octs((48, 128, 5, 0, 36, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0, 2, 1, 1, - 0, 0)), - substrateFun=lambda a, b, c: (b, c) + ints2octs((48, 128, 5, 0, 36, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0)), + substrateFun=lambda a, b, c: (b, str2octs('')) ) == (ints2octs( - (5, 0, 36, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0)), -1) + (5, 0, 36, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0)), str2octs('')) def testTagFormat(self): try: @@ -687,8 +694,9 @@ class SequenceDecoderTestCase(unittest.TestCase): assert 0, 'wrong tagFormat worked out' -class SequenceDecoderWithSchemaTestCase(unittest.TestCase): +class SequenceDecoderWithSchemaTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('place-holder', univ.Null(null)), @@ -823,8 +831,9 @@ class SequenceDecoderWithSchemaTestCase(unittest.TestCase): ) == (self.s, null) -class SetDecoderTestCase(unittest.TestCase): +class SetDecoderTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) self.s = univ.Set( componentType=namedtype.NamedTypes( namedtype.NamedType('place-holder', univ.Null(null)), @@ -860,15 +869,15 @@ class SetDecoderTestCase(unittest.TestCase): def testWithOptionalAndDefaultedDefModeSubst(self): assert decoder.decode( ints2octs((49, 18, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1)), - substrateFun=lambda a, b, c: (b, c) - ) == (ints2octs((5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1)), 18) + substrateFun=lambda a, b, c: (b, b[c:]) + ) == (ints2octs((5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1)), str2octs('')) def testWithOptionalAndDefaultedIndefModeSubst(self): assert decoder.decode( ints2octs((49, 128, 5, 0, 36, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0)), - substrateFun=lambda a, b, c: (b, c) + substrateFun=lambda a, b, c: (b, str2octs('')) ) == (ints2octs( - (5, 0, 36, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0)), -1) + (5, 0, 36, 128, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0)), str2octs('')) def testTagFormat(self): try: @@ -881,8 +890,9 @@ class SetDecoderTestCase(unittest.TestCase): assert 0, 'wrong tagFormat worked out' -class SetDecoderWithSchemaTestCase(unittest.TestCase): +class SetDecoderWithSchemaTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) self.s = univ.Set( componentType=namedtype.NamedTypes( namedtype.NamedType('place-holder', univ.Null(null)), @@ -1020,8 +1030,9 @@ class SetDecoderWithSchemaTestCase(unittest.TestCase): ) == (self.s, null) -class SequenceOfWithExpTaggedOctetStringDecoder(unittest.TestCase): +class SequenceOfWithExpTaggedOctetStringDecoder(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) self.s = univ.SequenceOf( componentType=univ.OctetString().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3)) ) @@ -1065,8 +1076,9 @@ class SequenceOfWithExpTaggedOctetStringDecoder(unittest.TestCase): assert s.tagSet == self.s.tagSet -class SequenceWithExpTaggedOctetStringDecoder(unittest.TestCase): +class SequenceWithExpTaggedOctetStringDecoder(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType( @@ -1114,8 +1126,9 @@ class SequenceWithExpTaggedOctetStringDecoder(unittest.TestCase): assert s.tagSet == self.s.tagSet -class ChoiceDecoderTestCase(unittest.TestCase): +class ChoiceDecoderTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) self.s = univ.Choice( componentType=namedtype.NamedTypes( namedtype.NamedType('place-holder', univ.Null(null)), @@ -1153,8 +1166,9 @@ class ChoiceDecoderTestCase(unittest.TestCase): assert decoder.decode(ints2octs((164, 128, 5, 0, 0, 0)), asn1Spec=s) == (s, null) -class AnyDecoderTestCase(unittest.TestCase): +class AnyDecoderTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) self.s = univ.Any() def testByUntagged(self): @@ -1187,18 +1201,18 @@ class AnyDecoderTestCase(unittest.TestCase): assert decoder.decode( ints2octs((4, 3, 102, 111, 120)), asn1Spec=self.s, - substrateFun=lambda a, b, c: (b, c) - ) == (ints2octs((4, 3, 102, 111, 120)), 5) + substrateFun=lambda a, b, c: (b, b[c:]) + ) == (ints2octs((4, 3, 102, 111, 120)), str2octs('')) def testTaggedExSubst(self): assert decoder.decode( ints2octs((164, 5, 4, 3, 102, 111, 120)), asn1Spec=self.s, - substrateFun=lambda a, b, c: (b, c) - ) == (ints2octs((164, 5, 4, 3, 102, 111, 120)), 7) + substrateFun=lambda a, b, c: (b, b[c:]) + ) == (ints2octs((164, 5, 4, 3, 102, 111, 120)), str2octs('')) -class EndOfOctetsTestCase(unittest.TestCase): +class EndOfOctetsTestCase(BaseTestCase): def testUnexpectedEoo(self): try: decoder.decode(ints2octs((0, 0))) @@ -1249,8 +1263,9 @@ class EndOfOctetsTestCase(unittest.TestCase): assert 0, 'end-of-contents octets accepted with unexpected data' -class NonStringDecoderTestCase(unittest.TestCase): +class NonStringDecoderTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('place-holder', univ.Null(null)), diff --git a/tests/codec/ber/test_encoder.py b/tests/codec/ber/test_encoder.py index 7935afe..153ebd7 100644 --- a/tests/codec/ber/test_encoder.py +++ b/tests/codec/ber/test_encoder.py @@ -5,20 +5,25 @@ # License: http://pyasn1.sf.net/license.html # import sys + try: import unittest2 as unittest + except ImportError: import unittest +from tests.base import BaseTestCase + from pyasn1.type import tag, namedtype, univ, char from pyasn1.codec.ber import encoder from pyasn1.compat.octets import ints2octs from pyasn1.error import PyAsn1Error -from sys import version_info class LargeTagEncoderTestCase(unittest.TestCase): def setUp(self): + BaseTestCase.setUp(self) + self.o = univ.Integer().subtype( value=1, explicitTag=tag.Tag(tag.tagClassApplication, tag.tagFormatSimple, 0xdeadbeaf) ) @@ -27,7 +32,7 @@ class LargeTagEncoderTestCase(unittest.TestCase): assert encoder.encode(self.o) == ints2octs((127, 141, 245, 182, 253, 47, 3, 2, 1, 1)) -class IntegerEncoderTestCase(unittest.TestCase): +class IntegerEncoderTestCase(BaseTestCase): def testPosInt(self): assert encoder.encode(univ.Integer(12)) == ints2octs((2, 1, 12)) @@ -57,7 +62,7 @@ class IntegerEncoderTestCase(unittest.TestCase): ) == ints2octs((2, 9, 255, 0, 0, 0, 0, 0, 0, 0, 1)) -class BooleanEncoderTestCase(unittest.TestCase): +class BooleanEncoderTestCase(BaseTestCase): def testTrue(self): assert encoder.encode(univ.Boolean(1)) == ints2octs((1, 1, 1)) @@ -65,8 +70,9 @@ class BooleanEncoderTestCase(unittest.TestCase): assert encoder.encode(univ.Boolean(0)) == ints2octs((1, 1, 0)) -class BitStringEncoderTestCase(unittest.TestCase): +class BitStringEncoderTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) self.b = univ.BitString((1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1)) def testDefMode(self): @@ -91,8 +97,9 @@ class BitStringEncoderTestCase(unittest.TestCase): assert encoder.encode(univ.BitString([])) == ints2octs((3, 1, 0)) -class OctetStringEncoderTestCase(unittest.TestCase): +class OctetStringEncoderTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) self.o = univ.OctetString('Quick brown fox') def testDefMode(self): @@ -117,8 +124,9 @@ class OctetStringEncoderTestCase(unittest.TestCase): 32, 4, 3, 102, 111, 120, 0, 0)) -class ExpTaggedOctetStringEncoderTestCase(unittest.TestCase): +class ExpTaggedOctetStringEncoderTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) self.o = univ.OctetString().subtype( value='Quick brown fox', explicitTag=tag.Tag(tag.tagClassApplication, tag.tagFormatSimple, 5) @@ -145,12 +153,12 @@ class ExpTaggedOctetStringEncoderTestCase(unittest.TestCase): ) == ints2octs((101, 128, 36, 128, 4, 4, 81, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 4, 111, 119, 110, 32, 4, 3, 102, 111, 120, 0, 0, 0, 0)) -class NullEncoderTestCase(unittest.TestCase): +class NullEncoderTestCase(BaseTestCase): def testNull(self): assert encoder.encode(univ.Null('')) == ints2octs((5, 0)) -class ObjectIdentifierEncoderTestCase(unittest.TestCase): +class ObjectIdentifierEncoderTestCase(BaseTestCase): def testOne(self): assert encoder.encode( univ.ObjectIdentifier((1, 3, 6, 0, 0xffffe)) @@ -258,7 +266,7 @@ class ObjectIdentifierEncoderTestCase(unittest.TestCase): 0xB8, 0xCB, 0xE2, 0xB6, 0x47)) -class RealEncoderTestCase(unittest.TestCase): +class RealEncoderTestCase(BaseTestCase): def testChar(self): assert encoder.encode( univ.Real((123, 10, 11)) @@ -322,26 +330,26 @@ class RealEncoderTestCase(unittest.TestCase): assert encoder.encode(univ.Real(0)) == ints2octs((9, 0)) -if version_info[0:2] > (2, 5): - class UniversalStringEncoderTestCase(unittest.TestCase): +if sys.version_info[0:2] > (2, 5): + class UniversalStringEncoderTestCase(BaseTestCase): def testEncoding(self): - assert encoder.encode(char.UniversalString(version_info[0] == 3 and 'abc' or unicode('abc'))) == ints2octs( + assert encoder.encode(char.UniversalString(sys.version_info[0] == 3 and 'abc' or unicode('abc'))) == ints2octs( (28, 12, 0, 0, 0, 97, 0, 0, 0, 98, 0, 0, 0, 99)), 'Incorrect encoding' -class BMPStringEncoderTestCase(unittest.TestCase): +class BMPStringEncoderTestCase(BaseTestCase): def testEncoding(self): - assert encoder.encode(char.BMPString(version_info[0] == 3 and 'abc' or unicode('abc'))) == ints2octs( + assert encoder.encode(char.BMPString(sys.version_info[0] == 3 and 'abc' or unicode('abc'))) == ints2octs( (30, 6, 0, 97, 0, 98, 0, 99)), 'Incorrect encoding' -class UTF8StringEncoderTestCase(unittest.TestCase): +class UTF8StringEncoderTestCase(BaseTestCase): def testEncoding(self): - assert encoder.encode(char.UTF8String(version_info[0] == 3 and 'abc' or unicode('abc'))) == ints2octs( + assert encoder.encode(char.UTF8String(sys.version_info[0] == 3 and 'abc' or unicode('abc'))) == ints2octs( (12, 3, 97, 98, 99)), 'Incorrect encoding' -class SequenceOfEncoderTestCase(unittest.TestCase): +class SequenceOfEncoderTestCase(BaseTestCase): def testEmpty(self): s = univ.SequenceOf() assert encoder.encode(s) == ints2octs((48, 0)) @@ -373,8 +381,9 @@ class SequenceOfEncoderTestCase(unittest.TestCase): ) == ints2octs((48, 128, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 0, 0)) -class SequenceOfEncoderWithSchemaTestCase(unittest.TestCase): +class SequenceOfEncoderWithSchemaTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) self.s = univ.SequenceOf(componentType=univ.OctetString()) def __init(self): @@ -404,7 +413,7 @@ class SequenceOfEncoderWithSchemaTestCase(unittest.TestCase): ) == ints2octs((48, 128, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 0, 0)) -class SetOfEncoderTestCase(unittest.TestCase): +class SetOfEncoderTestCase(BaseTestCase): def testEmpty(self): s = univ.SetOf() assert encoder.encode(s) == ints2octs((49, 0)) @@ -436,8 +445,9 @@ class SetOfEncoderTestCase(unittest.TestCase): ) == ints2octs((49, 128, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 0, 0)) -class SetOfEncoderWithSchemaTestCase(unittest.TestCase): +class SetOfEncoderWithSchemaTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) self.s = univ.SetOf(componentType=univ.OctetString()) def __init(self): @@ -467,8 +477,9 @@ class SetOfEncoderWithSchemaTestCase(unittest.TestCase): ) == ints2octs((49, 128, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 0, 0)) -class SequenceEncoderTestCase(unittest.TestCase): +class SequenceEncoderTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) self.s = univ.Sequence() self.s.setComponentByPosition(0, univ.Null('')) self.s.setComponentByPosition(1, univ.OctetString('quick brown')) @@ -493,8 +504,9 @@ class SequenceEncoderTestCase(unittest.TestCase): ) == ints2octs((48, 128, 5, 0, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0)) -class SequenceEncoderWithSchemaTestCase(unittest.TestCase): +class SequenceEncoderWithSchemaTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('place-holder', univ.Null()), @@ -617,8 +629,9 @@ class SequenceEncoderWithSchemaTestCase(unittest.TestCase): 0, 2, 1, 1, 0, 0)) -class ExpTaggedSequenceEncoderTestCase(unittest.TestCase): +class ExpTaggedSequenceEncoderTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('number', univ.Integer()), @@ -642,8 +655,9 @@ class ExpTaggedSequenceEncoderTestCase(unittest.TestCase): ) == ints2octs((101, 128, 48, 128, 2, 1, 12, 0, 0, 0, 0)) -class SetEncoderTestCase(unittest.TestCase): +class SetEncoderTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) self.s = univ.Set() self.s.setComponentByPosition(0, univ.Null('')) self.s.setComponentByPosition(1, univ.OctetString('quick brown')) @@ -668,8 +682,9 @@ class SetEncoderTestCase(unittest.TestCase): ) == ints2octs((49, 128, 5, 0, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0)) -class SetEncoderWithSchemaTestCase(unittest.TestCase): +class SetEncoderWithSchemaTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) self.s = univ.Set( componentType=namedtype.NamedTypes( namedtype.NamedType('place-holder', univ.Null()), @@ -791,7 +806,7 @@ class SetEncoderWithSchemaTestCase(unittest.TestCase): ) == ints2octs((49, 128, 5, 0, 36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0, 2, 1, 1, 0, 0)) -class ChoiceEncoderTestCase(unittest.TestCase): +class ChoiceEncoderTestCase(BaseTestCase): def testEmpty(self): s = univ.Choice() @@ -834,8 +849,9 @@ class ChoiceEncoderTestCase(unittest.TestCase): ) == ints2octs((36, 128, 4, 4, 113, 117, 105, 99, 4, 4, 107, 32, 98, 114, 4, 3, 111, 119, 110, 0, 0)) -class ChoiceEncoderWithSchemaTestCase(unittest.TestCase): +class ChoiceEncoderWithSchemaTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) self.s = univ.Choice( componentType=namedtype.NamedTypes( namedtype.NamedType('place-holder', univ.Null('')), @@ -877,8 +893,9 @@ class ChoiceEncoderWithSchemaTestCase(unittest.TestCase): (164, 128, 36, 128, 4, 3, 97, 98, 99, 4, 3, 100, 101, 102, 4, 2, 103, 104, 0, 0, 0, 0)) -class AnyEncoderTestCase(unittest.TestCase): +class AnyEncoderTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) self.s = univ.Any(encoder.encode(univ.OctetString('fox'))) def testUntagged(self): diff --git a/tests/codec/cer/test_decoder.py b/tests/codec/cer/test_decoder.py index 3ae1f99..828c17f 100644 --- a/tests/codec/cer/test_decoder.py +++ b/tests/codec/cer/test_decoder.py @@ -5,17 +5,20 @@ # License: http://pyasn1.sf.net/license.html # import sys + try: import unittest2 as unittest except ImportError: import unittest +from tests.base import BaseTestCase + from pyasn1.codec.cer import decoder from pyasn1.compat.octets import ints2octs, str2octs, null from pyasn1.error import PyAsn1Error -class BooleanDecoderTestCase(unittest.TestCase): +class BooleanDecoderTestCase(BaseTestCase): def testTrue(self): assert decoder.decode(ints2octs((1, 1, 255))) == (1, null) @@ -34,7 +37,7 @@ class BooleanDecoderTestCase(unittest.TestCase): except PyAsn1Error: pass -class BitStringDecoderTestCase(unittest.TestCase): +class BitStringDecoderTestCase(BaseTestCase): def testShortMode(self): assert decoder.decode( ints2octs((3, 3, 6, 170, 128)) @@ -48,7 +51,7 @@ class BitStringDecoderTestCase(unittest.TestCase): # TODO: test failures on short chunked and long unchunked substrate samples -class OctetStringDecoderTestCase(unittest.TestCase): +class OctetStringDecoderTestCase(BaseTestCase): def testShortMode(self): assert decoder.decode( ints2octs((4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120)), diff --git a/tests/codec/cer/test_encoder.py b/tests/codec/cer/test_encoder.py index 7b0cc8c..32d87b0 100644 --- a/tests/codec/cer/test_encoder.py +++ b/tests/codec/cer/test_encoder.py @@ -5,18 +5,21 @@ # License: http://pyasn1.sf.net/license.html # import sys + try: import unittest2 as unittest except ImportError: import unittest +from tests.base import BaseTestCase + from pyasn1.type import namedtype, univ, useful from pyasn1.codec.cer import encoder from pyasn1.compat.octets import ints2octs from pyasn1.error import PyAsn1Error -class BooleanEncoderTestCase(unittest.TestCase): +class BooleanEncoderTestCase(BaseTestCase): def testTrue(self): assert encoder.encode(univ.Boolean(1)) == ints2octs((1, 1, 255)) @@ -24,7 +27,7 @@ class BooleanEncoderTestCase(unittest.TestCase): assert encoder.encode(univ.Boolean(0)) == ints2octs((1, 1, 0)) -class BitStringEncoderTestCase(unittest.TestCase): +class BitStringEncoderTestCase(BaseTestCase): def testShortMode(self): assert encoder.encode( univ.BitString((1, 0) * 5) @@ -34,7 +37,7 @@ class BitStringEncoderTestCase(unittest.TestCase): assert encoder.encode(univ.BitString((1, 0) * 501)) == ints2octs((3, 127, 6) + (170,) * 125 + (128,)) -class OctetStringEncoderTestCase(unittest.TestCase): +class OctetStringEncoderTestCase(BaseTestCase): def testShortMode(self): assert encoder.encode( univ.OctetString('Quick brown fox') @@ -46,7 +49,7 @@ class OctetStringEncoderTestCase(unittest.TestCase): ) == ints2octs((36, 128, 4, 130, 3, 232) + (81,) * 1000 + (4, 1, 81, 0, 0)) -class GeneralizedTimeEncoderTestCase(unittest.TestCase): +class GeneralizedTimeEncoderTestCase(BaseTestCase): # def testExtraZeroInSeconds(self): # try: # assert encoder.encode( @@ -104,7 +107,7 @@ class GeneralizedTimeEncoderTestCase(unittest.TestCase): ) == ints2octs((24, 13, 50, 48, 49, 55, 48, 56, 48, 49, 49, 50, 48, 49, 90)) -class UTCTimeEncoderTestCase(unittest.TestCase): +class UTCTimeEncoderTestCase(BaseTestCase): def testFractionOfSecond(self): try: assert encoder.encode( @@ -146,7 +149,7 @@ class UTCTimeEncoderTestCase(unittest.TestCase): ) == ints2octs((23, 11, 57, 57, 48, 56, 48, 49, 49, 50, 48, 49, 90)) -class SequenceOfEncoderTestCase(unittest.TestCase): +class SequenceOfEncoderTestCase(BaseTestCase): def testEmpty(self): s = univ.SequenceOf() assert encoder.encode(s) == ints2octs((48, 128, 0, 0)) @@ -176,8 +179,9 @@ class SequenceOfEncoderTestCase(unittest.TestCase): assert encoder.encode(s) == ints2octs((48, 128, 4, 1, 97, 4, 1, 98, 0, 0)) -class SequenceOfEncoderWithSchemaTestCase(unittest.TestCase): +class SequenceOfEncoderWithSchemaTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) self.s = univ.SequenceOf(componentType=univ.OctetString()) def testEmpty(self): @@ -209,7 +213,7 @@ class SequenceOfEncoderWithSchemaTestCase(unittest.TestCase): assert encoder.encode(self.s) == ints2octs((48, 128, 4, 1, 97, 4, 1, 98, 0, 0)) -class SetOfEncoderTestCase(unittest.TestCase): +class SetOfEncoderTestCase(BaseTestCase): def testEmpty(self): s = univ.SetOf() assert encoder.encode(s) == ints2octs((49, 128, 0, 0)) @@ -239,8 +243,9 @@ class SetOfEncoderTestCase(unittest.TestCase): assert encoder.encode(s) == ints2octs((49, 128, 4, 1, 97, 4, 1, 98, 0, 0)) -class SetOfEncoderWithSchemaTestCase(unittest.TestCase): +class SetOfEncoderWithSchemaTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) self.s = univ.SetOf(componentType=univ.OctetString()) def testEmpty(self): @@ -276,8 +281,9 @@ class SetOfEncoderWithSchemaTestCase(unittest.TestCase): assert encoder.encode(self.s) == ints2octs((49, 128, 4, 1, 97, 4, 1, 98, 0, 0)) -class SetEncoderTestCase(unittest.TestCase): +class SetEncoderTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) self.s = univ.Set() self.s.setComponentByPosition(0, univ.Null('')) self.s.setComponentByPosition(1, univ.OctetString('quick brown')) @@ -302,8 +308,9 @@ class SetEncoderTestCase(unittest.TestCase): ) == ints2octs((49, 128, 2, 1, 1, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 5, 0, 0, 0)) -class SetEncoderWithSchemaTestCase(unittest.TestCase): +class SetEncoderWithSchemaTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) self.s = univ.Set(componentType=namedtype.NamedTypes( namedtype.NamedType('place-holder', univ.Null('')), namedtype.OptionalNamedType('first-name', univ.OctetString()), @@ -353,8 +360,9 @@ class SetEncoderWithSchemaTestCase(unittest.TestCase): ) == ints2octs((49, 128, 2, 1, 1, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 5, 0, 0, 0)) -class SetWithChoiceWithSchemaEncoderTestCase(unittest.TestCase): +class SetWithChoiceWithSchemaEncoderTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) c = univ.Choice(componentType=namedtype.NamedTypes( namedtype.NamedType('actual', univ.Boolean(0)) )) @@ -370,8 +378,9 @@ class SetWithChoiceWithSchemaEncoderTestCase(unittest.TestCase): assert encoder.encode(self.s) == ints2octs((49, 128, 1, 1, 255, 5, 0, 0, 0)) -class SetEncoderTestCase(unittest.TestCase): +class SetEncoderTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) self.s = univ.Set() self.s.setComponentByPosition(0, univ.Null('')) self.s.setComponentByPosition(1, univ.OctetString('quick brown')) @@ -396,8 +405,9 @@ class SetEncoderTestCase(unittest.TestCase): ) == ints2octs((49, 128, 2, 1, 1, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 5, 0, 0, 0)) -class SequenceEncoderTestCase(unittest.TestCase): +class SequenceEncoderTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) self.s = univ.Sequence() self.s.setComponentByPosition(0, univ.Null('')) self.s.setComponentByPosition(1, univ.OctetString('quick brown')) @@ -422,8 +432,9 @@ class SequenceEncoderTestCase(unittest.TestCase): ) == ints2octs((48, 128, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1, 0, 0)) -class SequenceEncoderWithSchemaTestCase(unittest.TestCase): +class SequenceEncoderWithSchemaTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('place-holder', univ.Null('')), @@ -475,8 +486,9 @@ class SequenceEncoderWithSchemaTestCase(unittest.TestCase): ) == ints2octs((48, 128, 5, 0, 4, 11, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 2, 1, 1, 0, 0)) -class NestedOptionalSequenceEncoderTestCase(unittest.TestCase): +class NestedOptionalSequenceEncoderTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) inner = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.OptionalNamedType('first-name', univ.OctetString()), @@ -564,8 +576,9 @@ class NestedOptionalSequenceEncoderTestCase(unittest.TestCase): assert encoder.encode(s) == ints2octs((48, 128, 48, 128, 2, 1, 123, 0, 0, 0, 0)) -class NestedOptionalChoiceEncoderTestCase(unittest.TestCase): +class NestedOptionalChoiceEncoderTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) layer3 = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.OptionalNamedType('first-name', univ.OctetString()), @@ -625,8 +638,9 @@ class NestedOptionalChoiceEncoderTestCase(unittest.TestCase): assert encoder.encode(s) == ints2octs((48, 128, 0, 0)) -class NestedOptionalSequenceOfEncoderTestCase(unittest.TestCase): +class NestedOptionalSequenceOfEncoderTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) layer2 = univ.SequenceOf( componentType=univ.OctetString() ) diff --git a/tests/codec/der/test_decoder.py b/tests/codec/der/test_decoder.py index 3fd55c3..6f292fd 100644 --- a/tests/codec/der/test_decoder.py +++ b/tests/codec/der/test_decoder.py @@ -5,17 +5,20 @@ # License: http://pyasn1.sf.net/license.html # import sys + try: import unittest2 as unittest except ImportError: import unittest +from tests.base import BaseTestCase + from pyasn1.codec.der import decoder from pyasn1.compat.octets import ints2octs, null from pyasn1.error import PyAsn1Error -class BitStringDecoderTestCase(unittest.TestCase): +class BitStringDecoderTestCase(BaseTestCase): def testShortMode(self): assert decoder.decode( ints2octs((3, 127, 6) + (170,) * 125 + (128,)) @@ -42,7 +45,7 @@ class BitStringDecoderTestCase(unittest.TestCase): assert 0, 'chunked encoding tolerated' -class OctetStringDecoderTestCase(unittest.TestCase): +class OctetStringDecoderTestCase(BaseTestCase): def testShortMode(self): assert decoder.decode( '\004\017Quick brown fox'.encode() diff --git a/tests/codec/der/test_encoder.py b/tests/codec/der/test_encoder.py index 354781a..3059c0c 100644 --- a/tests/codec/der/test_encoder.py +++ b/tests/codec/der/test_encoder.py @@ -5,18 +5,20 @@ # License: http://pyasn1.sf.net/license.html # import sys + try: import unittest2 as unittest except ImportError: import unittest +from tests.base import BaseTestCase + from pyasn1.type import namedtype, univ from pyasn1.codec.der import encoder from pyasn1.compat.octets import ints2octs -from pyasn1.error import PyAsn1Error -class OctetStringEncoderTestCase(unittest.TestCase): +class OctetStringEncoderTestCase(BaseTestCase): def testDefModeShort(self): assert encoder.encode( univ.OctetString('Quick brown fox') @@ -28,7 +30,7 @@ class OctetStringEncoderTestCase(unittest.TestCase): ) == ints2octs((4, 130, 39, 16) + (81,) * 10000) -class BitStringEncoderTestCase(unittest.TestCase): +class BitStringEncoderTestCase(BaseTestCase): def testDefModeShort(self): assert encoder.encode( univ.BitString((1,)) @@ -40,8 +42,10 @@ class BitStringEncoderTestCase(unittest.TestCase): ) == ints2octs((3, 130, 39, 17, 0) + (255,) * 10000) -class SetOfEncoderTestCase(unittest.TestCase): +class SetOfEncoderTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) + self.s = univ.SetOf(componentType=univ.OctetString()) def testDefMode1(self): @@ -72,12 +76,15 @@ class SetOfEncoderTestCase(unittest.TestCase): assert encoder.encode(self.s) == ints2octs((49, 6, 4, 1, 97, 4, 1, 98)) -class SetWithChoiceEncoderTestCase(unittest.TestCase): +class SetWithChoiceEncoderTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) + c = univ.Choice(componentType=namedtype.NamedTypes( namedtype.NamedType('name', univ.OctetString()), namedtype.NamedType('amount', univ.Boolean())) ) + self.s = univ.Set(componentType=namedtype.NamedTypes( namedtype.NamedType('value', univ.Integer(5)), namedtype.NamedType('status', c)) @@ -94,8 +101,10 @@ class SetWithChoiceEncoderTestCase(unittest.TestCase): assert encoder.encode(self.s) == ints2octs((49, 6, 1, 1, 255, 2, 1, 5)) -class NestedOptionalSequenceEncoderTestCase(unittest.TestCase): +class NestedOptionalSequenceEncoderTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) + inner = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.OptionalNamedType('first-name', univ.OctetString()), @@ -183,8 +192,10 @@ class NestedOptionalSequenceEncoderTestCase(unittest.TestCase): assert encoder.encode(s) == ints2octs((48, 5, 48, 3, 2, 1, 123)) -class NestedOptionalChoiceEncoderTestCase(unittest.TestCase): +class NestedOptionalChoiceEncoderTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) + layer3 = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.OptionalNamedType('first-name', univ.OctetString()), @@ -244,8 +255,10 @@ class NestedOptionalChoiceEncoderTestCase(unittest.TestCase): assert encoder.encode(s) == ints2octs((48, 0)) -class NestedOptionalSequenceOfEncoderTestCase(unittest.TestCase): +class NestedOptionalSequenceOfEncoderTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) + layer2 = univ.SequenceOf( componentType=univ.OctetString() ) diff --git a/tests/codec/native/test_decoder.py b/tests/codec/native/test_decoder.py index 16fddfc..c3854af 100644 --- a/tests/codec/native/test_decoder.py +++ b/tests/codec/native/test_decoder.py @@ -5,17 +5,20 @@ # License: http://pyasn1.sf.net/license.html # import sys + try: import unittest2 as unittest except ImportError: import unittest -from pyasn1.type import tag, namedtype, univ, char +from tests.base import BaseTestCase + +from pyasn1.type import namedtype, univ from pyasn1.codec.native import decoder from pyasn1.error import PyAsn1Error -class BadAsn1SpecTestCase(unittest.TestCase): +class BadAsn1SpecTestCase(BaseTestCase): def testBadSpec(self): try: decoder.decode('', asn1Spec='not an Asn1Item') @@ -25,7 +28,7 @@ class BadAsn1SpecTestCase(unittest.TestCase): assert 0, 'Invalid asn1Spec accepted' -class IntegerDecoderTestCase(unittest.TestCase): +class IntegerDecoderTestCase(BaseTestCase): def testPosInt(self): assert decoder.decode(12, asn1Spec=univ.Integer()) == univ.Integer(12) @@ -33,7 +36,7 @@ class IntegerDecoderTestCase(unittest.TestCase): assert decoder.decode(-12, asn1Spec=univ.Integer()) == univ.Integer(-12) -class BooleanDecoderTestCase(unittest.TestCase): +class BooleanDecoderTestCase(BaseTestCase): def testTrue(self): assert decoder.decode(True, asn1Spec=univ.Boolean()) == univ.Boolean(True) @@ -41,33 +44,35 @@ class BooleanDecoderTestCase(unittest.TestCase): assert decoder.decode(False, asn1Spec=univ.Boolean()) == univ.Boolean(False) -class BitStringDecoderTestCase(unittest.TestCase): +class BitStringDecoderTestCase(BaseTestCase): def testSimple(self): assert decoder.decode('11111111', asn1Spec=univ.BitString()) == univ.BitString(hexValue='ff') -class OctetStringDecoderTestCase(unittest.TestCase): +class OctetStringDecoderTestCase(BaseTestCase): def testSimple(self): assert decoder.decode('Quick brown fox', asn1Spec=univ.OctetString()) == univ.OctetString('Quick brown fox') -class NullDecoderTestCase(unittest.TestCase): +class NullDecoderTestCase(BaseTestCase): def testNull(self): assert decoder.decode(None, asn1Spec=univ.Null()) == univ.Null() -class ObjectIdentifierDecoderTestCase(unittest.TestCase): +class ObjectIdentifierDecoderTestCase(BaseTestCase): def testOne(self): assert decoder.decode('1.3.6.11', asn1Spec=univ.ObjectIdentifier()) == univ.ObjectIdentifier('1.3.6.11') -class RealDecoderTestCase(unittest.TestCase): +class RealDecoderTestCase(BaseTestCase): def testSimple(self): assert decoder.decode(1.33, asn1Spec=univ.Real()) == univ.Real(1.33) -class SequenceDecoderTestCase(unittest.TestCase): +class SequenceDecoderTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) + self.s = univ.Sequence( componentType=namedtype.NamedTypes( namedtype.NamedType('place-holder', univ.Null()), @@ -84,8 +89,10 @@ class SequenceDecoderTestCase(unittest.TestCase): assert decoder.decode({'place-holder': None, 'first-name': 'xx', 'age': 33}, asn1Spec=self.s) == s -class ChoiceDecoderTestCase(unittest.TestCase): +class ChoiceDecoderTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) + self.s = univ.Choice( componentType=namedtype.NamedTypes( namedtype.NamedType('place-holder', univ.Null()), @@ -100,8 +107,10 @@ class ChoiceDecoderTestCase(unittest.TestCase): assert decoder.decode({'first-name': 'xx'}, asn1Spec=self.s) == s -class AnyDecoderTestCase(unittest.TestCase): +class AnyDecoderTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) + self.s = univ.Any() def testSimple(self): diff --git a/tests/codec/native/test_encoder.py b/tests/codec/native/test_encoder.py index a1d9efc..cfa5b89 100644 --- a/tests/codec/native/test_encoder.py +++ b/tests/codec/native/test_encoder.py @@ -5,28 +5,33 @@ # License: http://pyasn1.sf.net/license.html # import sys + try: import unittest2 as unittest except ImportError: import unittest -from pyasn1.type import tag, namedtype, univ +from tests.base import BaseTestCase + +from pyasn1.type import namedtype, univ from pyasn1.codec.native import encoder from pyasn1.compat.octets import str2octs from pyasn1.error import PyAsn1Error -class BadAsn1SpecTestCase(unittest.TestCase): +class BadAsn1SpecTestCase(BaseTestCase): def testBadValueType(self): try: encoder.encode('not an Asn1Item') + except PyAsn1Error: pass + else: assert 0, 'Invalid value type accepted' -class IntegerEncoderTestCase(unittest.TestCase): +class IntegerEncoderTestCase(BaseTestCase): def testPosInt(self): assert encoder.encode(univ.Integer(12)) == 12 @@ -34,7 +39,7 @@ class IntegerEncoderTestCase(unittest.TestCase): assert encoder.encode(univ.Integer(-12)) == -12 -class BooleanEncoderTestCase(unittest.TestCase): +class BooleanEncoderTestCase(BaseTestCase): def testTrue(self): assert encoder.encode(univ.Boolean(1)) is True @@ -42,33 +47,35 @@ class BooleanEncoderTestCase(unittest.TestCase): assert encoder.encode(univ.Boolean(0)) is False -class BitStringEncoderTestCase(unittest.TestCase): +class BitStringEncoderTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) self.b = univ.BitString((1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1)) def testValue(self): assert encoder.encode(self.b) == '101010011000101' -class OctetStringEncoderTestCase(unittest.TestCase): +class OctetStringEncoderTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) self.o = univ.OctetString('Quick brown fox') def testValue(self): assert encoder.encode(self.o) == str2octs('Quick brown fox') -class NullEncoderTestCase(unittest.TestCase): +class NullEncoderTestCase(BaseTestCase): def testNull(self): assert encoder.encode(univ.Null('')) is None -class ObjectIdentifierEncoderTestCase(unittest.TestCase): +class ObjectIdentifierEncoderTestCase(BaseTestCase): def testOne(self): assert encoder.encode(univ.ObjectIdentifier((1, 3, 6, 0, 12345))) == '1.3.6.0.12345' -class RealEncoderTestCase(unittest.TestCase): +class RealEncoderTestCase(BaseTestCase): def testChar(self): assert encoder.encode(univ.Real((123, 10, 11))) == 1.23e+13 @@ -79,8 +86,10 @@ class RealEncoderTestCase(unittest.TestCase): assert encoder.encode(univ.Real('-inf')) == float('-inf') -class SequenceEncoderTestCase(unittest.TestCase): +class SequenceEncoderTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) + self.s = univ.Sequence(componentType=namedtype.NamedTypes( namedtype.NamedType('place-holder', univ.Null('')), namedtype.OptionalNamedType('first-name', univ.OctetString('')), @@ -95,13 +104,17 @@ class SequenceEncoderTestCase(unittest.TestCase): assert encoder.encode(s) == {'place-holder': None, 'first-name': str2octs('abc'), 'age': 123} -class ChoiceEncoderTestCase(unittest.TestCase): +class ChoiceEncoderTestCase(BaseTestCase): def setUp(self): - self.s = univ.Choice(componentType=namedtype.NamedTypes( - namedtype.NamedType('place-holder', univ.Null('')), - namedtype.NamedType('number', univ.Integer(0)), - namedtype.NamedType('string', univ.OctetString()) - )) + BaseTestCase.setUp(self) + + self.s = univ.Choice( + componentType=namedtype.NamedTypes( + namedtype.NamedType('place-holder', univ.Null('')), + namedtype.NamedType('number', univ.Integer(0)), + namedtype.NamedType('string', univ.OctetString()) + ) + ) def testEmpty(self): try: @@ -116,8 +129,9 @@ class ChoiceEncoderTestCase(unittest.TestCase): assert encoder.encode(self.s) == {'place-holder': None} -class AnyEncoderTestCase(unittest.TestCase): +class AnyEncoderTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) self.s = univ.Any(encoder.encode(univ.OctetString('fox'))) def testSimple(self): diff --git a/tests/compat/test_binary.py b/tests/compat/test_binary.py index 7660206..ce3d1ef 100644 --- a/tests/compat/test_binary.py +++ b/tests/compat/test_binary.py @@ -5,15 +5,18 @@ # License: http://pyasn1.sf.net/license.html # import sys -from pyasn1.compat import binary try: import unittest2 as unittest except ImportError: import unittest +from tests.base import BaseTestCase + +from pyasn1.compat import binary + -class BinaryTestCase(unittest.TestCase): +class BinaryTestCase(BaseTestCase): def test_bin_zero(self): assert '0b0' == binary.bin(0) diff --git a/tests/compat/test_integer.py b/tests/compat/test_integer.py index 9179641..22aadd9 100644 --- a/tests/compat/test_integer.py +++ b/tests/compat/test_integer.py @@ -5,15 +5,18 @@ # License: http://pyasn1.sf.net/license.html # import sys -from pyasn1.compat import integer try: import unittest2 as unittest except ImportError: import unittest +from tests.base import BaseTestCase + +from pyasn1.compat import integer + -class IntegerTestCase(unittest.TestCase): +class IntegerTestCase(BaseTestCase): if sys.version_info[0] > 2: diff --git a/tests/compat/test_octets.py b/tests/compat/test_octets.py index 4652b33..82382f7 100644 --- a/tests/compat/test_octets.py +++ b/tests/compat/test_octets.py @@ -5,15 +5,18 @@ # License: http://pyasn1.sf.net/license.html # import sys -from pyasn1.compat import octets try: import unittest2 as unittest except ImportError: import unittest +from tests.base import BaseTestCase + +from pyasn1.compat import octets + -class OctetsTestCase(unittest.TestCase): +class OctetsTestCase(BaseTestCase): if sys.version_info[0] > 2: diff --git a/tests/test_debug.py b/tests/test_debug.py index 742f7f1..e4616bb 100644 --- a/tests/test_debug.py +++ b/tests/test_debug.py @@ -5,16 +5,21 @@ # License: http://pyasn1.sf.net/license.html # import sys + try: import unittest2 as unittest + except ImportError: import unittest +from tests.base import BaseTestCase + from pyasn1 import debug from pyasn1 import error -class DebugCaseBase(unittest.TestCase): +class DebugCaseBase(BaseTestCase): def testKnownFlags(self): + debug.setLogger(0) debug.setLogger(debug.Debug('all', 'encoder', 'decoder')) debug.setLogger(0) diff --git a/tests/type/test_char.py b/tests/type/test_char.py index dcdbbd2..74550c0 100644 --- a/tests/type/test_char.py +++ b/tests/type/test_char.py @@ -5,23 +5,28 @@ # License: http://pyasn1.sf.net/license.html # import sys -from pyasn1.type import char, univ, constraint -from pyasn1.compat.octets import ints2octs -from pyasn1.error import PyAsn1Error try: import unittest2 as unittest except ImportError: import unittest +from tests.base import BaseTestCase + +from pyasn1.type import char, univ, constraint +from pyasn1.compat.octets import ints2octs +from pyasn1.error import PyAsn1Error -class AbstractStringTestCase: + +class AbstractStringTestCase(object): initializer = () encoding = 'us-ascii' asn1Type = None def setUp(self): + BaseTestCase.setUp(self) + self.asn1String = self.asn1Type(ints2octs(self.initializer), encoding=self.encoding) self.pythonString = ints2octs(self.initializer).decode(self.encoding) @@ -107,28 +112,28 @@ class AbstractStringTestCase: assert list(reversed(self.asn1String)) == list(reversed(self.pythonString)) -class VisibleStringTestCase(AbstractStringTestCase, unittest.TestCase): +class VisibleStringTestCase(AbstractStringTestCase, BaseTestCase): initializer = (97, 102) encoding = 'us-ascii' asn1Type = char.VisibleString -class GeneralStringTestCase(AbstractStringTestCase, unittest.TestCase): +class GeneralStringTestCase(AbstractStringTestCase, BaseTestCase): initializer = (169, 174) encoding = 'iso-8859-1' asn1Type = char.GeneralString -class UTF8StringTestCase(AbstractStringTestCase, unittest.TestCase): +class UTF8StringTestCase(AbstractStringTestCase, BaseTestCase): initializer = (209, 132, 208, 176) encoding = 'utf-8' asn1Type = char.UTF8String -class BMPStringTestCase(AbstractStringTestCase, unittest.TestCase): +class BMPStringTestCase(AbstractStringTestCase, BaseTestCase): initializer = (4, 48, 4, 68) encoding = 'utf-16-be' @@ -139,7 +144,7 @@ if sys.version_info[0] > 2: # Somehow comparison of UTF-32 encoded strings does not work in Py2 - class UniversalStringTestCase(AbstractStringTestCase, unittest.TestCase): + class UniversalStringTestCase(AbstractStringTestCase, BaseTestCase): initializer = (0, 0, 4, 48, 0, 0, 4, 68) encoding = 'utf-32-be' asn1Type = char.UniversalString diff --git a/tests/type/test_constraint.py b/tests/type/test_constraint.py index 0ea4ed4..1dbffb1 100644 --- a/tests/type/test_constraint.py +++ b/tests/type/test_constraint.py @@ -5,17 +5,21 @@ # License: http://pyasn1.sf.net/license.html # import sys + try: import unittest2 as unittest except ImportError: import unittest +from tests.base import BaseTestCase + from pyasn1.type import constraint, error -class SingleValueConstraintTestCase(unittest.TestCase): +class SingleValueConstraintTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) self.c1 = constraint.SingleValueConstraint(1, 2) self.c2 = constraint.SingleValueConstraint(3, 4) @@ -28,6 +32,7 @@ class SingleValueConstraintTestCase(unittest.TestCase): def testGoodVal(self): try: self.c1(1) + except error.ValueConstraintError: assert 0, 'constraint check fails' @@ -40,8 +45,9 @@ class SingleValueConstraintTestCase(unittest.TestCase): assert 0, 'constraint check fails' -class ContainedSubtypeConstraintTestCase(unittest.TestCase): +class ContainedSubtypeConstraintTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) self.c1 = constraint.ContainedSubtypeConstraint( constraint.SingleValueConstraint(12) ) @@ -61,8 +67,9 @@ class ContainedSubtypeConstraintTestCase(unittest.TestCase): assert 0, 'constraint check fails' -class ValueRangeConstraintTestCase(unittest.TestCase): +class ValueRangeConstraintTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) self.c1 = constraint.ValueRangeConstraint(1, 4) def testGoodVal(self): @@ -80,8 +87,9 @@ class ValueRangeConstraintTestCase(unittest.TestCase): assert 0, 'constraint check fails' -class ValueSizeConstraintTestCase(unittest.TestCase): +class ValueSizeConstraintTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) self.c1 = constraint.ValueSizeConstraint(1, 2) def testGoodVal(self): @@ -119,8 +127,9 @@ class PermittedAlphabetConstraintTestCase(SingleValueConstraintTestCase): assert 0, 'constraint check fails' -class ConstraintsIntersectionTestCase(unittest.TestCase): +class ConstraintsIntersectionTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) self.c1 = constraint.ConstraintsIntersection( constraint.SingleValueConstraint(4), constraint.ValueRangeConstraint(2, 4) @@ -161,7 +170,7 @@ class ConstraintsIntersectionTestCase(unittest.TestCase): assert 0, 'constraint check fails' -class InnerTypeConstraintTestCase(unittest.TestCase): +class InnerTypeConstraintTestCase(BaseTestCase): def testConst1(self): c = constraint.InnerTypeConstraint( constraint.SingleValueConstraint(4) @@ -203,8 +212,9 @@ class InnerTypeConstraintTestCase(unittest.TestCase): # Constraints compositions -class ConstraintsIntersectionRangeTestCase(unittest.TestCase): +class ConstraintsIntersectionRangeTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) self.c1 = constraint.ConstraintsIntersection( constraint.ValueRangeConstraint(1, 9), constraint.ValueRangeConstraint(2, 5) @@ -225,8 +235,9 @@ class ConstraintsIntersectionRangeTestCase(unittest.TestCase): assert 0, 'constraint check fails' -class ConstraintsUnionTestCase(unittest.TestCase): +class ConstraintsUnionTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) self.c1 = constraint.ConstraintsUnion( constraint.SingleValueConstraint(5), constraint.ValueRangeConstraint(1, 3) @@ -248,8 +259,9 @@ class ConstraintsUnionTestCase(unittest.TestCase): assert 0, 'constraint check fails' -class ConstraintsExclusionTestCase(unittest.TestCase): +class ConstraintsExclusionTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) self.c1 = constraint.ConstraintsExclusion( constraint.ValueRangeConstraint(2, 4) ) @@ -271,9 +283,12 @@ class ConstraintsExclusionTestCase(unittest.TestCase): # Constraints derivations -class DirectDerivationTestCase(unittest.TestCase): +class DirectDerivationTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) + self.c1 = constraint.SingleValueConstraint(5) + self.c2 = constraint.ConstraintsUnion( self.c1, constraint.ValueRangeConstraint(1, 3) ) @@ -287,14 +302,18 @@ class DirectDerivationTestCase(unittest.TestCase): assert self.c2.isSubTypeOf(self.c1), 'isSubTypeOf failed' -class IndirectDerivationTestCase(unittest.TestCase): +class IndirectDerivationTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) + self.c1 = constraint.ConstraintsIntersection( constraint.ValueRangeConstraint(1, 30) ) + self.c2 = constraint.ConstraintsIntersection( self.c1, constraint.ValueRangeConstraint(1, 20) ) + self.c2 = constraint.ConstraintsIntersection( self.c2, constraint.ValueRangeConstraint(1, 10) ) @@ -307,7 +326,7 @@ class IndirectDerivationTestCase(unittest.TestCase): assert not self.c2.isSuperTypeOf(self.c1), 'isSuperTypeOf failed' assert self.c2.isSubTypeOf(self.c1), 'isSubTypeOf failed' -# TODO: how to apply size constriants to constructed types? +# TODO: how to apply size constraints to constructed types? suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) diff --git a/tests/type/test_namedtype.py b/tests/type/test_namedtype.py index 4991876..65f9d65 100644 --- a/tests/type/test_namedtype.py +++ b/tests/type/test_namedtype.py @@ -5,17 +5,22 @@ # License: http://pyasn1.sf.net/license.html # import sys + try: import unittest2 as unittest + except ImportError: import unittest +from tests.base import BaseTestCase + from pyasn1.type import namedtype, univ from pyasn1.error import PyAsn1Error -class NamedTypeCaseBase(unittest.TestCase): +class NamedTypeCaseBase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) self.e = namedtype.NamedType('age', univ.Integer(0)) def testIter(self): @@ -26,8 +31,10 @@ class NamedTypeCaseBase(unittest.TestCase): assert eval(repr(self.e), {'NamedType': namedtype.NamedType, 'Integer': univ.Integer}) == self.e, 'repr() fails' -class NamedTypesCaseBase(unittest.TestCase): +class NamedTypesCaseBase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) + self.e = namedtype.NamedTypes( namedtype.NamedType('first-name', univ.OctetString('')), namedtype.OptionalNamedType('age', univ.Integer(0)), @@ -35,9 +42,15 @@ class NamedTypesCaseBase(unittest.TestCase): ) def testRepr(self): - assert eval(repr(self.e), {'NamedTypes': namedtype.NamedTypes, 'NamedType': namedtype.NamedType, - 'OptionalNamedType': namedtype.OptionalNamedType, 'Integer': univ.Integer, - 'OctetString': univ.OctetString}) == self.e, 'repr() fails' + assert eval( + repr(self.e), { + 'NamedTypes': namedtype.NamedTypes, + 'NamedType': namedtype.NamedType, + 'OptionalNamedType': namedtype.OptionalNamedType, + 'Integer': univ.Integer, + 'OctetString': univ.OctetString + } + ) == self.e, 'repr() fails' def testContains(self): assert 'first-name' in self.e @@ -104,8 +117,10 @@ class NamedTypesCaseBase(unittest.TestCase): assert self.e.getPositionNearType(univ.OctetString.tagSet, 2) == 2 -class OrderedNamedTypesCaseBase(unittest.TestCase): +class OrderedNamedTypesCaseBase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) + self.e = namedtype.NamedTypes( namedtype.NamedType('first-name', univ.OctetString('')), namedtype.NamedType('age', univ.Integer(0)) @@ -116,7 +131,7 @@ class OrderedNamedTypesCaseBase(unittest.TestCase): 'getTypeByPosition() fails' -class DuplicateNamedTypesCaseBase(unittest.TestCase): +class DuplicateNamedTypesCaseBase(BaseTestCase): def testDuplicateDefaultTags(self): nt = namedtype.NamedTypes( namedtype.NamedType('first-name', univ.Any()), diff --git a/tests/type/test_namedval.py b/tests/type/test_namedval.py index 6504b34..215a3a1 100644 --- a/tests/type/test_namedval.py +++ b/tests/type/test_namedval.py @@ -5,17 +5,21 @@ # License: http://pyasn1.sf.net/license.html # import sys + try: import unittest2 as unittest except ImportError: import unittest +from tests.base import BaseTestCase + from pyasn1.type import namedval -class NamedValuesCaseBase(unittest.TestCase): +class NamedValuesCaseBase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) self.e = namedval.NamedValues(('off', 0), ('on', 1)) def testDict(self): diff --git a/tests/type/test_tag.py b/tests/type/test_tag.py index fac9783..57121e8 100644 --- a/tests/type/test_tag.py +++ b/tests/type/test_tag.py @@ -5,17 +5,21 @@ # License: http://pyasn1.sf.net/license.html # import sys + try: import unittest2 as unittest except ImportError: import unittest +from tests.base import BaseTestCase + from pyasn1.type import tag -class TagTestCaseBase(unittest.TestCase): +class TagTestCaseBase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) self.t1 = tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 3) self.t2 = tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 3) @@ -38,11 +42,14 @@ class TagCmpTestCase(TagTestCaseBase): self.t1[2] == self.t2[2], 'tag sequence protocol fails' -class TagSetTestCaseBase(unittest.TestCase): +class TagSetTestCaseBase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) + self.ts1 = tag.initTagSet( tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 12) ) + self.ts2 = tag.initTagSet( tag.Tag(tag.tagClassUniversal, tag.tagFormatSimple, 12) ) diff --git a/tests/type/test_univ.py b/tests/type/test_univ.py index c9da0b2..23f269e 100644 --- a/tests/type/test_univ.py +++ b/tests/type/test_univ.py @@ -6,17 +6,21 @@ # import sys import math -from pyasn1.type import univ, tag, constraint, namedtype, namedval, error -from pyasn1.compat.octets import str2octs, ints2octs, octs2ints -from pyasn1.error import PyAsn1Error try: import unittest2 as unittest + except ImportError: import unittest +from tests.base import BaseTestCase -class NoValueTestCase(unittest.TestCase): +from pyasn1.type import univ, tag, constraint, namedtype, namedval, error +from pyasn1.compat.octets import str2octs, ints2octs, octs2ints +from pyasn1.error import PyAsn1Error + + +class NoValueTestCase(BaseTestCase): def testSingleton(self): assert univ.NoValue() is univ.NoValue(), 'NoValue is not a singleton' @@ -144,7 +148,7 @@ class NoValueTestCase(unittest.TestCase): assert False, 'sizeof failed for NoValue object' -class IntegerTestCase(unittest.TestCase): +class IntegerTestCase(BaseTestCase): def testStr(self): assert str(univ.Integer(1)) in ('1', '1L'), 'str() fails' @@ -292,7 +296,7 @@ class IntegerTestCase(unittest.TestCase): ) -class BooleanTestCase(unittest.TestCase): +class BooleanTestCase(BaseTestCase): def testTruth(self): assert univ.Boolean(True) and univ.Boolean(1), 'Truth initializer fails' @@ -324,8 +328,10 @@ class BooleanTestCase(unittest.TestCase): assert 0, 'constraint fail' -class BitStringTestCase(unittest.TestCase): +class BitStringTestCase(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) + self.b = univ.BitString( namedValues=namedval.NamedValues(('Active', 0), ('Urgent', 1)) ) @@ -465,17 +471,17 @@ class OctetStringWithUnicodeMixIn(object): assert list(reversed(univ.OctetString(self.encodedPythonString))) == list(reversed(self.encodedPythonString)) -class OctetStringWithAsciiTestCase(OctetStringWithUnicodeMixIn, unittest.TestCase): +class OctetStringWithAsciiTestCase(OctetStringWithUnicodeMixIn, BaseTestCase): initializer = (97, 102) encoding = 'us-ascii' -class OctetStringWithUtf8TestCase(OctetStringWithUnicodeMixIn, unittest.TestCase): +class OctetStringWithUtf8TestCase(OctetStringWithUnicodeMixIn, BaseTestCase): initializer = (208, 176, 208, 177, 208, 178) encoding = 'utf-8' -class OctetStringWithUtf16TestCase(OctetStringWithUnicodeMixIn, unittest.TestCase): +class OctetStringWithUtf16TestCase(OctetStringWithUnicodeMixIn, BaseTestCase): initializer = (4, 48, 4, 49, 4, 50) encoding = 'utf-16-be' @@ -484,12 +490,12 @@ if sys.version_info[0] > 2: # Somehow comparison of UTF-32 encoded strings does not work in Py2 - class OctetStringWithUtf32TestCase(OctetStringWithUnicodeMixIn, unittest.TestCase): + class OctetStringWithUtf32TestCase(OctetStringWithUnicodeMixIn, BaseTestCase): initializer = (0, 0, 4, 48, 0, 0, 4, 49, 0, 0, 4, 50) encoding = 'utf-32-be' -class OctetStringTestCase(unittest.TestCase): +class OctetStringTestCase(BaseTestCase): def testBinDefault(self): @@ -539,7 +545,7 @@ class OctetStringTestCase(unittest.TestCase): assert OctetString(hexValue="FA9823C43E43510DE3422") == ints2octs((250, 152, 35, 196, 62, 67, 81, 13, 227, 66, 32)) -class Null(unittest.TestCase): +class Null(BaseTestCase): def testStr(self): assert str(univ.Null('')) == '', 'str() fails' @@ -568,7 +574,7 @@ class Null(unittest.TestCase): assert not Null() -class RealTestCase(unittest.TestCase): +class RealTestCase(BaseTestCase): def testFloat4BinEnc(self): assert univ.Real((0.25, 2, 3)) == 2.0, 'float initializer for binary encoding fails' @@ -701,7 +707,7 @@ class RealTestCase(unittest.TestCase): assert Real(1.0) == 1.0 -class ObjectIdentifier(unittest.TestCase): +class ObjectIdentifier(BaseTestCase): def testStr(self): assert str(univ.ObjectIdentifier((1, 3, 6))) == '1.3.6', 'str() fails' @@ -761,8 +767,9 @@ class ObjectIdentifier(unittest.TestCase): assert str(ObjectIdentifier((1, 3, 6))) == '1.3.6' -class SequenceOf(unittest.TestCase): +class SequenceOf(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) self.s1 = univ.SequenceOf( componentType=univ.OctetString('') ) @@ -954,20 +961,28 @@ class SequenceOf(unittest.TestCase): assert n == o -class Sequence(unittest.TestCase): +class Sequence(BaseTestCase): def setUp(self): - self.s1 = univ.Sequence(componentType=namedtype.NamedTypes( - namedtype.NamedType('name', univ.OctetString('')), - namedtype.OptionalNamedType('nick', univ.OctetString('')), - namedtype.DefaultedNamedType('age', univ.Integer(34)) - )) + BaseTestCase.setUp(self) + self.s1 = univ.Sequence( + componentType=namedtype.NamedTypes( + namedtype.NamedType('name', univ.OctetString('')), + namedtype.OptionalNamedType('nick', univ.OctetString('')), + namedtype.DefaultedNamedType('age', univ.Integer(34)) + ) + ) def testRepr(self): - assert eval(repr(self.s1.clone().setComponents('a', 'b')), - {'Sequence': univ.Sequence, 'OctetString': univ.OctetString, 'Integer': univ.Integer, - 'NamedTypes': namedtype.NamedTypes, 'NamedType': namedtype.NamedType, - 'OptionalNamedType': namedtype.OptionalNamedType, - 'DefaultedNamedType': namedtype.DefaultedNamedType}) == self.s1.clone().setComponents('a', 'b'), 'repr() fails' + assert eval( + repr(self.s1.clone().setComponents('a', 'b')), + {'Sequence': univ.Sequence, + 'OctetString': univ.OctetString, + 'Integer': univ.Integer, + 'NamedTypes': namedtype.NamedTypes, + 'NamedType': namedtype.NamedType, + 'OptionalNamedType': namedtype.OptionalNamedType, + 'DefaultedNamedType': namedtype.DefaultedNamedType} + ) == self.s1.clone().setComponents('a', 'b'), 'repr() fails' def testTag(self): assert self.s1.tagSet == tag.TagSet( @@ -1101,7 +1116,7 @@ class Sequence(unittest.TestCase): assert s['name'] == str2octs('abc') -class SequenceWithoutSchema(unittest.TestCase): +class SequenceWithoutSchema(BaseTestCase): def testIter(self): s = univ.Sequence() @@ -1151,8 +1166,9 @@ class SequenceWithoutSchema(unittest.TestCase): assert 'field-0' not in s -class SetOf(unittest.TestCase): +class SetOf(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) self.s1 = univ.SetOf(componentType=univ.OctetString('')) def testTag(self): @@ -1178,13 +1194,17 @@ class SetOf(unittest.TestCase): assert s == [str2octs('abc')] -class Set(unittest.TestCase): +class Set(BaseTestCase): def setUp(self): - self.s1 = univ.Set(componentType=namedtype.NamedTypes( - namedtype.NamedType('name', univ.OctetString('')), - namedtype.OptionalNamedType('null', univ.Null('')), - namedtype.DefaultedNamedType('age', univ.Integer(34)) - )) + BaseTestCase.setUp(self) + + self.s1 = univ.Set( + componentType=namedtype.NamedTypes( + namedtype.NamedType('name', univ.OctetString('')), + namedtype.OptionalNamedType('null', univ.Null('')), + namedtype.DefaultedNamedType('age', univ.Integer(34)) + ) + ) self.s2 = self.s1.clone() def testTag(self): @@ -1241,8 +1261,10 @@ class Set(unittest.TestCase): assert s['name'] == str2octs('abc') -class Choice(unittest.TestCase): +class Choice(BaseTestCase): def setUp(self): + BaseTestCase.setUp(self) + innerComp = univ.Choice( componentType=namedtype.NamedTypes( namedtype.NamedType('count', univ.Integer()), diff --git a/tests/type/test_useful.py b/tests/type/test_useful.py index dbd6fe0..717eede 100644 --- a/tests/type/test_useful.py +++ b/tests/type/test_useful.py @@ -6,14 +6,16 @@ # import sys import datetime -from pyasn1.type import useful -from pyasn1.error import PyAsn1Error try: import unittest2 as unittest + except ImportError: import unittest +from tests.base import BaseTestCase + +from pyasn1.type import useful class FixedOffset(datetime.tzinfo): def __init__(self, offset, name): @@ -34,11 +36,11 @@ UTC = FixedOffset(0, 'UTC') UTC2 = FixedOffset(120, 'UTC') -class ObjectDescriptorTestCase(unittest.TestCase): +class ObjectDescriptorTestCase(BaseTestCase): pass -class GeneralizedTimeTestCase(unittest.TestCase): +class GeneralizedTimeTestCase(BaseTestCase): def testFromDateTime(self): assert useful.GeneralizedTime.fromDateTime(datetime.datetime(2017, 7, 11, 0, 1, 2, 30000, tzinfo=UTC)) == '20170711000102.3Z' @@ -71,7 +73,7 @@ class GeneralizedTimeTestCase(unittest.TestCase): assert datetime.datetime(2017, 7, 11, 0) == useful.GeneralizedTime('2017071100').asDateTime -class UTCTimeTestCase(unittest.TestCase): +class UTCTimeTestCase(BaseTestCase): def testFromDateTime(self): assert useful.UTCTime.fromDateTime(datetime.datetime(2017, 7, 11, 0, 1, 2, tzinfo=UTC)) == '170711000102Z' -- cgit v1.2.1 From 5356afca8d7b7a1f991297af02cb44a17fbe8924 Mon Sep 17 00:00:00 2001 From: Ilya Etingof Date: Sat, 16 Sep 2017 09:59:45 +0200 Subject: 0.3.5 release --- CHANGES.rst | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 644f2fe..a1d9799 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,12 +1,13 @@ -Revision 0.3.5, released XX-09-2017 +Revision 0.3.5, released 16-09-2017 ----------------------------------- -- Codecs signatures unified and pass **options through the call chain +- Codecs signatures unified and pass the options kwargs through the + call chain - Explicit tag encoding optimized to avoid unnecessary copying - End-of-octets sentinel encoding optimized -- Refactored ASN.1 codecs properties to silently enforce proper length and - chunk size encoding modes +- Refactored ASN.1 codecs properties to silently enforce proper + length and chunk size encoding modes - Fixed DER encoder to always produce primitive encoding - Fixed crash at SequenceOf native decoder - Fixed Real.prettyPrint() to fail gracefully on overflow -- cgit v1.2.1 From 3182ecf81839ae4072a46706c3d0426a03f80be8 Mon Sep 17 00:00:00 2001 From: Ilya Etingof Date: Sun, 17 Sep 2017 00:16:53 +0200 Subject: wrong inheritance in test fixed --- tests/codec/ber/test_encoder.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/codec/ber/test_encoder.py b/tests/codec/ber/test_encoder.py index 153ebd7..265e866 100644 --- a/tests/codec/ber/test_encoder.py +++ b/tests/codec/ber/test_encoder.py @@ -20,7 +20,7 @@ from pyasn1.compat.octets import ints2octs from pyasn1.error import PyAsn1Error -class LargeTagEncoderTestCase(unittest.TestCase): +class LargeTagEncoderTestCase(BaseTestCase): def setUp(self): BaseTestCase.setUp(self) -- cgit v1.2.1