1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
|
import regex as re
import six
from six.moves import StringIO
from flanker.addresslib._parser.lexer import t_ATOM, t_FWSP
_RE_ATOM_PHRASE = re.compile(
r'(({atom}|\.)+({fwsp}({atom}|\.)+)*)?'.format(atom=t_ATOM, fwsp=t_FWSP),
re.MULTILINE | re.VERBOSE)
def smart_quote(s):
"""
Quotes the input string but only if it contains at least one word that is
not an rfc2822 atom. That is probably a little bit excessive but we better
be safe then sorry.
"""
if _contains_atoms_only(s):
return s
return '"' + s.replace('\\', '\\\\').replace('"', '\\"') + '"'
def smart_unquote(s):
"""
Returns a string that is created from the input string by unquoting all
quoted regions in there. If there are no quoted regions in the input string
then output string is identical to the input string.
"""
unquoted = StringIO()
escaped_char = False
is_quoted_section = False
for c in s:
if is_quoted_section:
if escaped_char:
escaped_char = False
else:
if c == '"':
is_quoted_section = False
continue
elif c == '\\':
escaped_char = True
continue
else:
if c == '"':
is_quoted_section = True
continue
unquoted.write(c)
return unquoted.getvalue()
def _contains_atoms_only(s):
if six.PY2 and isinstance(s, six.text_type):
s = s.encode('utf-8')
match_result = _RE_ATOM_PHRASE.match(s)
return match_result and match_result.end(0) == len(s)
|