classification
Title: fix _PyRun_SimpleFileObject create __main__ module and cache. Call this function multiple times, the attributes stored in the module dict will affect eachother.
Type: behavior Stage: resolved
Components: C API Versions: Python 3.10
process
Status: closed Resolution: wont fix
Dependencies: Superseder:
Assigned To: Nosy List: JunyiXie, petr.viktorin
Priority: normal Keywords: patch

Created on 2021-03-26 03:57 by JunyiXie, last changed 2021-07-20 13:07 by petr.viktorin. This issue is now closed.

Pull Requests
URL Status Linked Edit
PR 25023 closed JunyiXie, 2021-03-26 04:01
Messages (2)
msg389538 - (view) Author: junyixie (JunyiXie) * Date: 2021-03-26 03:57
fix _PyRun_SimpleFileObject create __main__ module and cache. Call this function multiple times, the attributes stored in the module dict will affect eachother.

create __main__ module, and cache it.

for example. 
if we run fileA, call _PyRun_SimpleFileObject will create __main__ module, fileA add some attribute in __main__ module dict.

now we run fileB. call _PyRun_SimpleFileObject will load cached __main__ module. now in __main__ module dict, we can get fileA's attribute.


dir(module), We got unexpected results
```
for name in dir(module):
    ...
```

in unittest, if we execute test, and don't exit. (unittest main.py TestProgram), set exit=False.
```
    def __init__(self, module='__main__', defaultTest=None, argv=None,
                    testRunner=None, testLoader=loader.defaultTestLoader,
                    exit=True, verbosity=1, failfast=None, catchbreak=None,
                    buffer=None, warnings=None, *, tb_locals=False):
```

then when unittest load tests. if we use _PyRun_SimpleFileObject to run unittest, it will Repeated load test cases
```
        for name in dir(module):
            obj = getattr(module, name)
            if isinstance(obj, type) and issubclass(obj, case.TestCase):
                tests.append(self.loadTestsFromTestCase(obj))
```


```
int
_PyRun_SimpleFileObject(FILE *fp, PyObject *filename, int closeit,
                        PyCompilerFlags *flags)
{
    PyObject *m, *d, *v;
    int set_file_name = 0, ret = -1;

    m = PyImport_AddModule("__main__");
    if (m == NULL)
        return -1;
    Py_INCREF(m);
    d = PyModule_GetDict(m);
```
msg397868 - (view) Author: Petr Viktorin (petr.viktorin) * (Python committer) Date: 2021-07-20 13:07
The public function that calls _PyRun_SimpleFileObject is PyRun_SimpleStringFlags, and the behavior is as specified in its documentation: "Executes the Python source code from command in the __main__ module according to the flags argument. If __main__ does not already exist, it is created."

https://docs.python.org/3.8/c-api/veryhigh.html?highlight=pyrun_simplefileexflags#c.PyRun_SimpleStringFlags
History
Date User Action Args
2021-07-20 13:07:41petr.viktorinsetstatus: open -> closed

nosy: + petr.viktorin
messages: + msg397868

stage: patch review -> resolved
2021-03-26 06:37:07JunyiXiesetresolution: wont fix
2021-03-26 04:01:35JunyiXiesetkeywords: + patch
stage: patch review
pull_requests: + pull_request23773
2021-03-26 03:57:11JunyiXiecreate