| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Sorry, something went wrong.
Rename _Py_fopen_obj() to Py_fopen(). The function now also accepts bytes path on Windows. Remove the private, undocumented, and untested function _Py_fopen_obj().
|
Do we need Py_fclose as well? |
Sorry, something went wrong.
fclose seems to be enough, we don't need to wrap it(Unless we use CloseHandle to close the file). |
Sorry, something went wrong.
Py_fopen() adds values to fopen(): accept a Python object, make the file descriptor non-inheritable, raise an exception on error. Py_fclose() would just call fclose() without any additional value? I would prefer to not add it unless we have to, and call directly fclose(). I asked the reporter if Py_fclose() would be needed. To be honest, I don't understand well the Windows DLL issue. From what I understood, to use a FILE* in Python DLL, it should be open in the Python DLL. Otherwise, things can go wrong if the C library version is not exactly the same in two DLLs. But I don't know if it's safe to call fopen() / Py_fopen() in DLL A and call fclose() in DLL B. |
Sorry, something went wrong.
|
PyRun_AnyFileExFlags has "closeit" parameter which I always used. Thank you guys for doing all this. |
Sorry, something went wrong.
Is Py_fclose() needed because of the DLL issue? |
Sorry, something went wrong.
Yes. When you call Py_fopen(), you will get a FILE * from whichever C runtime Python is linked to, which isn't necessarily the same as your own application. So you can only pass it back to the same C runtime - it must only be passed into Python APIs, essentially. So regular fclose might crash (or close a different file), and you need Py_fclose() to make sure it goes back to the right runtime. |
Sorry, something went wrong.
|
Ok, I wanted to make sure that I get the rationale correctly. I added Py_fclose() function and documented that files opened by Py_fopen() must only be closed by Py_fclose(). |
Sorry, something went wrong.
|
Your updated documentation seems a bit snarky. The Py_fclose may be needed on any platform depending on your static linking situation. I see no reason not to just document it as "should be used to close files opened by Py_fopen" and if people manage to use fclose and it works then good for them. |
Sorry, something went wrong.
It's not my intent to be snarky. I just tried to explain why calling fclose() directly can cause issues in practice.
Ok, let's do that. |
Sorry, something went wrong.
Co-authored-by: Steve Dower <steve.dower@microsoft.com>
|
I created capi-workgroup/decisions#51: "Add public Py_fopen() and Py_fclose() functions, and remove private _Py_fopen_obj() function". |
Sorry, something went wrong.
There was a problem hiding this comment.
LGTM in general. I would like to see more tests. The support of the path-like protocol is inconsistent.
Sorry, something went wrong.
| wmode, Py_ARRAY_LENGTH(wmode)); | ||
| if (usize == 0) { | ||
| PyErr_SetFromWindowsErr(0); | ||
| wchar_t wmode[10]; |
There was a problem hiding this comment.
TODO: Add tests for mode: NULL, non-decodable (non-ASCII) mode, too long mode (e.g. "rt+, ccs=UTF-8").
Sorry, something went wrong.
There was a problem hiding this comment.
I added a test for "too long mode" and non-ASCII mode.
Passing NULL does crash. I don't know how to modify the Argument Clinic code to accept NULL.
Sorry, something went wrong.
There was a problem hiding this comment.
You can use "z#" to pass arbitrary sequence of bytes or NULL. In Argument Clinic it is expressed as str(zeroes=True, accept={robuffer, str, NoneType}).
Use the NULLABLE macro for path.
If it crashes, just add a comment # CRASHES with specific call as in other tests as indication that we did not miss such case, but cannot test it.
Sorry, something went wrong.
There was a problem hiding this comment.
If it crashes, just add a comment # CRASHES with specific call as in other tests as indication that we did not miss such case, but cannot test it.
Ok, I added a comment.
Sorry, something went wrong.
Test also non-ASCII mode.
* Skip TESTFN_UNENCODABLE if it's None. * Remove TESTFN_UNDECODABLE test.
|
|
||
| # non-ASCII mode failing with "Invalid argument" | ||
| with self.assertRaises(OSError): | ||
| _testcapi.py_fopen(__file__, "\xe9") |
There was a problem hiding this comment.
"\xe9" is encoded to b'\xc3\xa9'. Please test also with non-UTF-8 bytes. You may get different error on Windows. Actually, it may depend on the locale.
Sorry, something went wrong.
There was a problem hiding this comment.
It's not possible to pass non-UTF-8 bytes, PySys_Audit() decodes the mode from UTF-8 in strict mode:
if (PySys_Audit("open", "Osi", path, mode, 0) < 0) {
return NULL;
}I don't think that it's worth to "support" non-UTF-8 just for the test, whereas it's rejected anyway by fopen().
Sorry, something went wrong.
| wmode, Py_ARRAY_LENGTH(wmode)); | ||
| if (usize == 0) { | ||
| PyErr_SetFromWindowsErr(0); | ||
| wchar_t wmode[10]; |
There was a problem hiding this comment.
You can use "z#" to pass arbitrary sequence of bytes or NULL. In Argument Clinic it is expressed as str(zeroes=True, accept={robuffer, str, NoneType}).
Use the NULLABLE macro for path.
If it crashes, just add a comment # CRASHES with specific call as in other tests as indication that we did not miss such case, but cannot test it.
Sorry, something went wrong.
There was a problem hiding this comment.
Yet more test suggestions.
Sorry, something went wrong.
|
@serhiy-storchaka: I tried to implement all requested tests, but I skipped some of them for practical reasons. On Windows, the file mode is limited to 10 characters. If it's a problem later, I can allocate memory on the heap and write more complicated code to handle longer modes. In practice, we should be fine with this arbitrary limit. |
Sorry, something went wrong.
|
PR merged, thanks for your reviews! @serhiy-storchaka: You can write a follow-up PR if you want to extend the code coverage (add more tests). |
Sorry, something went wrong.
| Back | FazBrowse Home | New Git URL |
Rename _Py_fopen_obj() to Py_fopen(). The function now also accepts bytes path on Windows.
Remove the private, undocumented, and untested function _Py_fopen_obj().
📚 Documentation preview 📚: https://cpython-previews--127821.org.readthedocs.build/