Skip to content

Commit 315f9b9

Browse files
committed
Some polish
1 parent 378cc16 commit 315f9b9

2 files changed

Lines changed: 23 additions & 32 deletions

File tree

mypyc/test/librt_cache.py

Lines changed: 22 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
"""Build and cache librt for use in non-compiled tests.
1+
"""Build and cache librt for use in tests.
22
33
This module provides a way to build librt extension modules once and cache
4-
them across test runs. The cache is invalidated when source files change.
4+
them across test runs, and across different test cases in a single run. The
5+
cache is invalidated when source files or details of the build environment change.
56
6-
Note: Tests must run in a subprocess to use the built librt, since importing
7-
this module triggers the system librt import via mypyc.build -> mypy.build.
7+
Note: Tests must run in a subprocess to use the cached librt, since importing
8+
this module also triggers the import of the regular installed librt.
89
910
Usage:
1011
from mypyc.test.librt_cache import get_librt_path, run_with_librt
@@ -24,10 +25,12 @@
2425
import subprocess
2526
import sys
2627
import sysconfig
28+
from typing import Any
2729

2830
import filelock
2931

30-
from mypyc.build import LIBRT_MODULES, RUNTIME_C_FILES, get_cflags, include_dir
32+
from mypyc.build import LIBRT_MODULES, get_cflags, include_dir
33+
from mypyc.common import RUNTIME_C_FILES
3134

3235

3336
def _librt_build_hash(experimental: bool) -> str:
@@ -46,8 +49,8 @@ def _librt_build_hash(experimental: bool) -> str:
4649
# Include free-threading status (Python 3.13+)
4750
is_free_threaded = bool(sysconfig.get_config_var("Py_GIL_DISABLED"))
4851
h.update(b"freethreaded" if is_free_threaded else b"gil")
49-
# Include compiler type (e.g., "unix", "msvc")
50-
compiler = ccompiler.new_compiler()
52+
# Include compiler type (e.g., "unix" or "msvc")
53+
compiler: Any = ccompiler.new_compiler()
5154
h.update(compiler.compiler_type.encode())
5255
# Include environment variables that affect C compilation
5356
for var in ("CC", "CXX", "CFLAGS", "CPPFLAGS", "LDFLAGS"):
@@ -56,25 +59,24 @@ def _librt_build_hash(experimental: bool) -> str:
5659
# Hash runtime files
5760
for name in RUNTIME_C_FILES:
5861
path = os.path.join(include_dir(), name)
59-
if os.path.exists(path):
60-
with open(path, "rb") as f:
61-
h.update(f.read())
62+
h.update(name.encode() + b"|")
63+
with open(path, "rb") as f:
64+
h.update(f.read())
6265
# Hash librt module files
6366
for mod, files, extra, includes in LIBRT_MODULES:
6467
for fname in files + extra:
6568
path = os.path.join(include_dir(), fname)
66-
if os.path.exists(path):
67-
with open(path, "rb") as f:
68-
h.update(f.read())
69+
h.update(fname.encode() + b"|")
70+
with open(path, "rb") as f:
71+
h.update(f.read())
6972
return h.hexdigest()[:16]
7073

7174

7275
def _generate_setup_py(build_dir: str, experimental: bool) -> str:
7376
"""Generate setup.py content for building librt directly.
7477
7578
We inline LIBRT_MODULES/RUNTIME_C_FILES/include_dir/cflags values to avoid
76-
importing mypyc.build, which imports mypy.build, which imports librt
77-
(circular dependency when librt isn't built yet).
79+
importing mypyc.build, which recursively imports lots of things.
7880
"""
7981
lib_rt_dir = include_dir()
8082

@@ -101,22 +103,15 @@ def _generate_setup_py(build_dir: str, experimental: bool) -> str:
101103
CFLAGS = {cflags_repr}
102104
103105
def write_file(path, contents):
104-
encoded = contents.encode("utf-8")
105106
os.makedirs(os.path.dirname(path), exist_ok=True)
106-
try:
107-
with open(path, "rb") as f:
108-
if f.read() == encoded:
109-
return
110-
except OSError:
111-
pass
112107
with open(path, "wb") as f:
113-
f.write(encoded)
108+
f.write(contents)
114109
115110
# Copy runtime C files
116111
for name in RUNTIME_C_FILES:
117112
src = os.path.join(lib_rt_dir, name)
118113
dst = os.path.join(build_dir, name)
119-
with open(src, encoding="utf-8") as f:
114+
with open(src, "rb") as f:
120115
write_file(dst, f.read())
121116
122117
# Build extensions for each librt module
@@ -126,7 +121,7 @@ def write_file(path, contents):
126121
for fname in file_names + extra_files:
127122
src = os.path.join(lib_rt_dir, fname)
128123
dst = os.path.join(build_dir, fname)
129-
with open(src, encoding="utf-8") as f:
124+
with open(src, "rb") as f:
130125
write_file(dst, f.read())
131126
132127
extensions.append(Extension(
@@ -141,7 +136,7 @@ def write_file(path, contents):
141136

142137

143138
def get_librt_path(experimental: bool = True) -> str:
144-
"""Get path to built librt, building and caching if necessary.
139+
"""Get path to librt built from the repository, building and caching if necessary.
145140
146141
Uses build/librt-cache/ under the repo root (gitignored). The cache is
147142
keyed by a hash of sources and build environment, so it auto-invalidates
@@ -234,9 +229,5 @@ def run_with_librt(
234229
env["PYTHONPATH"] = librt_path + (os.pathsep + existing if existing else "")
235230

236231
return subprocess.run(
237-
[sys.executable, file_path],
238-
capture_output=True,
239-
text=True,
240-
check=check,
241-
env=env,
232+
[sys.executable, file_path], capture_output=True, text=True, check=check, env=env
242233
)

mypyc/test/test_run.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@
2626
from mypyc.errors import Errors
2727
from mypyc.options import CompilerOptions
2828
from mypyc.test.config import test_data_prefix
29-
from mypyc.test.test_serialization import check_serialization_roundtrip
3029
from mypyc.test.librt_cache import get_librt_path
30+
from mypyc.test.test_serialization import check_serialization_roundtrip
3131
from mypyc.test.testutil import (
3232
ICODE_GEN_BUILTINS,
3333
TESTUTIL_PATH,

0 commit comments

Comments
 (0)