You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-03 00:45:53 +08:00
148 lines
3.4 KiB
Python
148 lines
3.4 KiB
Python
# Self-checking test.
|
|
# String interpolation tests
|
|
|
|
# RUNNABLE!
|
|
"""This program is self-checking!"""
|
|
|
|
var1 = "x"
|
|
var2 = "y"
|
|
abc = "def"
|
|
assert (
|
|
f"interpolate {var1} strings {var2!r} {var2!s} 'py36"
|
|
== "interpolate x strings 'y' y 'py36"
|
|
)
|
|
assert "def0" == f"{abc}0"
|
|
assert "defdef" == f"{abc}{abc!s}"
|
|
|
|
|
|
# From 3.8 test/test_string.py
|
|
# We had the precedence of yield vs. lambda incorrect.
|
|
def fn(x):
|
|
yield f"x:{yield (lambda i: x * i)}"
|
|
|
|
|
|
# From 3.6 functools.py
|
|
# Bug was handling format operator strings.
|
|
|
|
k, v = "1", ["2"]
|
|
x = f"{k}={v!r}"
|
|
y = f"functools.{x}({', '.join(v)})"
|
|
assert x == "1=['2']"
|
|
assert y == "functools.1=['2'](2)"
|
|
|
|
# From 3.6 http/client.py
|
|
# Bug is in handling X
|
|
chunk = ["a", "b", "c"]
|
|
chunk2 = "d"
|
|
chunk = f"{len(chunk):X}" + chunk2
|
|
assert chunk == "3d"
|
|
|
|
chunk = b"abc"
|
|
chunk2 = "d"
|
|
chunk = f"{len(chunk):X}\r\n".encode("ascii") + chunk + b"\r\n"
|
|
assert chunk == b"3\r\nabc\r\n"
|
|
|
|
# From 3.6.8 idlelib/pyshell.py
|
|
# Bug was handling '''
|
|
import os
|
|
|
|
filename = "."
|
|
source = "foo"
|
|
source = f"__file__ = r'''{os.path.abspath(filename)}'''\n" + source + "\ndel __file__"
|
|
|
|
# Note how { and } are *not* escaped here
|
|
f = "one"
|
|
name = "two"
|
|
assert (f"{f}{'{{name}}'} {f}{'{name}'}") == "one{{name}} one{name}"
|
|
|
|
# From 3.7.3 dataclasses.py
|
|
log_rounds = 5
|
|
assert "05$" == f"{log_rounds:02d}$"
|
|
|
|
|
|
def testit(a, b, ll):
|
|
# print(ll)
|
|
return ll
|
|
|
|
|
|
# The call below shows the need for BUILD_STRING to count expr arguments.
|
|
# Also note that we use {{ }} to escape braces in contrast to the example
|
|
# above.
|
|
def _repr_fn(fields):
|
|
return testit(
|
|
"__repr__",
|
|
("self",),
|
|
['return xx + f"(' + ", ".join([f"{f}={{self.{f}!r}}" for f in fields]) + ')"'],
|
|
)
|
|
|
|
|
|
fields = ["a", "b", "c"]
|
|
assert _repr_fn(fields) == ['return xx + f"(a={self.a!r}, b={self.b!r}, c={self.c!r})"']
|
|
|
|
|
|
#################################
|
|
# From Python 3.7 test_fstring.py
|
|
|
|
x = 5
|
|
assert f'{(lambda y:x*y)("8")!r}' == "'88888'"
|
|
assert f'{(lambda y:x*y)("8")!r:10}' == "'88888' "
|
|
assert f'{(lambda y:x*y)("8"):10}' == "88888 "
|
|
|
|
try:
|
|
eval("f'{lambda x:x}'")
|
|
except SyntaxError:
|
|
pass
|
|
else:
|
|
assert False, "f'{lambda x:x}' should be a syntax error"
|
|
|
|
(x, y, width) = ("foo", 2, 10)
|
|
assert f"x={x*y:{width}}" == "x=foofoo "
|
|
|
|
|
|
# Why the fact that the distinction of docstring versus stmt is a
|
|
# string expression is important academic, but we will decompile an
|
|
# equivalent thing. For compatibility with older Python we'll use "%"
|
|
# instead of a format string
|
|
def f():
|
|
f"""Not a docstring""" # noqa
|
|
|
|
|
|
def g():
|
|
"""Not a docstring""" f"" # noqa
|
|
|
|
|
|
assert f.__doc__ is None
|
|
assert g.__doc__ is None
|
|
|
|
import decimal
|
|
|
|
width, precision, value = (10, 4, decimal.Decimal("12.34567"))
|
|
|
|
# Make sure we don't have additional f'..' inside the format strings below.
|
|
assert f"result: {value:{width}.{precision}}" == "result: 12.35"
|
|
assert f"result: {value:{width:0}.{precision:1}}" == "result: 12.35"
|
|
assert f"{2}\t" == "2\t"
|
|
|
|
# But below we *do* need the additional f".."
|
|
assert f'{f"{0}"*3}' == "000"
|
|
|
|
# We need to make sure we have { {x:... not {{x: ...
|
|
# ^
|
|
# The former, {{ confuses the format strings so dictionary/set comprehensions
|
|
# don't work.
|
|
assert f"expr={ {x: y for x, y in [(1, 2), ]}}" == "expr={1: 2}"
|
|
|
|
|
|
class Line:
|
|
def __init__(self, x, y):
|
|
self.x = x
|
|
self.y = y
|
|
|
|
# From 3.7 test_typing.py
|
|
def __str__(self):
|
|
return f"{self.x} -> {self.y}"
|
|
|
|
|
|
line = Line(1, 2)
|
|
assert str(line) == "1 -> 2"
|