From fe2725f8c80039d9d82af2bd3299abc174417c27 Mon Sep 17 00:00:00 2001 From: Alex Shafer Date: Sat, 29 Jun 2019 00:20:15 -0600 Subject: Add specific exceptions for String issues (#155) This change helps telling unicode-related exceptions from other PyAsn1Error exceptions. --- pyasn1/error.py | 28 ++++++++++++++++++++++++++++ pyasn1/type/char.py | 24 ++++++++++++------------ pyasn1/type/univ.py | 24 ++++++++++++------------ 3 files changed, 52 insertions(+), 24 deletions(-) diff --git a/pyasn1/error.py b/pyasn1/error.py index 7f606bb..fb23f1d 100644 --- a/pyasn1/error.py +++ b/pyasn1/error.py @@ -13,6 +13,34 @@ class PyAsn1Error(Exception): """ +class PyAsn1StringError(PyAsn1Error, UnicodeError): + """Create pyasn1 exception object + + The `PyAsn1StringError` exception is a base class for errors relating to + string encoding/decoding and other related problems + """ + 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): + """Create pyasn1 exception object + + The `PyAsn1StringDecodeError` exception represents a failure to decode + underlying bytes values to a string + """ + + +class PyAsn1StringEncodeError(PyAsn1StringError, UnicodeEncodeError): + """Create pyasn1 exception object + + The `PyAsn1StringEncodeError` exception represents a failure to encode + underlying string value as bytes + """ + + class ValueConstraintError(PyAsn1Error): """Create pyasn1 exception object diff --git a/pyasn1/type/char.py b/pyasn1/type/char.py index 617b98d..03121a0 100644 --- a/pyasn1/type/char.py +++ b/pyasn1/type/char.py @@ -54,9 +54,9 @@ class AbstractCharacterString(univ.OctetString): # `str` is Py2 text representation return self._value.encode(self.encoding) - except UnicodeEncodeError: - raise error.PyAsn1Error( - "Can't encode string '%s' with codec %s" % (self._value, self.encoding) + except UnicodeEncodeError as e: + raise error.PyAsn1StringEncodeError( + "Can't encode string '%s' with codec %s" % (self._value, self.encoding), e ) def __unicode__(self): @@ -75,9 +75,9 @@ class AbstractCharacterString(univ.OctetString): else: return unicode(value) - except (UnicodeDecodeError, LookupError): - raise error.PyAsn1Error( - "Can't decode string '%s' with codec %s" % (value, self.encoding) + except (UnicodeDecodeError, LookupError) as e: + raise error.PyAsn1StringDecodeError( + "Can't decode string '%s' with codec %s" % (value, self.encoding), e ) def asOctets(self, padding=True): @@ -94,9 +94,9 @@ class AbstractCharacterString(univ.OctetString): def __bytes__(self): try: return self._value.encode(self.encoding) - except UnicodeEncodeError: - raise error.PyAsn1Error( - "Can't encode string '%s' with codec %s" % (self._value, self.encoding) + except UnicodeEncodeError as e: + raise error.PyAsn1StringEncodeError( + "Can't encode string '%s' with codec %s" % (self._value, self.encoding), e ) def prettyIn(self, value): @@ -112,9 +112,9 @@ class AbstractCharacterString(univ.OctetString): else: return str(value) - except (UnicodeDecodeError, LookupError): - raise error.PyAsn1Error( - "Can't decode string '%s' with codec %s" % (value, self.encoding) + except (UnicodeDecodeError, LookupError) as e: + raise error.PyAsn1StringDecodeError( + "Can't decode string '%s' with codec %s" % (value, self.encoding), e ) def asOctets(self, padding=True): diff --git a/pyasn1/type/univ.py b/pyasn1/type/univ.py index 4c8c8e4..7d88957 100644 --- a/pyasn1/type/univ.py +++ b/pyasn1/type/univ.py @@ -825,9 +825,9 @@ class OctetString(base.AbstractSimpleAsn1Item): elif isinstance(value, unicode): try: return value.encode(self.encoding) - except (LookupError, UnicodeEncodeError): - raise error.PyAsn1Error( - "Can't encode string '%s' with codec %s" % (value, self.encoding) + except (LookupError, UnicodeEncodeError) as e: + raise error.PyAsn1StringEncodeError( + "Can't encode string '%s' with codec %s" % (value, self.encoding), e ) elif isinstance(value, (tuple, list)): try: @@ -846,9 +846,9 @@ class OctetString(base.AbstractSimpleAsn1Item): try: return self._value.decode(self.encoding) - except UnicodeDecodeError: - raise error.PyAsn1Error( - "Can't decode string '%s' with codec %s" % (self._value, self.encoding) + except UnicodeDecodeError as e: + raise error.PyAsn1StringDecodeError( + "Can't decode string '%s' with codec %s" % (self._value, self.encoding), e ) def asOctets(self): @@ -864,9 +864,9 @@ class OctetString(base.AbstractSimpleAsn1Item): elif isinstance(value, str): try: return value.encode(self.encoding) - except UnicodeEncodeError: - raise error.PyAsn1Error( - "Can't encode string '%s' with '%s' codec" % (value, self.encoding) + except UnicodeEncodeError as e: + raise error.PyAsn1StringEncodeError( + "Can't encode string '%s' with '%s' codec" % (value, self.encoding), e ) elif isinstance(value, OctetString): # a shortcut, bytes() would work the same way return value.asOctets() @@ -881,9 +881,9 @@ class OctetString(base.AbstractSimpleAsn1Item): try: return self._value.decode(self.encoding) - except UnicodeDecodeError: - raise error.PyAsn1Error( - "Can't decode string '%s' with '%s' codec at '%s'" % (self._value, self.encoding, self.__class__.__name__) + 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 ) def __bytes__(self): -- cgit v1.2.3