diff options
author | Ilya Etingof <etingof@gmail.com> | 2019-06-29 08:50:35 +0200 |
---|---|---|
committer | Ilya Etingof <etingof@gmail.com> | 2019-06-29 09:24:35 +0200 |
commit | 4a9abf7ae867e9ebabc850320d87a7c1230acfad (patch) | |
tree | 98e32bd72e9a5054703a2c32a711a724d28c75b3 | |
parent | fe2725f8c80039d9d82af2bd3299abc174417c27 (diff) | |
download | pyasn1-4a9abf7ae867e9ebabc850320d87a7c1230acfad.tar.gz |
Rename pyasn1 unicode exceptions
The new exception classes names are `PyAsn1UnicodeDecodeError`
and `PyAsn1UnicodeEncodeError`.
Also, unit tests added.
-rw-r--r-- | CHANGES.rst | 3 | ||||
-rw-r--r-- | pyasn1/error.py | 40 | ||||
-rw-r--r-- | pyasn1/type/char.py | 32 | ||||
-rw-r--r-- | pyasn1/type/univ.py | 27 | ||||
-rw-r--r-- | tests/type/test_univ.py | 29 |
5 files changed, 89 insertions, 42 deletions
diff --git a/CHANGES.rst b/CHANGES.rst index 1bcd5f6..e979039 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -26,6 +26,9 @@ Revision 0.4.6, released XX-06-2019 becomes a value object. - Added `.reset()` method to all constructed types to turn value object into a schema object. +- Added `PyAsn1UnicodeDecodeError`/`PyAsn1UnicodeDecodeError` exceptions + to help the caller treating unicode errors happening internally + to pyasn1 at the upper layers. - Fixed `AnyDecoder` to accept possible `TagMap` as `asn1Spec` to make dumping raw value operational diff --git a/pyasn1/error.py b/pyasn1/error.py index fb23f1d..cb30033 100644 --- a/pyasn1/error.py +++ b/pyasn1/error.py @@ -13,45 +13,47 @@ class PyAsn1Error(Exception): """ -class PyAsn1StringError(PyAsn1Error, UnicodeError): +class ValueConstraintError(PyAsn1Error): """Create pyasn1 exception object - The `PyAsn1StringError` exception is a base class for errors relating to - string encoding/decoding and other related problems + The `ValueConstraintError` exception indicates an ASN.1 value + constraint violation. """ - def __init__(self, message, unicode_error=None): - if isinstance(unicode_error, UnicodeError): - UnicodeError.__init__(self, *unicode_error.args) - PyAsn1Error.__init__(self, message) -class PyAsn1StringDecodeError(PyAsn1StringError, UnicodeDecodeError): +class SubstrateUnderrunError(PyAsn1Error): """Create pyasn1 exception object - The `PyAsn1StringDecodeError` exception represents a failure to decode - underlying bytes values to a string + The `SubstrateUnderrunError` exception indicates insufficient serialised + data on input of a de-serialization routine. """ -class PyAsn1StringEncodeError(PyAsn1StringError, UnicodeEncodeError): +class PyAsn1UnicodeError(PyAsn1Error, UnicodeError): """Create pyasn1 exception object - The `PyAsn1StringEncodeError` exception represents a failure to encode - underlying string value as bytes + The `PyAsn1UnicodeError` exception is a base class for errors relating to + unicode text de/serialization. """ + def __init__(self, message, unicode_error=None): + if isinstance(unicode_error, UnicodeError): + UnicodeError.__init__(self, *unicode_error.args) + PyAsn1Error.__init__(self, message) -class ValueConstraintError(PyAsn1Error): +class PyAsn1UnicodeDecodeError(PyAsn1UnicodeError, UnicodeDecodeError): """Create pyasn1 exception object - The `ValueConstraintError` exception indicates an ASN.1 value - constraint violation. + The `PyAsn1UnicodeDecodeError` exception represents a failure to + deserialize unicode text. """ -class SubstrateUnderrunError(PyAsn1Error): +class PyAsn1UnicodeEncodeError(PyAsn1UnicodeError, UnicodeEncodeError): """Create pyasn1 exception object - The `SubstrateUnderrunError` exception indicates insufficient serialised - data on input of a de-serialization routine. + The `PyAsn1UnicodeEncodeError` exception represents a failure to + serialize unicode text. """ + + diff --git a/pyasn1/type/char.py b/pyasn1/type/char.py index 03121a0..1b5daed 100644 --- a/pyasn1/type/char.py +++ b/pyasn1/type/char.py @@ -54,9 +54,11 @@ class AbstractCharacterString(univ.OctetString): # `str` is Py2 text representation return self._value.encode(self.encoding) - except UnicodeEncodeError as e: - raise error.PyAsn1StringEncodeError( - "Can't encode string '%s' with codec %s" % (self._value, self.encoding), e + except UnicodeEncodeError: + exc = sys.exc_info()[1] + raise error.PyAsn1UnicodeEncodeError( + "Can't encode string '%s' with codec " + "%s" % (self._value, self.encoding), exc ) def __unicode__(self): @@ -75,9 +77,11 @@ class AbstractCharacterString(univ.OctetString): else: return unicode(value) - except (UnicodeDecodeError, LookupError) as e: - raise error.PyAsn1StringDecodeError( - "Can't decode string '%s' with codec %s" % (value, self.encoding), e + except (UnicodeDecodeError, LookupError) as exc: + exc = sys.exc_info()[1] + raise error.PyAsn1UnicodeDecodeError( + "Can't decode string '%s' with codec " + "%s" % (value, self.encoding), exc ) def asOctets(self, padding=True): @@ -94,9 +98,11 @@ class AbstractCharacterString(univ.OctetString): def __bytes__(self): try: return self._value.encode(self.encoding) - except UnicodeEncodeError as e: - raise error.PyAsn1StringEncodeError( - "Can't encode string '%s' with codec %s" % (self._value, self.encoding), e + except UnicodeEncodeError: + exc = sys.exc_info()[1] + raise error.PyAsn1UnicodeEncodeError( + "Can't encode string '%s' with codec " + "%s" % (self._value, self.encoding), exc ) def prettyIn(self, value): @@ -112,9 +118,11 @@ class AbstractCharacterString(univ.OctetString): else: return str(value) - except (UnicodeDecodeError, LookupError) as e: - raise error.PyAsn1StringDecodeError( - "Can't decode string '%s' with codec %s" % (value, self.encoding), e + except (UnicodeDecodeError, LookupError): + exc = sys.exc_info()[1] + raise error.PyAsn1UnicodeDecodeError( + "Can't decode string '%s' with codec " + "%s" % (value, self.encoding), exc ) def asOctets(self, padding=True): diff --git a/pyasn1/type/univ.py b/pyasn1/type/univ.py index 7d88957..96623e7 100644 --- a/pyasn1/type/univ.py +++ b/pyasn1/type/univ.py @@ -825,9 +825,11 @@ class OctetString(base.AbstractSimpleAsn1Item): elif isinstance(value, unicode): try: return value.encode(self.encoding) - except (LookupError, UnicodeEncodeError) as e: - raise error.PyAsn1StringEncodeError( - "Can't encode string '%s' with codec %s" % (value, self.encoding), e + except (LookupError, UnicodeEncodeError): + exc = sys.exc_info()[1] + raise error.PyAsn1UnicodeEncodeError( + "Can't encode string '%s' with codec " + "%s" % (value, self.encoding), exc ) elif isinstance(value, (tuple, list)): try: @@ -846,9 +848,11 @@ class OctetString(base.AbstractSimpleAsn1Item): try: return self._value.decode(self.encoding) - except UnicodeDecodeError as e: - raise error.PyAsn1StringDecodeError( - "Can't decode string '%s' with codec %s" % (self._value, self.encoding), e + except UnicodeDecodeError: + exc = sys.exc_info()[1] + raise error.PyAsn1UnicodeDecodeError( + "Can't decode string '%s' with codec " + "%s" % (self._value, self.encoding), exc ) def asOctets(self): @@ -865,7 +869,7 @@ class OctetString(base.AbstractSimpleAsn1Item): try: return value.encode(self.encoding) except UnicodeEncodeError as e: - raise error.PyAsn1StringEncodeError( + raise error.PyAsn1UnicodeEncodeError( "Can't encode string '%s' with '%s' codec" % (value, self.encoding), e ) elif isinstance(value, OctetString): # a shortcut, bytes() would work the same way @@ -881,9 +885,12 @@ class OctetString(base.AbstractSimpleAsn1Item): try: return self._value.decode(self.encoding) - except UnicodeDecodeError as e: - raise error.PyAsn1StringDecodeError( - "Can't decode string '%s' with '%s' codec at '%s'" % (self._value, self.encoding, self.__class__.__name__), e + except UnicodeDecodeError: + exc = sys.exc_info()[1] + raise error.PyAsn1UnicodeDecodeError( + "Can't decode string '%s' with '%s' codec at " + "'%s'" % (self._value, self.encoding, + self.__class__.__name__), exc ) def __bytes__(self): diff --git a/tests/type/test_univ.py b/tests/type/test_univ.py index 3cd125b..169b73e 100644 --- a/tests/type/test_univ.py +++ b/tests/type/test_univ.py @@ -22,8 +22,9 @@ from pyasn1.type import constraint from pyasn1.type import namedtype from pyasn1.type import namedval from pyasn1.type import error -from pyasn1.compat.octets import str2octs, ints2octs, octs2ints +from pyasn1.compat.octets import str2octs, ints2octs, octs2ints, octs2str from pyasn1.error import PyAsn1Error +from pyasn1.error import PyAsn1UnicodeEncodeError, PyAsn1UnicodeDecodeError class NoValueTestCase(BaseTestCase): @@ -543,6 +544,32 @@ class OctetStringWithAsciiTestCase(OctetStringWithUnicodeMixIn, BaseTestCase): encoding = 'us-ascii' +class OctetStringUnicodeErrorTestCase(BaseTestCase): + def testEncodeError(self): + text = octs2str(ints2octs((0xff, 0xfe))) + + try: + univ.OctetString(text, encoding='us-ascii') + + except PyAsn1UnicodeEncodeError: + pass + + else: + assert False, 'Unicode encoding error not caught' + + def testDecodeError(self): + serialized = ints2octs((0xff, 0xfe)) + + try: + str(univ.OctetString(serialized, encoding='us-ascii')) + + except PyAsn1UnicodeDecodeError: + pass + + else: + assert False, 'Unicode decoding error not caught' + + class OctetStringWithUtf8TestCase(OctetStringWithUnicodeMixIn, BaseTestCase): initializer = (208, 176, 208, 177, 208, 178) encoding = 'utf-8' |