Skip to content

Commit d4b7c91

Browse files
committed
Fix cron-ci failures: ctypes set_attr, missing features, __func__ AttributeError
- Use cls.set_attr() instead of cls.as_object().set_attr() in ctypes to ensure modified() is called and type cache stays valid - Add host_env feature to cron-ci.yaml for frozen_origname_matches test - Add stdio feature to cron-ci.yaml for encodings initialization - Fix __func__ AttributeError in custom_text_test_runner.py
1 parent add34a2 commit d4b7c91

File tree

5 files changed

+32
-29
lines changed

5 files changed

+32
-29
lines changed

.github/workflows/cron-ci.yaml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ on:
1212
name: Periodic checks/tasks
1313

1414
env:
15-
CARGO_ARGS: --no-default-features --features stdlib,importlib,encodings,ssl-rustls,jit
15+
CARGO_ARGS: --no-default-features --features stdlib,importlib,stdio,encodings,ssl-rustls,jit,host_env
1616
PYTHON_VERSION: "3.14.3"
1717

1818
jobs:
@@ -35,7 +35,7 @@ jobs:
3535
python-version: ${{ env.PYTHON_VERSION }}
3636
- run: sudo apt-get update && sudo apt-get -y install lcov
3737
- name: Run cargo-llvm-cov with Rust tests.
38-
run: cargo llvm-cov --no-report --workspace --exclude rustpython_wasm --exclude rustpython-compiler-source --exclude rustpython-venvlauncher --verbose --no-default-features --features stdlib,importlib,encodings,ssl-rustls,jit
38+
run: cargo llvm-cov --no-report --workspace --exclude rustpython_wasm --exclude rustpython-compiler-source --exclude rustpython-venvlauncher --verbose --no-default-features --features stdlib,importlib,stdio,encodings,ssl-rustls,jit
3939
- name: Run cargo-llvm-cov with Python snippets.
4040
run: python scripts/cargo-llvm-cov.py
4141
continue-on-error: true
@@ -170,12 +170,12 @@ jobs:
170170
- name: restructure generated files
171171
run: |
172172
cd ./target/criterion/reports
173-
find -type d -name cpython | xargs rm -rf
174-
find -type d -name rustpython | xargs rm -rf
175-
find -mindepth 2 -maxdepth 2 -name violin.svg | xargs rm -rf
176-
find -type f -not -name violin.svg | xargs rm -rf
177-
for file in $(find -type f -name violin.svg); do mv $file $(echo $file | sed -E "s_\./([^/]+)/([^/]+)/violin\.svg_./\1/\2.svg_"); done
178-
find -mindepth 2 -maxdepth 2 -type d | xargs rm -rf
173+
find . -type d -name cpython | xargs rm -rf
174+
find . -type d -name rustpython | xargs rm -rf
175+
find . -mindepth 2 -maxdepth 2 -name violin.svg | xargs rm -rf
176+
find . -type f -not -name violin.svg | xargs rm -rf
177+
for file in $(find . -type f -name violin.svg); do mv "$file" $(echo "$file" | sed -E "s_\./([^/]+)/([^/]+)/violin\.svg_./\1/\2.svg_"); done
178+
find . -mindepth 2 -maxdepth 2 -type d | xargs rm -rf
179179
cd ..
180180
mv reports/* .
181181
rmdir reports

crates/vm/src/stdlib/_ctypes/base.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2554,11 +2554,10 @@ fn make_fields(
25542554
}
25552555

25562556
let new_descr = super::PyCField::new_from_field(fdescr, index, offset);
2557-
cls.as_object().set_attr(
2557+
cls.set_attr(
25582558
vm.ctx.intern_str(fname.as_wtf8()),
25592559
new_descr.to_pyobject(vm),
2560-
vm,
2561-
)?;
2560+
);
25622561
}
25632562

25642563
Ok(())
@@ -2597,11 +2596,10 @@ pub(super) fn make_anon_fields(cls: &Py<PyType>, vm: &VirtualMachine) -> PyResul
25972596

25982597
let mut new_descr = super::PyCField::new_from_field(descr, 0, 0);
25992598
new_descr.set_anonymous(true);
2600-
cls.as_object().set_attr(
2599+
cls.set_attr(
26012600
vm.ctx.intern_str(fname.as_wtf8()),
26022601
new_descr.to_pyobject(vm),
2603-
vm,
2604-
)?;
2602+
);
26052603

26062604
make_fields(cls, descr, descr.index, descr.offset, vm)?;
26072605
}

crates/vm/src/stdlib/_ctypes/structure.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -498,11 +498,7 @@ impl PyCStructType {
498498
};
499499

500500
// Set the CField as a class attribute
501-
cls.as_object().set_attr(
502-
vm.ctx.intern_str(name.clone()),
503-
c_field.to_pyobject(vm),
504-
vm,
505-
)?;
501+
cls.set_attr(vm.ctx.intern_str(name.clone()), c_field.to_pyobject(vm));
506502

507503
// Update tracking - don't advance offset for packed bitfields
508504
if field_advances_offset {

crates/vm/src/stdlib/_ctypes/union.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -312,8 +312,7 @@ impl PyCUnionType {
312312
PyCField::new(name.clone(), field_type_ref, 0, size as isize, index)
313313
};
314314

315-
cls.as_object()
316-
.set_attr(vm.ctx.intern_str(name), c_field.to_pyobject(vm), vm)?;
315+
cls.set_attr(vm.ctx.intern_str(name), c_field.to_pyobject(vm));
317316
}
318317

319318
// Calculate total_align and aligned_size

extra_tests/custom_text_test_runner.py

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,16 @@
3838
from unittest.runner import registerResult, result
3939

4040

41+
def _get_method_dict(test):
42+
"""Get the __dict__ of the underlying function for a test method.
43+
44+
Works for both bound methods (__func__.__dict__) and plain functions.
45+
"""
46+
method = getattr(test, test._testMethodName)
47+
func = getattr(method, '__func__', method)
48+
return func.__dict__
49+
50+
4151
class TablePrinter(object):
4252
# Modified from https://github.com/agramian/table-printer, same license as above
4353
"Print a list of dicts as a table"
@@ -325,7 +335,7 @@ def startTest(self, test):
325335
self.stream.writeln("TEST SUITE: %s" % self.suite)
326336
self.stream.writeln("Description: %s" % self.getSuiteDescription(test))
327337
try:
328-
name_override = getattr(test, test._testMethodName).__func__.__dict__[
338+
name_override = _get_method_dict(test)[
329339
"test_case_name"
330340
]
331341
except:
@@ -382,30 +392,30 @@ def startTest(self, test):
382392
).__func__.__dict__ and set([s.lower() for s in self.test_types]) == set(
383393
[
384394
s.lower()
385-
for s in getattr(test, test._testMethodName).__func__.__dict__[
395+
for s in _get_method_dict(test)[
386396
"test_type"
387397
]
388398
]
389399
):
390400
pass
391401
else:
392-
getattr(test, test._testMethodName).__func__.__dict__[
402+
_get_method_dict(test)[
393403
"__unittest_skip_why__"
394404
] = 'Test run specified to only run tests of type "%s"' % ",".join(
395405
self.test_types
396406
)
397-
getattr(test, test._testMethodName).__func__.__dict__[
407+
_get_method_dict(test)[
398408
"__unittest_skip__"
399409
] = True
400-
if "skip_device" in getattr(test, test._testMethodName).__func__.__dict__:
401-
for device in getattr(test, test._testMethodName).__func__.__dict__[
410+
if "skip_device" in _get_method_dict(test):
411+
for device in _get_method_dict(test)[
402412
"skip_device"
403413
]:
404414
if self.config and device.lower() in self.config["device_name"].lower():
405-
getattr(test, test._testMethodName).__func__.__dict__[
415+
_get_method_dict(test)[
406416
"__unittest_skip_why__"
407417
] = "Test is marked to be skipped on %s" % device
408-
getattr(test, test._testMethodName).__func__.__dict__[
418+
_get_method_dict(test)[
409419
"__unittest_skip__"
410420
] = True
411421
break

0 commit comments

Comments
 (0)