diff options
author | Ilya Etingof <etingof@gmail.com> | 2019-08-19 21:26:51 +0200 |
---|---|---|
committer | Ilya Etingof <etingof@gmail.com> | 2019-08-24 21:37:51 +0200 |
commit | 41597f2e7f1820ab4e1c5b085da1f5e168df24bc (patch) | |
tree | e552f03ee7846566b4b036c192d9ed326a9e74a5 | |
parent | ec580e545ef25f117573014d40ca5c512e58dbf3 (diff) | |
download | pyasn1-git-add-consistency-check-hook.tar.gz |
Add `isInconsistent` property hook to all constructed typesadd-consistency-check-hook
Added `isInconsistent` property to all constructed types. This property
conceptually replaces `verifySizeSpec` method to serve a more general
purpose e.g. ensuring all required fields are in a good shape. By
default this check invokes subtype constraints verification and is run
by codecs on value de/serialisation.
-rw-r--r-- | CHANGES.rst | 6 | ||||
-rw-r--r-- | docs/source/pyasn1/type/base/constructedasn1type.rst | 2 | ||||
-rw-r--r-- | docs/source/pyasn1/type/univ/choice.rst | 2 | ||||
-rw-r--r-- | docs/source/pyasn1/type/univ/sequence.rst | 2 | ||||
-rw-r--r-- | docs/source/pyasn1/type/univ/sequenceof.rst | 2 | ||||
-rw-r--r-- | docs/source/pyasn1/type/univ/set.rst | 2 | ||||
-rw-r--r-- | docs/source/pyasn1/type/univ/setof.rst | 2 | ||||
-rw-r--r-- | pyasn1/codec/ber/decoder.py | 8 | ||||
-rw-r--r-- | pyasn1/codec/ber/encoder.py | 8 | ||||
-rw-r--r-- | pyasn1/codec/cer/encoder.py | 4 | ||||
-rw-r--r-- | pyasn1/codec/native/encoder.py | 8 | ||||
-rw-r--r-- | pyasn1/type/base.py | 23 | ||||
-rw-r--r-- | pyasn1/type/univ.py | 2 | ||||
-rw-r--r-- | tests/type/test_univ.py | 14 |
14 files changed, 57 insertions, 28 deletions
diff --git a/CHANGES.rst b/CHANGES.rst index 0d9c545..0dcb2f2 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -2,7 +2,11 @@ Revision 0.4.7, released XX-09-2019 ----------------------------------- -No changes yet +- Added `isInconsistent` property to all constructed types. This property + conceptually replaces `verifySizeSpec` method to serve a more general + purpose e.g. ensuring all required fields are in a good shape. By default + this check invokes subtype constraints verification and is run by codecs + on value de/serialisation. Revision 0.4.6, released 31-07-2019 ----------------------------------- diff --git a/docs/source/pyasn1/type/base/constructedasn1type.rst b/docs/source/pyasn1/type/base/constructedasn1type.rst index 54d828f..169552f 100644 --- a/docs/source/pyasn1/type/base/constructedasn1type.rst +++ b/docs/source/pyasn1/type/base/constructedasn1type.rst @@ -7,4 +7,4 @@ ------------ .. autoclass:: pyasn1.type.base.ConstructedAsn1Type(tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), sizeSpec=ConstraintsIntersection(), componentType=None) - :members: isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, subtypeSpec + :members: isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, subtypeSpec, isInconsistent diff --git a/docs/source/pyasn1/type/univ/choice.rst b/docs/source/pyasn1/type/univ/choice.rst index 9731971..9e2b4dc 100644 --- a/docs/source/pyasn1/type/univ/choice.rst +++ b/docs/source/pyasn1/type/univ/choice.rst @@ -9,7 +9,7 @@ .. autoclass:: pyasn1.type.univ.Choice(componentType=None, tagSet=tagSet(), subtypeSpec=ConstraintsIntersection(), sizeSpec=ConstraintsIntersection()) :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, componentType, subtypeSpec, sizeSpec, getComponentByPosition, setComponentByPosition, getComponentByName, setComponentByName, setDefaultComponents, - getComponentByType, setComponentByType, getName, getComponent + getComponentByType, setComponentByType, getName, getComponent, isInconsistent .. note:: diff --git a/docs/source/pyasn1/type/univ/sequence.rst b/docs/source/pyasn1/type/univ/sequence.rst index 0988004..94804c7 100644 --- a/docs/source/pyasn1/type/univ/sequence.rst +++ b/docs/source/pyasn1/type/univ/sequence.rst @@ -9,7 +9,7 @@ .. autoclass:: pyasn1.type.univ.Sequence(componentType=NamedTypes(), tagSet=tagSet(), subtypeSpec=ConstraintsIntersection(), sizeSpec=ConstraintsIntersection()) :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, componentType, subtypeSpec, sizeSpec, getComponentByPosition, setComponentByPosition, getComponentByName, setComponentByName, setDefaultComponents, - clear, reset + clear, reset, isInconsistent .. note:: diff --git a/docs/source/pyasn1/type/univ/sequenceof.rst b/docs/source/pyasn1/type/univ/sequenceof.rst index 6a09b92..be5442e 100644 --- a/docs/source/pyasn1/type/univ/sequenceof.rst +++ b/docs/source/pyasn1/type/univ/sequenceof.rst @@ -8,7 +8,7 @@ .. autoclass:: pyasn1.type.univ.SequenceOf(componentType=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), sizeSpec=ConstraintsIntersection()) :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, componentType, subtypeSpec, sizeSpec, - getComponentByPosition, setComponentByPosition, clear, reset + getComponentByPosition, setComponentByPosition, clear, reset, isInconsistent .. note:: diff --git a/docs/source/pyasn1/type/univ/set.rst b/docs/source/pyasn1/type/univ/set.rst index 792d2e9..aad8ee0 100644 --- a/docs/source/pyasn1/type/univ/set.rst +++ b/docs/source/pyasn1/type/univ/set.rst @@ -9,7 +9,7 @@ .. autoclass:: pyasn1.type.univ.Set(componentType=NamedTypes(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), sizeSpec=ConstraintsIntersection()) :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, componentType, subtypeSpec, sizeSpec, getComponentByPosition, setComponentByPosition, getComponentByName, setComponentByName, setDefaultComponents, - getComponentByType, setComponentByType, clear, reset + getComponentByType, setComponentByType, clear, reset, isInconsistent .. note:: diff --git a/docs/source/pyasn1/type/univ/setof.rst b/docs/source/pyasn1/type/univ/setof.rst index 67ef92f..ce519a9 100644 --- a/docs/source/pyasn1/type/univ/setof.rst +++ b/docs/source/pyasn1/type/univ/setof.rst @@ -8,7 +8,7 @@ .. autoclass:: pyasn1.type.univ.SetOf(componentType=NoValue(), tagSet=TagSet(), subtypeSpec=ConstraintsIntersection(), sizeSpec=ConstraintsIntersection()) :members: isValue, isSameTypeWith, isSuperTypeOf, tagSet, effectiveTagSet, tagMap, componentType, subtypeSpec, sizeSpec, - Â getComponentByPosition, setComponentByPosition, clear, reset + Â getComponentByPosition, setComponentByPosition, clear, reset, isInconsistent .. note:: diff --git a/pyasn1/codec/ber/decoder.py b/pyasn1/codec/ber/decoder.py index 3f2d180..5759ab8 100644 --- a/pyasn1/codec/ber/decoder.py +++ b/pyasn1/codec/ber/decoder.py @@ -695,7 +695,9 @@ class UniversalConstructedTypeDecoder(AbstractConstructedDecoder): asn1Object.setComponentByPosition(idx, component) else: - asn1Object.verifySizeSpec() + inconsistency = asn1Object.isInconsistent + if inconsistency: + raise inconsistency else: asn1Object = asn1Spec.clone() @@ -879,7 +881,9 @@ class UniversalConstructedTypeDecoder(AbstractConstructedDecoder): asn1Object.setComponentByPosition(idx, component) else: - asn1Object.verifySizeSpec() + inconsistency = asn1Object.isInconsistent + if inconsistency: + raise inconsistency else: asn1Object = asn1Spec.clone() diff --git a/pyasn1/codec/ber/encoder.py b/pyasn1/codec/ber/encoder.py index a5d5fd3..778aa86 100644 --- a/pyasn1/codec/ber/encoder.py +++ b/pyasn1/codec/ber/encoder.py @@ -537,7 +537,9 @@ class SequenceEncoder(AbstractItemEncoder): if asn1Spec is None: # instance of ASN.1 schema - value.verifySizeSpec() + inconsistency = value.isInconsistent + if inconsistency: + raise inconsistency namedTypes = value.componentType @@ -643,7 +645,9 @@ class SequenceOfEncoder(AbstractItemEncoder): def _encodeComponents(self, value, asn1Spec, encodeFun, **options): if asn1Spec is None: - value.verifySizeSpec() + inconsistency = value.isInconsistent + if inconsistency: + raise inconsistency else: asn1Spec = asn1Spec.componentType diff --git a/pyasn1/codec/cer/encoder.py b/pyasn1/codec/cer/encoder.py index 6a9db97..935b696 100644 --- a/pyasn1/codec/cer/encoder.py +++ b/pyasn1/codec/cer/encoder.py @@ -169,7 +169,9 @@ class SetEncoder(encoder.SequenceEncoder): if asn1Spec is None: # instance of ASN.1 schema - value.verifySizeSpec() + inconsistency = value.isInconsistent + if inconsistency: + raise inconsistency namedTypes = value.componentType diff --git a/pyasn1/codec/native/encoder.py b/pyasn1/codec/native/encoder.py index 4c5908d..4318abd 100644 --- a/pyasn1/codec/native/encoder.py +++ b/pyasn1/codec/native/encoder.py @@ -72,7 +72,9 @@ class SetEncoder(AbstractItemEncoder): protoDict = dict def encode(self, value, encodeFun, **options): - value.verifySizeSpec() + inconsistency = value.isInconsistent + if inconsistency: + raise inconsistency namedTypes = value.componentType substrate = self.protoDict() @@ -90,7 +92,9 @@ class SequenceEncoder(SetEncoder): class SequenceOfEncoder(AbstractItemEncoder): def encode(self, value, encodeFun, **options): - value.verifySizeSpec() + inconsistency = value.isInconsistent + if inconsistency: + raise inconsistency return [encodeFun(x, **options) for x in value] diff --git a/pyasn1/type/base.py b/pyasn1/type/base.py index 21e4041..1fd69f9 100644 --- a/pyasn1/type/base.py +++ b/pyasn1/type/base.py @@ -655,8 +655,23 @@ class ConstructedAsn1Type(Asn1Type): return clone - def verifySizeSpec(self): - self.sizeSpec(self) + @property + def isInconsistent(self): + """Run necessary checks to ensure object consistency. + + Default action is to verify |ASN.1| object against constraints imposed + by `subtypeSpec`. + + Raises + ------ + :py:class:`~pyasn1.error.PyAsn1tError` on any inconsistencies found + """ + try: + self.sizeSpec(self) + + except error.PyAsn1Error: + exc = sys.exc_info()[1] + return exc def getComponentByPosition(self, idx): raise error.PyAsn1Error('Method not implemented') @@ -679,5 +694,9 @@ class ConstructedAsn1Type(Asn1Type): def getComponentType(self): return self.componentType + def verifySizeSpec(self): + self.sizeSpec(self) + + # Backward compatibility AbstractConstructedAsn1Item = ConstructedAsn1Type diff --git a/pyasn1/type/univ.py b/pyasn1/type/univ.py index b39c533..4f305f6 100644 --- a/pyasn1/type/univ.py +++ b/pyasn1/type/univ.py @@ -3004,7 +3004,7 @@ class Choice(Set): if self._currentIdx is not None: yield self.componentType[self._currentIdx].getName(), self[self._currentIdx] - def verifySizeSpec(self): + def checkConsistency(self): if self._currentIdx is None: raise error.PyAsn1Error('Component not chosen') diff --git a/tests/type/test_univ.py b/tests/type/test_univ.py index 0092588..4cbfa01 100644 --- a/tests/type/test_univ.py +++ b/tests/type/test_univ.py @@ -1040,22 +1040,14 @@ class SequenceOf(BaseTestCase): else: pass - def testSizeSpec(self): + def testConsistency(self): s = self.s1.clone(sizeSpec=constraint.ConstraintsUnion( constraint.ValueSizeConstraint(1, 1) )) s.setComponentByPosition(0, univ.OctetString('abc')) - try: - s.verifySizeSpec() - except PyAsn1Error: - assert 0, 'size spec fails' + assert not s.isInconsistent, 'size spec fails' s.setComponentByPosition(1, univ.OctetString('abc')) - try: - s.verifySizeSpec() - except PyAsn1Error: - pass - else: - assert 0, 'size spec fails' + assert s.isInconsistent, 'size spec fails' def testGetComponentTagMap(self): assert self.s1.componentType.tagMap.presentTypes == { |