Merge "Adds a custom deepcopy handler"

This commit is contained in:
Jenkins 2016-08-03 03:15:24 +00:00 committed by Gerrit Code Review
commit 9e749efcf4
2 changed files with 30 additions and 27 deletions

View File

@ -182,6 +182,35 @@ class SecurityError(Error):
amendment = _('(Disable insecure_debug mode to suppress these details.)')
def __deepcopy__(self):
"""Override the default deepcopy.
Keystone :class:`keystone.exception.Error` accepts an optional message
that will be used when rendering the exception object as a string. If
not provided the object's message_format attribute is used instead.
:class:`keystone.exception.SecurityError` is a little different in
that it only uses the message provided to the initializer when
keystone is in `insecure_debug` mode. Instead it will use its
`message_format`. This is to ensure that sensitive details are not
leaked back to the caller in a production deployment.
This dual mode for string rendering causes some odd behaviour when
combined with oslo_i18n translation. Any object used as a value for
formatting a translated string is deep copied.
The copy causes an issue. The deep copy process actually creates a new
exception instance with the rendered string. Then when that new
instance is rendered as a string to use for substitution a warning is
logged. This is because the code tries to use the `message_format` in
secure mode, but the required kwargs are not in the deep copy.
The end result is not an error because when the KeyError is caught the
instance's ``message`` is used instead and this has the properly
translated message. The only indication that something is wonky is a
message in the warning log.
"""
return self
def _build_message(self, message, **kwargs):
"""Only returns detailed messages in insecure_debug mode."""
if message and CONF.insecure_debug:

View File

@ -25,7 +25,6 @@ import keystone.conf
from keystone import exception
from keystone.i18n import _LE
from keystone.tests import unit
from keystone.tests.unit import utils
CONF = keystone.conf.CONF
@ -281,31 +280,7 @@ class SecurityErrorTestCase(ExceptionTestCase):
class TestSecurityErrorTranslation(unit.BaseTestCase):
"""Test i18n for SecurityError exceptions.
Keystone ``Error`` accepts an optional message that will be used when
rendering the exception object as a string. If not provided the object's
message_format attribute is used instead. ``SecurityError``s are a little
different in that they only use the message provided to the initializer
when keystone is in insecure_debug mode. Instead they will use the message
format. This is to ensure that sensitive details are not leaked back to
the caller in a production deployment.
This dual mode for string rendering causes some odd behaviour when
combined with oslo_i18n translation. Any object used as a value for
formatting a translated string is deep copied.
The copy causes an issue. The deep copy process actually creates a new
exception instance with the rendered string. Then when that new instance
is rendered as a string to use for substitution a warning is logged. This
is because the code tries to use the ``message_format`` in secure mode,
but the required kwargs are not in the deep copy.
The end result is not an error because when the KeyError is cause the
instance's ``message`` is used instead and this has the properly
translated message. The only indication that something is wonky is a
message in the warning log.
"""
"""Test i18n for SecurityError exceptions."""
def setUp(self):
super(TestSecurityErrorTranslation, self).setUp()
@ -323,7 +298,6 @@ class TestSecurityErrorTranslation(unit.BaseTestCase):
class CustomError(exception.Error):
message_format = _LE('We had a failure in the %(place)r')
@utils.wip('this will fail until we fix the deepcopy issue')
def test_nested_translation_of_SecurityErrors(self):
e = self.CustomSecurityError(place='code')
_LE('Admiral found this in the log: %s') % e