Skip to content

Commit 1180e5a

Browse files
bpo-30879: os.listdir() and os.scandir() now emit bytes names when (#2634)
called with bytes-like argument.
1 parent 4f9a446 commit 1180e5a

File tree

4 files changed

+35
-6
lines changed

4 files changed

+35
-6
lines changed

Lib/test/test_os.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3420,6 +3420,22 @@ def test_bytes(self):
34203420
self.assertEqual(entry.path,
34213421
os.fsencode(os.path.join(self.path, 'file.txt')))
34223422

3423+
def test_bytes_like(self):
3424+
self.create_file("file.txt")
3425+
3426+
for cls in bytearray, memoryview:
3427+
path_bytes = cls(os.fsencode(self.path))
3428+
with self.assertWarns(DeprecationWarning):
3429+
entries = list(os.scandir(path_bytes))
3430+
self.assertEqual(len(entries), 1, entries)
3431+
entry = entries[0]
3432+
3433+
self.assertEqual(entry.name, b'file.txt')
3434+
self.assertEqual(entry.path,
3435+
os.fsencode(os.path.join(self.path, 'file.txt')))
3436+
self.assertIs(type(entry.name), bytes)
3437+
self.assertIs(type(entry.path), bytes)
3438+
34233439
@unittest.skipUnless(os.listdir in os.supports_fd,
34243440
'fd support for listdir required for this test.')
34253441
def test_fd(self):

Lib/test/test_posix.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -643,17 +643,25 @@ def test_chdir(self):
643643
self.assertRaises(OSError, posix.chdir, support.TESTFN)
644644

645645
def test_listdir(self):
646-
self.assertTrue(support.TESTFN in posix.listdir(os.curdir))
646+
self.assertIn(support.TESTFN, posix.listdir(os.curdir))
647647

648648
def test_listdir_default(self):
649649
# When listdir is called without argument,
650650
# it's the same as listdir(os.curdir).
651-
self.assertTrue(support.TESTFN in posix.listdir())
651+
self.assertIn(support.TESTFN, posix.listdir())
652652

653653
def test_listdir_bytes(self):
654654
# When listdir is called with a bytes object,
655655
# the returned strings are of type bytes.
656-
self.assertTrue(os.fsencode(support.TESTFN) in posix.listdir(b'.'))
656+
self.assertIn(os.fsencode(support.TESTFN), posix.listdir(b'.'))
657+
658+
def test_listdir_bytes_like(self):
659+
for cls in bytearray, memoryview:
660+
with self.assertWarns(DeprecationWarning):
661+
names = posix.listdir(cls(b'.'))
662+
self.assertIn(os.fsencode(support.TESTFN), names)
663+
for name in names:
664+
self.assertIs(type(name), bytes)
657665

658666
@unittest.skipUnless(posix.listdir in os.supports_fd,
659667
"test needs fd support for posix.listdir()")

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,9 @@ Extension Modules
376376
Library
377377
-------
378378

379+
- bpo-30879: os.listdir() and os.scandir() now emit bytes names when called
380+
with bytes-like argument.
381+
379382
- bpo-30746: Prohibited the '=' character in environment variable names in
380383
``os.putenv()`` and ``os.spawn*()``.
381384

Modules/posixmodule.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1037,6 +1037,8 @@ path_converter(PyObject *o, void *p)
10371037
Py_INCREF(bytes);
10381038
}
10391039
else if (is_buffer) {
1040+
/* XXX Replace PyObject_CheckBuffer with PyBytes_Check in other code
1041+
after removing suport of non-bytes buffer objects. */
10401042
if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
10411043
"%s%s%s should be %s, not %.200s",
10421044
path->function_name ? path->function_name : "",
@@ -3588,8 +3590,8 @@ _posix_listdir(path_t *path, PyObject *list)
35883590
const char *name;
35893591
if (path->narrow) {
35903592
name = path->narrow;
3591-
/* only return bytes if they specified a bytes object */
3592-
return_str = !(PyBytes_Check(path->object));
3593+
/* only return bytes if they specified a bytes-like object */
3594+
return_str = !PyObject_CheckBuffer(path->object);
35933595
}
35943596
else {
35953597
name = ".";
@@ -11842,7 +11844,7 @@ DirEntry_from_posix_info(path_t *path, const char *name, Py_ssize_t name_len,
1184211844
goto error;
1184311845
}
1184411846

11845-
if (!path->narrow || !PyBytes_Check(path->object)) {
11847+
if (!path->narrow || !PyObject_CheckBuffer(path->object)) {
1184611848
entry->name = PyUnicode_DecodeFSDefaultAndSize(name, name_len);
1184711849
if (joined_path)
1184811850
entry->path = PyUnicode_DecodeFSDefault(joined_path);

0 commit comments

Comments
 (0)