Created
July 20, 2024 09:24
-
-
Save dsoprea/f0a5007b250c5005abbb6efa6d045c2a to your computer and use it in GitHub Desktop.
Tools to convert between dictionaries and strings with proper escaping
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
_ENCODED_ESCAPE_TRANSLATION = str.maketrans({ | |
'\\': r'\\', | |
',': r'\,', | |
'=': r'\=', | |
}) | |
def dictionary_to_string(d): | |
components = [ | |
'{}={}'.format( | |
str(key).translate(_ENCODED_ESCAPE_TRANSLATION), | |
str(value).translate(_ENCODED_ESCAPE_TRANSLATION)) | |
for key, value | |
in d.items() | |
] | |
encoded = ','.join(components) | |
return encoded | |
def _split_by_unescaped_character(s, separator): | |
last = 0 | |
for i, c in enumerate(s): | |
if c != separator: | |
continue | |
elif i > 0 and s[i - 1] == '\\': | |
continue | |
value = s[last:i] | |
yield value | |
last = i + 1 | |
value = s[last:] | |
yield value | |
def _unescape(s): | |
# Process the string in reverse, because we'll need to 'lookahead' in order | |
# to skip the preceding slashes | |
chars = [] | |
len_ = len(s) | |
i = 0 | |
r = list(reversed(s)) | |
while i < len_: | |
c = r[i] | |
chars.append(c) | |
i += 1 | |
# If it was escaped, remove the slash and step another position | |
if i < len_ and r[i] == '\\': | |
i += 1 | |
return ''.join(reversed(chars)) | |
def string_to_dictionary(s): | |
components = _split_by_unescaped_character(s, ',') | |
components = list(components) | |
d = {} | |
for component in components: | |
couplet = _split_by_unescaped_character(component, '=') | |
couplet = list(couplet) | |
assert \ | |
len(couplet) == 2, \ | |
"Name-value couplet does not have two parts: {}".format(couplet) | |
escaped_key, escaped_value = couplet | |
key = _unescape(escaped_key) | |
value = _unescape(escaped_value) | |
d[key] = value | |
return d |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment