Can't compare dicts with both single and double quotes in keys
kammala opened this issue · 3 comments
Describe the bug
DeepDiff falls with an exception while comparing dicts with keys containing both single and double quotes.
To Reproduce
import deepdiff
deepdiff.DeepDiff({'''a'"a''': 1}, {'''a'"a''': 2})
Expected behavior
A comparison result is being returned.
OS, DeepDiff version and Python version (please complete the following information):
- DeepDiff Version: 6.7.0
Additional context
The branch to handle both single and double quotes in stringify_element
doesn't define result
variable which is used later in return statement which causes exception (UnboundLocalError: local variable 'result' referenced before assignment
) to be triggered.
I get an error on stringify_element when param is a byte string.
With the following change (in the first 2 lines) it works.
def stringify_element(param, quote_str=None):
if isinstance(param, str):
has_quote = "'" in param
has_double_quote = '"' in param
else:
has_quote = b"'" in param
has_double_quote = b'"' in param
if has_quote and has_double_quote:
new_param = []
for char in param:
if char in {'"', "'"}:
new_param.append('\\')
new_param.append(char)
result = ''.join(new_param)
elif has_quote:
result = f'"{param}"'
elif has_double_quote:
result = f"'{param}'"
else:
result = param if quote_str is None else quote_str.format(param)
return result
I am not so familiar with all the DeepDiff code, thus let me try just suggesting a correction that seems to work assuming one is using 'utf8' encoding in bytes and bytearray
def stringify_element(param, quote_str=None):
if isinstance(param, (bytes, bytearray)): ## handle bytes
param = param.decode('utf8') ## here
has_quote = "'" in param
has_double_quote = '"' in param
if has_quote and has_double_quote:
new_param = []
for char in param:
if char in {'"', "'"}:
new_param.append('\\')
new_param.append(char)
result = ''.join(new_param)
elif has_quote:
result = f'"{param}"'
elif has_double_quote:
result = f"'{param}'"
else:
result = param if quote_str is None else quote_str.format(param)
return result
Test:
B = {'Foo\'\"':42}
A = {b'Foo\'\"':42}
deepdiff.DeepDiff(A, B)
Out[8]:
{'dictionary_item_added': [root[Foo\'\"]],
'dictionary_item_removed': [root[Foo\'\"]]}