mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-10-10 13:33:24 -05:00
fix: hold the installer to python 3.8 for real
This commit is contained in:
1 parent
8380f63f97
commit
61cba2d3c1
1 file changed
+86
-1
+86
-1
@@ -855,10 +855,95 @@ class InstallerStaysOnPython38AndTheStdlib(unittest.TestCase):
|
|||||||
|
|
||||||
def test_no_api_newer_than_38(self):
|
def test_no_api_newer_than_38(self):
|
||||||
newer = (".removeprefix(", ".removesuffix(", "zoneinfo", "graphlib",
|
newer = (".removeprefix(", ".removesuffix(", "zoneinfo", "graphlib",
|
||||||
"functools.cache(", ".bit_count(", "math.lcm(", "math.nextafter(")
|
"functools.cache(", ".bit_count(", "math.lcm(", "math.nextafter(",
|
||||||
|
"tomllib", ".is_relative_to(", ".with_stem(", ".hardlink_to(",
|
||||||
|
"itertools.pairwise(", "str.removeprefix", "types.NoneType")
|
||||||
used = [api for api in newer if api in self.SOURCE]
|
used = [api for api in newer if api in self.SOURCE]
|
||||||
self.assertEqual(used, [])
|
self.assertEqual(used, [])
|
||||||
|
|
||||||
|
def test_a_python_38_interpreter_compiles_and_imports_it(self):
|
||||||
|
"""ast.parse(feature_version=(3, 8)) on 3.12 accepts parenthesized
|
||||||
|
context managers and PEP 701 f-strings: only a 3.8 interpreter says."""
|
||||||
|
import shutil # noqa: PLC0415
|
||||||
|
import subprocess # noqa: PLC0415
|
||||||
|
|
||||||
|
python38 = shutil.which("python3.8")
|
||||||
|
if python38 is None:
|
||||||
|
self.skipTest("no python3.8 on PATH; the static checks below still run")
|
||||||
|
code = (
|
||||||
|
"import importlib.util; "
|
||||||
|
"spec = importlib.util.spec_from_file_location('install', 'install.py'); "
|
||||||
|
"spec.loader.exec_module(importlib.util.module_from_spec(spec))"
|
||||||
|
)
|
||||||
|
proc = subprocess.run(
|
||||||
|
[python38, "-I", "-c", code], cwd=REPO_ROOT,
|
||||||
|
capture_output=True, text=True, timeout=60, check=False,
|
||||||
|
)
|
||||||
|
self.assertEqual(proc.returncode, 0, proc.stderr)
|
||||||
|
|
||||||
|
def test_no_syntax_a_312_parser_lets_through(self):
|
||||||
|
"""Parenthesized context managers (3.9) and f-strings reusing their
|
||||||
|
own quote or a backslash inside a replacement field (3.12)."""
|
||||||
|
import io # noqa: PLC0415
|
||||||
|
import tokenize # noqa: PLC0415
|
||||||
|
|
||||||
|
found = []
|
||||||
|
tokens = list(tokenize.generate_tokens(io.StringIO(self.SOURCE).readline))
|
||||||
|
for i, tok in enumerate(tokens):
|
||||||
|
if tok.type == tokenize.NAME and tok.string == "with" and i + 1 < len(tokens):
|
||||||
|
if tokens[i + 1].string != "(":
|
||||||
|
continue
|
||||||
|
depth = 0
|
||||||
|
for inner in tokens[i + 1:]:
|
||||||
|
if inner.string in "([{" and inner.type == tokenize.OP:
|
||||||
|
depth += 1
|
||||||
|
elif inner.string in ")]}" and inner.type == tokenize.OP:
|
||||||
|
depth -= 1
|
||||||
|
if depth == 0:
|
||||||
|
break
|
||||||
|
elif depth == 1 and inner.type == tokenize.NAME and inner.string == "as":
|
||||||
|
found.append(f"line {tok.start[0]}: parenthesized with")
|
||||||
|
break
|
||||||
|
fstring_start = getattr(tokenize, "FSTRING_START", None)
|
||||||
|
if fstring_start is not None:
|
||||||
|
stack = []
|
||||||
|
for tok in tokens:
|
||||||
|
if tok.type == fstring_start:
|
||||||
|
if stack:
|
||||||
|
found.append(f"line {tok.start[0]}: f-string inside an f-string")
|
||||||
|
stack.append(tok.string[-1])
|
||||||
|
elif tok.type == tokenize.FSTRING_END:
|
||||||
|
stack.pop()
|
||||||
|
elif stack and tok.type == tokenize.STRING and stack[-1] in tok.string:
|
||||||
|
found.append(f"line {tok.start[0]}: f-string reuses its quote")
|
||||||
|
elif stack and tok.type == tokenize.FSTRING_MIDDLE:
|
||||||
|
continue
|
||||||
|
elif stack and tok.type == tokenize.ERRORTOKEN and tok.string == "\\":
|
||||||
|
found.append(f"line {tok.start[0]}: backslash in an f-string field")
|
||||||
|
self.assertEqual(found, [])
|
||||||
|
|
||||||
|
def test_no_runtime_generic_builtin(self):
|
||||||
|
"""dict[str, Path] outside an annotation runs on 3.9 and later only."""
|
||||||
|
import ast # noqa: PLC0415
|
||||||
|
|
||||||
|
tree = ast.parse(self.SOURCE)
|
||||||
|
annotations = set()
|
||||||
|
for node in ast.walk(tree):
|
||||||
|
for field in ("annotation", "returns"):
|
||||||
|
sub = getattr(node, field, None)
|
||||||
|
if sub is not None:
|
||||||
|
annotations.update(id(n) for n in ast.walk(sub))
|
||||||
|
generic = {"dict", "list", "tuple", "set", "frozenset", "type"}
|
||||||
|
used = sorted(
|
||||||
|
f"line {node.lineno}: {node.value.id}[...]"
|
||||||
|
for node in ast.walk(tree)
|
||||||
|
if isinstance(node, ast.Subscript)
|
||||||
|
and isinstance(node.value, ast.Name)
|
||||||
|
and node.value.id in generic
|
||||||
|
and id(node) not in annotations
|
||||||
|
)
|
||||||
|
self.assertEqual(used, [])
|
||||||
|
|
||||||
|
|
||||||
class ARefusedCopyIsAnError(unittest.TestCase):
|
class ARefusedCopyIsAnError(unittest.TestCase):
|
||||||
"""A PermissionError on a standalone copy was counted as "dir not found"
|
"""A PermissionError on a standalone copy was counted as "dir not found"
|
||||||
|
|||||||
Reference in new issue
Block a user