summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIlya Etingof <etingof@gmail.com>2019-06-29 08:50:35 +0200
committerIlya Etingof <etingof@gmail.com>2019-06-29 09:24:35 +0200
commit4a9abf7ae867e9ebabc850320d87a7c1230acfad (patch)
tree98e32bd72e9a5054703a2c32a711a724d28c75b3
parentfe2725f8c80039d9d82af2bd3299abc174417c27 (diff)
downloadpyasn1-git-4a9abf7ae867e9ebabc850320d87a7c1230acfad.tar.gz
Rename pyasn1 unicode exceptions
The new exception classes names are `PyAsn1UnicodeDecodeError` and `PyAsn1UnicodeEncodeError`. Also, unit tests added.
-rw-r--r--CHANGES.rst3
-rw-r--r--pyasn1/error.py40
-rw-r--r--pyasn1/type/char.py32
-rw-r--r--pyasn1/type/univ.py27
-rw-r--r--tests/type/test_univ.py29
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'