Skip to content

Commit 5b52a4e

Browse files
committed
Support __fspath__() protocol on Windows
Test also non-ASCII mode.
1 parent a8c26b2 commit 5b52a4e

File tree

2 files changed

+29
-10
lines changed

2 files changed

+29
-10
lines changed

Lib/test/test_capi/test_file.py

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,23 @@
99
class CAPIFileTest(unittest.TestCase):
1010
def test_py_fopen(self):
1111
# Test Py_fopen() and Py_fclose()
12+
class FSPath:
13+
def __init__(self, path):
14+
self.path = path
15+
def __fspath__(self):
16+
return self.path
17+
18+
with open(__file__, "rb") as fp:
19+
source = fp.read()
20+
1221
for filename in (__file__, os.fsencode(__file__)):
1322
with self.subTest(filename=filename):
14-
content = _testcapi.py_fopen(filename, "rb")
15-
with open(filename, "rb") as fp:
16-
self.assertEqual(fp.read(256), content)
23+
data = _testcapi.py_fopen(filename, "rb")
24+
self.assertEqual(data, source[:256])
25+
26+
data = _testcapi.py_fopen(FSPath(filename), "rb")
27+
self.assertEqual(data, source[:256])
1728

18-
with open(__file__, "rb") as fp:
19-
content = fp.read()
2029
for filename in (
2130
os_helper.TESTFN,
2231
os.fsencode(os_helper.TESTFN),
@@ -26,11 +35,10 @@ def test_py_fopen(self):
2635
with self.subTest(filename=filename):
2736
try:
2837
with open(filename, "wb") as fp:
29-
fp.write(content)
38+
fp.write(source)
3039

31-
content = _testcapi.py_fopen(filename, "rb")
32-
with open(filename, "rb") as fp:
33-
self.assertEqual(fp.read(256), content[:256])
40+
data = _testcapi.py_fopen(filename, "rb")
41+
self.assertEqual(data, source[:256])
3442
finally:
3543
os_helper.unlink(filename)
3644

@@ -40,10 +48,15 @@ def test_py_fopen(self):
4048
with self.assertRaises(ValueError):
4149
_testcapi.py_fopen(b"a\x00b", "rb")
4250

51+
# non-ASCII mode failing with "Invalid argument"
52+
with self.assertRaises(OSError):
53+
_testcapi.py_fopen(__file__, "\xe9")
54+
55+
# invalid filename type
4356
for invalid_type in (123, object()):
4457
with self.subTest(filename=invalid_type):
4558
with self.assertRaises(TypeError):
46-
_testcapi.py_fopen(invalid_type, "r")
59+
_testcapi.py_fopen(invalid_type, "rb")
4760

4861
if support.MS_WINDOWS:
4962
with self.assertRaises(OSError):

Python/fileutils.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1776,6 +1776,12 @@ Py_fopen(PyObject *path, const char *mode)
17761776
int async_err = 0;
17771777
int saved_errno;
17781778
#ifdef MS_WINDOWS
1779+
PyObject *fspath = PyOS_FSPath(arg);
1780+
if (fspath == NULL) {
1781+
return NULL;
1782+
}
1783+
Py_SETREF(path, fspath);
1784+
17791785
if (PyUnicode_Check(path)) {
17801786
wchar_t *wpath = PyUnicode_AsWideCharString(path, NULL);
17811787
if (wpath == NULL) {

0 commit comments

Comments
 (0)