* rustpython_vm::import::import_source
* always print exceptions when panic by expect_pyresult
if users want simple panic, Result::expect could be used.
It turns out that there are many other tests that can impact
test_many_opens by leaving unclosed file handles. Rather than fix them
all, it is easier to simply increase the threshold for the problematic
test.
Context managers have an `__exit__` function that returns a boolean-like
object. If the object is truthy, then exceptions are suppressed.
If an exception was thrown while resolving that boolean, it would leak
and live on in the error stack, getting tacked on to all future
exceptions. This caused several mysterious test failures which would
only trigger after this very specific event was tested in `test_with`.
The solution is to move a call to `vm.set_exception()` before
attempting the `try_to_bool()` which threw the error.
Minimal example to reproduce the bug:
```py
import sys
import traceback
class cm(object):
def __init__(self):
pass
def __enter__(self):
return 3
def __exit__(self, a, b, c):
class Bool:
def __bool__(self):
1 // 0
return Bool()
try:
with cm():
raise Exception("Should NOT see this")
except ZeroDivisionError:
print("exception caught, as expected")
print("There should now be no exception")
traceback.print_exc()
print(sys.exc_info())
```
There seems to have been a bug in the libregrtest code which unloaded
modules between tests. The previous state was calculated using
`sys.modules.keys()`, which is actually a mutable object that is updated
as the underlying `sys.modules` is updated. The result was that modules
were not unloaded between tests, which is the root cause for
`test_unittest` failing when run after `test_import` and
`test_importlib`.
This code is copied from 3.12. Ideally all of `libregrtest` should
probably be updated as it seems wildly out of date, but that's a lot
more work.
This test was marked as an expected failure. Because the garbage
collector is missing, that meant that the `os.scandir` object went
unclosed. This object was squatting on the file descriptors of all the
files contained in the test directory, which was breaking test_zipfile.
After you suggestion in https://github.com/python/cpython/issues/116504#issuecomment-1999239012 I went to take a look at `test_cmd_line` in RustPython (it was so long ago I contributed to this amazing project, so may thing had changed!), and I've noticed this.
This is a problem, here' the simplest demo:
```python
import unittest
class TestMe(unittest.TestCase):
@unittest.expectedFailure
def test_me(self):
def run():
raise ValueError
with self.subTest(run=run):
run()
if __name__ == '__main__':
unittest.main()
```
This works as expected:
```
» ./python.exe ex.py
x
----------------------------------------------------------------------
Ran 1 test in 0.001s
OK (expected failures=1)
```
This does not:
```python
import unittest
class TestMe(unittest.TestCase):
def test_me(self):
@unittest.expectedFailure
def run():
raise ValueError
with self.subTest(run=run):
run()
if __name__ == '__main__':
unittest.main()
```
Produces:
```
» ./python.exe ex.py
E
======================================================================
ERROR: test_me (__main__.TestMe.test_me) (run=<function TestMe.test_me.<locals>.run at 0x1057a2150>)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/sobolev/Desktop/cpython2/ex.py", line 10, in test_me
run()
~~~^^
File "/Users/sobolev/Desktop/cpython2/ex.py", line 7, in run
raise ValueError
ValueError
----------------------------------------------------------------------
Ran 1 test in 0.001s
FAILED (errors=1)
```
So, I propose to remove these decorators, let's only keep `TODO` comments to indicate separate failures.