Sync with oslo-incubator

Head of oslo-incubator is commit id:
2fd457bf2ccbeb2b84ffb204778b6417cd5405ba

includes a fix for gettextutil.Message handling of deep copy
failures and adding a license header

Change-Id: Ie89de1f95bb6fb9d11058413e682c441c39524f1
This commit is contained in:
Davanum Srinivas
2014-04-02 21:30:22 -04:00
parent 59c1103655
commit ff0c87eeca
2 changed files with 24 additions and 35 deletions

View File

@@ -1,2 +1,17 @@
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import six import six
six.add_move(six.MovedModule('mox', 'mox', 'mox3.mox')) six.add_move(six.MovedModule('mox', 'mox', 'mox3.mox'))

View File

@@ -28,7 +28,6 @@ import gettext
import locale import locale
from logging import handlers from logging import handlers
import os import os
import re
from babel import localedata from babel import localedata
import six import six
@@ -248,47 +247,22 @@ class Message(six.text_type):
if other is None: if other is None:
params = (other,) params = (other,)
elif isinstance(other, dict): elif isinstance(other, dict):
params = self._trim_dictionary_parameters(other) # Merge the dictionaries
# Copy each item in case one does not support deep copy.
params = {}
if isinstance(self.params, dict):
for key, val in self.params.items():
params[key] = self._copy_param(val)
for key, val in other.items():
params[key] = self._copy_param(val)
else: else:
params = self._copy_param(other) params = self._copy_param(other)
return params return params
def _trim_dictionary_parameters(self, dict_param):
"""Return a dict that only has matching entries in the msgid."""
# NOTE(luisg): Here we trim down the dictionary passed as parameters
# to avoid carrying a lot of unnecessary weight around in the message
# object, for example if someone passes in Message() % locals() but
# only some params are used, and additionally we prevent errors for
# non-deepcopyable objects by unicoding() them.
# Look for %(param) keys in msgid;
# Skip %% and deal with the case where % is first character on the line
keys = re.findall('(?:[^%]|^)?%\((\w*)\)[a-z]', self.msgid)
# If we don't find any %(param) keys but have a %s
if not keys and re.findall('(?:[^%]|^)%[a-z]', self.msgid):
# Apparently the full dictionary is the parameter
params = self._copy_param(dict_param)
else:
params = {}
# Save our existing parameters as defaults to protect
# ourselves from losing values if we are called through an
# (erroneous) chain that builds a valid Message with
# arguments, and then does something like "msg % kwds"
# where kwds is an empty dictionary.
src = {}
if isinstance(self.params, dict):
src.update(self.params)
src.update(dict_param)
for key in keys:
params[key] = self._copy_param(src[key])
return params
def _copy_param(self, param): def _copy_param(self, param):
try: try:
return copy.deepcopy(param) return copy.deepcopy(param)
except TypeError: except Exception:
# Fallback to casting to unicode this will handle the # Fallback to casting to unicode this will handle the
# python code-like objects that can't be deep-copied # python code-like objects that can't be deep-copied
return six.text_type(param) return six.text_type(param)