inspect: perform thorough namespace resolution in namesdict (#51591)
This commit is contained in:
parent
c6a9bfb535
commit
20c6163de8
|
@ -4397,6 +4397,12 @@ def test_inspect_page(pub, local_user):
|
|||
upload.receive([b'hello world'])
|
||||
formdata.data['4'] = upload
|
||||
formdata.user_id = local_user.id
|
||||
formdata.workflow_data = {
|
||||
'foo': {
|
||||
'bar_coin': 'yy',
|
||||
},
|
||||
'foo_bar': 'xx',
|
||||
}
|
||||
formdata.store()
|
||||
|
||||
from wcs.admin.settings import UserFieldsFormDef
|
||||
|
|
|
@ -196,33 +196,41 @@ class CompatibilityNamesDict(dict):
|
|||
|
||||
return flat_keys.keys()
|
||||
|
||||
def __getitem__(self, key):
|
||||
try:
|
||||
val = super(CompatibilityNamesDict, self).__getitem__(key)
|
||||
except KeyError:
|
||||
# fallback to deconstructing namespaces around underscores
|
||||
parts = key.split('_')
|
||||
current_dict = self
|
||||
while parts:
|
||||
for i in range(len(parts), 0, -1):
|
||||
part = '_'.join(parts[:i])
|
||||
try:
|
||||
if current_dict is self:
|
||||
current_dict = dict.__getitem__(current_dict, part)
|
||||
elif hasattr(current_dict, '__getitem__'):
|
||||
current_dict = current_dict[part]
|
||||
else:
|
||||
current_dict = getattr(current_dict, part)
|
||||
except (AttributeError, KeyError, TypeError):
|
||||
# TypeError will happen if indexing is used on a string
|
||||
if i == 1:
|
||||
raise KeyError(key)
|
||||
else:
|
||||
parts = parts[i:]
|
||||
break
|
||||
return current_dict
|
||||
def get_path(self, base, path):
|
||||
def resolve(path):
|
||||
key = '_'.join(path)
|
||||
try:
|
||||
if base is self:
|
||||
return dict.__getitem__(base, key)
|
||||
elif hasattr(base, '__getitem__'):
|
||||
return base[key]
|
||||
else:
|
||||
return getattr(base, key)
|
||||
except (AttributeError, KeyError, TypeError) as e:
|
||||
# TypeError will happen if indexing is used on a string
|
||||
raise KeyError(key) from e
|
||||
|
||||
return val
|
||||
# longer item's names have precedence over short ones, i.e. if
|
||||
# d = {'foo': {'bar': 1}, 'foo_bar': 2}
|
||||
# then get_path(d, 'foor_bar') will return 2 and never 1.
|
||||
for i in range(len(path), 0, -1):
|
||||
try:
|
||||
value = resolve(path[:i])
|
||||
rest = path[i:]
|
||||
if rest:
|
||||
return self.get_path(value, rest)
|
||||
else:
|
||||
return value
|
||||
except KeyError:
|
||||
pass
|
||||
raise KeyError
|
||||
|
||||
def __getitem__(self, key):
|
||||
parts = key.split('_')
|
||||
try:
|
||||
return self.get_path(self, parts)
|
||||
except KeyError as e:
|
||||
raise KeyError(key) from e
|
||||
|
||||
def __contains__(self, key):
|
||||
try:
|
||||
|
|
Loading…
Reference in New Issue