Skip to content

Commit 91aeef3

Browse files
committed
tests: detect stale Cython .so files at test startup
Add a pytest_configure hook in tests/conftest.py that compares mtime of each compiled .so against its .py source and warns when the source is newer. This prevents silently testing stale compiled code after editing a Cython-compiled module without rebuilding. Also document the rebuild requirement in CONTRIBUTING.rst.
1 parent efdc08a commit 91aeef3

File tree

2 files changed

+65
-0
lines changed

2 files changed

+65
-0
lines changed

CONTRIBUTING.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,16 @@ When modifying driver files, rebuilding Cython modules is often necessary.
4040
Without caching, each such rebuild may take over a minute. Caching usually brings it
4141
down to about 2-3 seconds.
4242

43+
**Important:** After modifying any ``.py`` file under ``cassandra/`` that is
44+
Cython-compiled (such as ``query.py``, ``protocol.py``, ``cluster.py``, etc.),
45+
you **must** rebuild extensions before running tests::
46+
47+
python setup.py build_ext --inplace
48+
49+
Without rebuilding, Python will load the stale compiled ``.so`` file instead of
50+
your modified ``.py`` source, and your changes will not actually be tested.
51+
The test suite will emit a warning if it detects this situation.
52+
4353
Building the Docs
4454
=================
4555

tests/conftest.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# Copyright ScyllaDB, Inc.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import glob
16+
import os
17+
import warnings
18+
19+
# Directory containing the Cython-compiled driver modules.
20+
_CASSANDRA_DIR = os.path.join(os.path.dirname(__file__), os.pardir, "cassandra")
21+
22+
23+
def pytest_configure(config):
24+
"""Warn when a compiled Cython .so is older than its .py source.
25+
26+
Python's import system prefers compiled extensions (.so / .pyd) over pure
27+
Python (.py) files. If a developer edits a .py file without rebuilding
28+
the Cython extensions (``python setup.py build_ext --inplace``), the tests
29+
will silently run the *old* compiled code, masking any regressions in the
30+
Python source.
31+
32+
This hook detects such staleness at test-session startup so the developer
33+
is alerted immediately.
34+
"""
35+
stale = []
36+
for so_path in glob.glob(os.path.join(_CASSANDRA_DIR, "*.so")):
37+
# Extension filenames look like query.cpython-314-x86_64-linux-gnu.so
38+
# The corresponding source is query.py
39+
basename = os.path.basename(so_path)
40+
module_name = basename.split(".")[0]
41+
py_path = os.path.join(_CASSANDRA_DIR, module_name + ".py")
42+
if os.path.exists(py_path) and os.path.getmtime(py_path) > os.path.getmtime(
43+
so_path
44+
):
45+
stale.append((module_name, so_path, py_path))
46+
47+
if stale:
48+
names = ", ".join(m for m, _, _ in stale)
49+
warnings.warn(
50+
f"Stale Cython extension(s) detected: {names}. "
51+
f"The .py source is newer than the compiled .so — tests will run "
52+
f"the OLD compiled code, not your latest changes. "
53+
f"Rebuild with: python setup.py build_ext --inplace",
54+
stacklevel=1,
55+
)

0 commit comments

Comments
 (0)