diff options
author | Tomer Vromen <tomer.vromen@intel.com> | 2020-02-04 20:34:36 +0200 |
---|---|---|
committer | Tomer Vromen <tomer.vromen@intel.com> | 2020-02-04 20:34:36 +0200 |
commit | f7b14bcaaae689e243bb379713bbd28686ee7e19 (patch) | |
tree | f38534ed868035f2d889b28a2df8dc713a716d66 /tests | |
parent | 55193857195b6a36c70708fadbe01f3ed61c0a88 (diff) | |
download | pygments-git-f7b14bcaaae689e243bb379713bbd28686ee7e19.tar.gz |
Python f-strings: highlight expressions in curly braces
Fixes #1228
Diffstat (limited to 'tests')
-rw-r--r-- | tests/test_python.py | 682 |
1 files changed, 682 insertions, 0 deletions
diff --git a/tests/test_python.py b/tests/test_python.py index b0922adf..23bb6ed1 100644 --- a/tests/test_python.py +++ b/tests/test_python.py @@ -12,6 +12,8 @@ import pytest from pygments.lexers import PythonLexer, Python3Lexer from pygments.token import Token +import re + @pytest.fixture(scope='module') def lexer2(): @@ -158,3 +160,683 @@ def test_walrus_operator(lexer3): (Token.Text, '\n'), ] assert list(lexer3.get_tokens(fragment)) == tokens + + +def test_fstring(lexer3): + """ + Tests that the lexer can parse f-strings + """ + fragments_and_tokens = ( + # examples from PEP-0498 + ( + "f'My name is {name}, my age next year is {age+1}, my anniversary is {anniversary:%A, %B %d, %Y}.'\n", + [ + (Token.Literal.String.Affix, 'f'), + (Token.Literal.String.Single, "'"), + (Token.Literal.String.Single, 'My name is '), + (Token.Literal.String.Interpol, '{'), + (Token.Name, 'name'), + (Token.Literal.String.Interpol, '}'), + (Token.Literal.String.Single, ', my age next year is '), + (Token.Literal.String.Interpol, '{'), + (Token.Name, 'age'), + (Token.Operator, '+'), + (Token.Literal.Number.Integer, '1'), + (Token.Literal.String.Interpol, '}'), + (Token.Literal.String.Single, ', my anniversary is '), + (Token.Literal.String.Interpol, '{'), + (Token.Name, 'anniversary'), + (Token.Literal.String.Interpol, ':'), + (Token.Literal.String.Single, '%A, %B %d, %Y'), + (Token.Literal.String.Interpol, '}'), + (Token.Literal.String.Single, '.'), + (Token.Literal.String.Single, "'"), + (Token.Text, u'\n') + ] + ), ( + "f'He said his name is {name!r}.'\n", + [ + (Token.Literal.String.Affix, 'f'), + (Token.Literal.String.Single, "'"), + (Token.Literal.String.Single, 'He said his name is '), + (Token.Literal.String.Interpol, '{'), + (Token.Name, 'name'), + (Token.Literal.String.Interpol, '!r}'), + (Token.Literal.String.Single, '.'), + (Token.Literal.String.Single, "'"), + (Token.Text, '\n') + ] + + ), ( + "f'input={value:#06x}'\n", + [ + (Token.Literal.String.Affix, 'f'), + (Token.Literal.String.Single, "'"), + (Token.Literal.String.Single, 'input='), + (Token.Literal.String.Interpol, '{'), + (Token.Name, 'value'), + (Token.Literal.String.Interpol, ':'), + (Token.Literal.String.Single, '#06x'), + (Token.Literal.String.Interpol, '}'), + (Token.Literal.String.Single, "'"), + (Token.Text, '\n') + ] + ), ( + """f'{"quoted string"}'\n""", + [ + (Token.Literal.String.Affix, 'f'), + (Token.Literal.String.Single, "'"), + (Token.Literal.String.Interpol, '{'), + (Token.Literal.String.Double, '"'), + (Token.Literal.String.Double, 'quoted string'), + (Token.Literal.String.Double, '"'), + (Token.Literal.String.Interpol, '}'), + (Token.Literal.String.Single, "'"), + (Token.Text, '\n') + ] + ), ( + """f'{f"{inner}"}'\n""", # not in the PEP + [ + (Token.Literal.String.Affix, 'f'), + (Token.Literal.String.Single, "'"), + (Token.Literal.String.Interpol, '{'), + (Token.Literal.String.Affix, 'f'), + (Token.Literal.String.Double, '"'), + (Token.Literal.String.Interpol, '{'), + (Token.Name, 'inner'), + (Token.Literal.String.Interpol, '}'), + (Token.Literal.String.Double, '"'), + (Token.Literal.String.Interpol, '}'), + (Token.Literal.String.Single, "'"), + (Token.Text, '\n') + ] + ), ( + # SyntaxError: f-string expression part cannot include a backslash + "f'{\\'quoted string\\'}'\n", + [ + (Token.Literal.String.Affix, 'f'), + (Token.Literal.String.Single, "'"), + (Token.Literal.String.Interpol, '{'), + (Token.Error, '\\'), + (Token.Literal.String.Single, "'"), + (Token.Literal.String.Single, 'quoted string'), + (Token.Literal.String.Escape, "\\'"), + (Token.Literal.String.Single, '}'), + (Token.Literal.String.Single, "'"), + (Token.Text, '\n') + ] + ), ( + "f'{{ {4*10} }}'\n", + [ + (Token.Literal.String.Affix, 'f'), + (Token.Literal.String.Single, "'"), + (Token.Literal.String.Escape, '{{'), + (Token.Literal.String.Single, ' '), + (Token.Literal.String.Interpol, '{'), + (Token.Literal.Number.Integer, '4'), + (Token.Operator, '*'), + (Token.Literal.Number.Integer, '10'), + (Token.Literal.String.Interpol, '}'), + (Token.Literal.String.Single, ' '), + (Token.Literal.String.Escape, '}}'), + (Token.Literal.String.Single, "'"), + (Token.Text, '\n') + ] + ), ( + "f'{{{4*10}}}'\n", + [ + (Token.Literal.String.Affix, 'f'), + (Token.Literal.String.Single, "'"), + (Token.Literal.String.Escape, '{{'), + (Token.Literal.String.Interpol, '{'), + (Token.Literal.Number.Integer, '4'), + (Token.Operator, '*'), + (Token.Literal.Number.Integer, '10'), + (Token.Literal.String.Interpol, '}'), + (Token.Literal.String.Escape, '}}'), + (Token.Literal.String.Single, "'"), + (Token.Text, '\n') + ] + ), ( + "fr'x={4*10}'\n", + [ + (Token.Literal.String.Affix, 'fr'), + (Token.Literal.String.Single, "'"), + (Token.Literal.String.Single, "x="), + (Token.Literal.String.Interpol, '{'), + (Token.Literal.Number.Integer, '4'), + (Token.Operator, '*'), + (Token.Literal.Number.Integer, '10'), + (Token.Literal.String.Interpol, '}'), + (Token.Literal.String.Single, "'"), + (Token.Text, '\n') + ] + ), ( + """f'abc {a["x"]} def'\n""", + [ + (Token.Literal.String.Affix, 'f'), + (Token.Literal.String.Single, "'"), + (Token.Literal.String.Single, 'abc '), + (Token.Literal.String.Interpol, '{'), + (Token.Name, 'a'), + (Token.Punctuation, '['), + (Token.Literal.String.Double, '"'), + (Token.Literal.String.Double, 'x'), + (Token.Literal.String.Double, '"'), + (Token.Punctuation, ']'), + (Token.Literal.String.Interpol, '}'), + (Token.Literal.String.Single, ' def'), + (Token.Literal.String.Single, "'"), + (Token.Text, '\n') + ] + ), ( + "f'''abc {a['x']} def'''\n", + [ + (Token.Literal.String.Affix, 'f'), + (Token.Literal.String.Single, "'''"), + (Token.Literal.String.Single, 'abc '), + (Token.Literal.String.Interpol, '{'), + (Token.Name, 'a'), + (Token.Punctuation, '['), + (Token.Literal.String.Single, "'"), + (Token.Literal.String.Single, 'x'), + (Token.Literal.String.Single, "'"), + (Token.Punctuation, ']'), + (Token.Literal.String.Interpol, '}'), + (Token.Literal.String.Single, ' def'), + (Token.Literal.String.Single, "'''"), + (Token.Text, '\n') + ] + ), ( + """f'''{x ++1}'''\n""", + [ + (Token.Literal.String.Affix, 'f'), + (Token.Literal.String.Single, "'''"), + (Token.Literal.String.Interpol, '{'), + (Token.Name, 'x'), + (Token.Text, '\n'), + (Token.Operator, '+'), + (Token.Literal.Number.Integer, '1'), + (Token.Literal.String.Interpol, '}'), + (Token.Literal.String.Single, "'''"), + (Token.Text, '\n') + ] + ), ( + """f'''{d[0 +]}'''\n""", + [ + (Token.Literal.String.Affix, 'f'), + (Token.Literal.String.Single, "'''"), + (Token.Literal.String.Interpol, '{'), + (Token.Name, 'd'), + (Token.Punctuation, '['), + (Token.Literal.Number.Integer, '0'), + (Token.Text, '\n'), + (Token.Punctuation, ']'), + (Token.Literal.String.Interpol, '}'), + (Token.Literal.String.Single, "'''"), + (Token.Text, '\n') + ] + ), ( + "f'result: {value:{width}.{precision}}'\n", + [ + (Token.Literal.String.Affix, 'f'), + (Token.Literal.String.Single, "'"), + (Token.Literal.String.Single, 'result: '), + (Token.Literal.String.Interpol, '{'), + (Token.Name, 'value'), + (Token.Literal.String.Interpol, ':'), + (Token.Literal.String.Interpol, '{'), + (Token.Name, 'width'), + (Token.Literal.String.Interpol, '}'), + (Token.Literal.String.Single, '.'), + (Token.Literal.String.Interpol, '{'), + (Token.Name, 'precision'), + (Token.Literal.String.Interpol, '}'), + (Token.Literal.String.Interpol, '}'), + (Token.Literal.String.Single, "'"), + (Token.Text, '\n') + ] + ), ( + "'a' 'b' f'{x}' '{c}' f'str<{y:^4}>' 'd' 'e'\n", + [ + (Token.Literal.String.Single, "'"), + (Token.Literal.String.Single, 'a'), + (Token.Literal.String.Single, "'"), + (Token.Text, ' '), + (Token.Literal.String.Single, "'"), + (Token.Literal.String.Single, 'b'), + (Token.Literal.String.Single, "'"), + (Token.Text, ' '), + (Token.Literal.String.Affix, 'f'), + (Token.Literal.String.Single, "'"), + (Token.Literal.String.Interpol, '{'), + (Token.Name, 'x'), + (Token.Literal.String.Interpol, '}'), + (Token.Literal.String.Single, "'"), + (Token.Text, ' '), + (Token.Literal.String.Single, "'"), + (Token.Literal.String.Interpol, '{c}'), + (Token.Literal.String.Single, "'"), + (Token.Text, ' '), + (Token.Literal.String.Affix, 'f'), + (Token.Literal.String.Single, "'"), + (Token.Literal.String.Single, 'str<'), + (Token.Literal.String.Interpol, '{'), + (Token.Name, 'y'), + (Token.Literal.String.Interpol, ':'), + (Token.Literal.String.Single, '^4'), + (Token.Literal.String.Interpol, '}'), + (Token.Literal.String.Single, '>'), + (Token.Literal.String.Single, "'"), + (Token.Text, ' '), + (Token.Literal.String.Single, "'"), + (Token.Literal.String.Single, 'd'), + (Token.Literal.String.Single, "'"), + (Token.Text, ' '), + (Token.Literal.String.Single, "'"), + (Token.Literal.String.Single, 'e'), + (Token.Literal.String.Single, "'"), + (Token.Text, '\n') + ] + ), ( + "f'{i}:{d[i]}'\n", + [ + (Token.Literal.String.Affix, 'f'), + (Token.Literal.String.Single, "'"), + (Token.Literal.String.Interpol, '{'), + (Token.Name, 'i'), + (Token.Literal.String.Interpol, '}'), + (Token.Literal.String.Single, ':'), + (Token.Literal.String.Interpol, '{'), + (Token.Name, 'd'), + (Token.Punctuation, '['), + (Token.Name, 'i'), + (Token.Punctuation, ']'), + (Token.Literal.String.Interpol, '}'), + (Token.Literal.String.Single, "'"), + (Token.Text, '\n') + ] + ), ( + "f'x = {x:+3}'\n", + [ + (Token.Literal.String.Affix, 'f'), + (Token.Literal.String.Single, "'"), + (Token.Literal.String.Single, "x = "), + (Token.Literal.String.Interpol, '{'), + (Token.Name, 'x'), + (Token.Literal.String.Interpol, ':'), + (Token.Literal.String.Single, '+3'), + (Token.Literal.String.Interpol, '}'), + (Token.Literal.String.Single, "'"), + (Token.Text, '\n') + ] + ), ( + "f'{fn(lst,2)} {fn(lst,3)}'\n", + [ + (Token.Literal.String.Affix, 'f'), + (Token.Literal.String.Single, "'"), + (Token.Literal.String.Interpol, '{'), + (Token.Name, 'fn'), + (Token.Punctuation, '('), + (Token.Name, 'lst'), + (Token.Punctuation, ','), + (Token.Literal.Number.Integer, '2'), + (Token.Punctuation, ')'), + (Token.Literal.String.Interpol, '}'), + (Token.Literal.String.Single, ' '), + (Token.Literal.String.Interpol, '{'), + (Token.Name, 'fn'), + (Token.Punctuation, '('), + (Token.Name, 'lst'), + (Token.Punctuation, ','), + (Token.Literal.Number.Integer, '3'), + (Token.Punctuation, ')'), + (Token.Literal.String.Interpol, '}'), + (Token.Literal.String.Single, "'"), + (Token.Text, '\n') + ] + ), ( + "f'mapping is { {a:b for (a, b) in ((1, 2), (3, 4))} }'\n", + [ + (Token.Literal.String.Affix, 'f'), + (Token.Literal.String.Single, "'"), + (Token.Literal.String.Single, 'mapping is '), + (Token.Literal.String.Interpol, '{'), + (Token.Text, ' '), + (Token.Punctuation, '{'), + (Token.Name, 'a'), + (Token.Punctuation, ':'), + (Token.Name, 'b'), + (Token.Text, ' '), + (Token.Keyword, 'for'), + (Token.Text, ' '), + (Token.Punctuation, '('), + (Token.Name, 'a'), + (Token.Punctuation, ','), + (Token.Text, ' '), + (Token.Name, 'b'), + (Token.Punctuation, ')'), + (Token.Text, ' '), + (Token.Operator.Word, 'in'), + (Token.Text, ' '), + (Token.Punctuation, '('), + (Token.Punctuation, '('), + (Token.Literal.Number.Integer, '1'), + (Token.Punctuation, ','), + (Token.Text, ' '), + (Token.Literal.Number.Integer, '2'), + (Token.Punctuation, ')'), + (Token.Punctuation, ','), + (Token.Text, ' '), + (Token.Punctuation, '('), + (Token.Literal.Number.Integer, '3'), + (Token.Punctuation, ','), + (Token.Text, ' '), + (Token.Literal.Number.Integer, '4'), + (Token.Punctuation, ')'), + (Token.Punctuation, ')'), + (Token.Punctuation, '}'), + (Token.Text, ' '), + (Token.Literal.String.Interpol, '}'), + (Token.Literal.String.Single, "'"), + (Token.Text, '\n') + ] + ), ( + """f'a={d["a"]}'\n""", + [ + (Token.Literal.String.Affix, 'f'), + (Token.Literal.String.Single, "'"), + (Token.Literal.String.Single, 'a='), + (Token.Literal.String.Interpol, '{'), + (Token.Name, 'd'), + (Token.Punctuation, '['), + (Token.Literal.String.Double, '"'), + (Token.Literal.String.Double, 'a'), + (Token.Literal.String.Double, '"'), + (Token.Punctuation, ']'), + (Token.Literal.String.Interpol, '}'), + (Token.Literal.String.Single, "'"), + (Token.Text, '\n') + ] + ), ( + "f'a={d[a]}'\n", + [ + (Token.Literal.String.Affix, 'f'), + (Token.Literal.String.Single, "'"), + (Token.Literal.String.Single, 'a='), + (Token.Literal.String.Interpol, '{'), + (Token.Name, 'd'), + (Token.Punctuation, '['), + (Token.Name, 'a'), + (Token.Punctuation, ']'), + (Token.Literal.String.Interpol, '}'), + (Token.Literal.String.Single, "'"), + (Token.Text, '\n') + ] + ), ( + "fr'{header}:\\s+'\n", + [ + (Token.Literal.String.Affix, 'fr'), + (Token.Literal.String.Single, "'"), + (Token.Literal.String.Interpol, '{'), + (Token.Name, 'header'), + (Token.Literal.String.Interpol, '}'), + (Token.Literal.String.Single, ':'), + (Token.Literal.String.Single, '\\'), + (Token.Literal.String.Single, 's+'), + (Token.Literal.String.Single, "'"), + (Token.Text, '\n') + ] + ), ( + "f'{a!r}'\n", + [ + (Token.Literal.String.Affix, 'f'), + (Token.Literal.String.Single, "'"), + (Token.Literal.String.Interpol, '{'), + (Token.Name, 'a'), + (Token.Literal.String.Interpol, '!r}'), + (Token.Literal.String.Single, "'"), + (Token.Text, '\n') + ] + ), ( + "f'{(lambda x: x*2)(3)}'\n", + [ + (Token.Literal.String.Affix, 'f'), + (Token.Literal.String.Single, "'"), + (Token.Literal.String.Interpol, '{'), + (Token.Punctuation, '('), + (Token.Keyword, 'lambda'), + (Token.Text, ' '), + (Token.Name, 'x'), + (Token.Punctuation, ':'), + (Token.Text, ' '), + (Token.Name, 'x'), + (Token.Operator, '*'), + (Token.Literal.Number.Integer, '2'), + (Token.Punctuation, ')'), + (Token.Punctuation, '('), + (Token.Literal.Number.Integer, '3'), + (Token.Punctuation, ')'), + (Token.Literal.String.Interpol, '}'), + (Token.Literal.String.Single, "'"), + (Token.Text, '\n') + ] + ), ( + "extra = f'{extra},waiters:{len(self._waiters)}'\n", + [ + (Token.Name, 'extra'), + (Token.Text, ' '), + (Token.Operator, '='), + (Token.Text, ' '), + (Token.Literal.String.Affix, 'f'), + (Token.Literal.String.Single, "'"), + (Token.Literal.String.Interpol, '{'), + (Token.Name, 'extra'), + (Token.Literal.String.Interpol, '}'), + (Token.Literal.String.Single, ',waiters:'), + (Token.Literal.String.Interpol, '{'), + (Token.Name.Builtin, 'len'), + (Token.Punctuation, '('), + (Token.Name.Builtin.Pseudo, 'self'), + (Token.Operator, '.'), + (Token.Name, '_waiters'), + (Token.Punctuation, ')'), + (Token.Literal.String.Interpol, '}'), + (Token.Literal.String.Single, "'"), + (Token.Text, '\n') + ] + ), ( + 'message.append(f" [line {lineno:2d}]")\n', + [ + (Token.Name, 'message'), + (Token.Operator, '.'), + (Token.Name, 'append'), + (Token.Punctuation, '('), + (Token.Literal.String.Affix, 'f'), + (Token.Literal.String.Double, '"'), + (Token.Literal.String.Double, ' [line '), + (Token.Literal.String.Interpol, '{'), + (Token.Name, 'lineno'), + (Token.Literal.String.Interpol, ':'), + (Token.Literal.String.Double, '2d'), + (Token.Literal.String.Interpol, '}'), + (Token.Literal.String.Double, ']'), + (Token.Literal.String.Double, '"'), + (Token.Punctuation, ')'), + (Token.Text, '\n') + ] + ), + # Examples from https://bugs.python.org/issue36817 + ( + 'f"{foo=}"\n', + [ + (Token.Literal.String.Affix, 'f'), + (Token.Literal.String.Double, '"'), + (Token.Literal.String.Interpol, '{'), + (Token.Name, 'foo'), + (Token.Literal.String.Interpol, '=}'), + (Token.Literal.String.Double, '"'), + (Token.Text, '\n') + ] + ), ( + "f'{foo=!s}'\n", + [ + (Token.Literal.String.Affix, 'f'), + (Token.Literal.String.Single, "'"), + (Token.Literal.String.Interpol, '{'), + (Token.Name, 'foo'), + (Token.Literal.String.Interpol, '=!s}'), + (Token.Literal.String.Single, "'"), + (Token.Text, '\n') + ] + ), ( + 'f"{math.pi=!f:.2f}"\n', + [ + (Token.Literal.String.Affix, 'f'), + (Token.Literal.String.Double, '"'), + (Token.Literal.String.Interpol, '{'), + (Token.Name, 'math'), + (Token.Operator, '.'), + (Token.Name, 'pi'), + (Token.Literal.String.Interpol, '=!f:'), + (Token.Literal.String.Double, '.2f'), + (Token.Literal.String.Interpol, '}'), + (Token.Literal.String.Double, '"'), + (Token.Text, '\n') + ] + ), ( + 'f"{ chr(65) =}"\n', + [ + (Token.Literal.String.Affix, 'f'), + (Token.Literal.String.Double, '"'), + (Token.Literal.String.Interpol, '{'), + (Token.Text, ' '), + (Token.Name.Builtin, 'chr'), + (Token.Punctuation, '('), + (Token.Literal.Number.Integer, '65'), + (Token.Punctuation, ')'), + (Token.Text, ' '), + (Token.Literal.String.Interpol, '=}'), + (Token.Literal.String.Double, '"'), + (Token.Text, '\n') + ] + ), ( + 'f"{chr(65) = }"\n', + [ + (Token.Literal.String.Affix, 'f'), + (Token.Literal.String.Double, '"'), + (Token.Literal.String.Interpol, '{'), + (Token.Name.Builtin, 'chr'), + (Token.Punctuation, '('), + (Token.Literal.Number.Integer, '65'), + (Token.Punctuation, ')'), + (Token.Text, ' '), + (Token.Literal.String.Interpol, '= }'), + (Token.Literal.String.Double, '"'), + (Token.Text, '\n') + ] + ), ( + "f'*{n=:30}*'\n", + [ + (Token.Literal.String.Affix, 'f'), + (Token.Literal.String.Single, "'"), + (Token.Literal.String.Single, '*'), + (Token.Literal.String.Interpol, '{'), + (Token.Name, 'n'), + (Token.Literal.String.Interpol, '=:'), + (Token.Literal.String.Single, '30'), + (Token.Literal.String.Interpol, '}'), + (Token.Literal.String.Single, '*'), + (Token.Literal.String.Single, "'"), + (Token.Text, '\n') + ] + ), ( + "f'*{n=!r:30}*'\n", + [ + (Token.Literal.String.Affix, 'f'), + (Token.Literal.String.Single, "'"), + (Token.Literal.String.Single, '*'), + (Token.Literal.String.Interpol, '{'), + (Token.Name, 'n'), + (Token.Literal.String.Interpol, '=!r:'), + (Token.Literal.String.Single, '30'), + (Token.Literal.String.Interpol, '}'), + (Token.Literal.String.Single, '*'), + (Token.Literal.String.Single, "'"), + (Token.Text, '\n') + ] + ), ( + """f"*{f'{n=}':30}*"\n""", + [ + (Token.Literal.String.Affix, 'f'), + (Token.Literal.String.Double, '"'), + (Token.Literal.String.Double, '*'), + (Token.Literal.String.Interpol, '{'), + (Token.Literal.String.Affix, 'f'), + (Token.Literal.String.Single, "'"), + (Token.Literal.String.Interpol, '{'), + (Token.Name, 'n'), + (Token.Literal.String.Interpol, '=}'), + (Token.Literal.String.Single, "'"), + (Token.Literal.String.Interpol, ':'), + (Token.Literal.String.Double, '30'), + (Token.Literal.String.Interpol, '}'), + (Token.Literal.String.Double, '*'), + (Token.Literal.String.Double, '"'), + (Token.Text, '\n') + ] + ), ( + "f'*{n=:+<30}*'\n", + [ + (Token.Literal.String.Affix, 'f'), + (Token.Literal.String.Single, "'"), + (Token.Literal.String.Single, '*'), + (Token.Literal.String.Interpol, '{'), + (Token.Name, 'n'), + (Token.Literal.String.Interpol, '=:'), + (Token.Literal.String.Single, '+<30'), + (Token.Literal.String.Interpol, '}'), + (Token.Literal.String.Single, '*'), + (Token.Literal.String.Single, "'"), + (Token.Text, '\n') + ] + ), ( + """ + f'''{foo + = !s:20}'''\n""", + [ + (Token.Text, ' '), + (Token.Literal.String.Affix, 'f'), + (Token.Literal.String.Single, "'''"), + (Token.Literal.String.Interpol, '{'), + (Token.Name, 'foo'), + (Token.Text, '\n '), + (Token.Literal.String.Interpol, '= !s:'), + (Token.Literal.String.Single, '20'), + (Token.Literal.String.Interpol, '}'), + (Token.Literal.String.Single, "'''"), + (Token.Text, '\n') + ] + ) + + ) + + for fragment,tokens in fragments_and_tokens: + assert list(lexer3.get_tokens(fragment)) == tokens + + # Now switch between single and double quotes, to cover both cases equally + rep = {"'":'"', '"':"'"} + pattern = re.compile("|".join(rep.keys())) + for fragment,tokens in fragments_and_tokens: + fragment = pattern.sub(lambda m: rep[m.group(0)], fragment) + tokens = list(tokens) + for i,(token,match) in enumerate(tokens): + if token == Token.Literal.String.Single: + token = Token.Literal.String.Double + elif token == Token.Literal.String.Double: + token = Token.Literal.String.Single + match = pattern.sub(lambda m: rep[m.group(0)], match) + tokens[i] = (token, match) + assert list(lexer3.get_tokens(fragment)) == tokens |