Skip to content

Commit 7527c32

Browse files
[3.5] bpo-30879: os.listdir() and os.scandir() now emit bytes names when (GH-2634) (#2657)
called with bytes-like argument. (cherry picked from commit 1180e5a)
1 parent 7f567e7 commit 7527c32

File tree

4 files changed

+39
-6
lines changed

4 files changed

+39
-6
lines changed

Lib/test/test_os.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3185,6 +3185,28 @@ def test_bytes(self):
31853185
self.assertEqual(entry.path,
31863186
os.fsencode(os.path.join(self.path, 'file.txt')))
31873187

3188+
def test_bytes_like(self):
3189+
if os.name == "nt":
3190+
# On Windows, os.scandir(bytes) must raise an exception
3191+
for cls in bytearray, memoryview:
3192+
self.assertRaises(TypeError, os.scandir, cls(b'.'))
3193+
return
3194+
3195+
# Deprecated in 3.6.
3196+
self.create_file("file.txt")
3197+
3198+
for cls in bytearray, memoryview:
3199+
path_bytes = cls(os.fsencode(self.path))
3200+
entries = list(os.scandir(path_bytes))
3201+
self.assertEqual(len(entries), 1, entries)
3202+
entry = entries[0]
3203+
3204+
self.assertEqual(entry.name, b'file.txt')
3205+
self.assertEqual(entry.path,
3206+
os.fsencode(os.path.join(self.path, 'file.txt')))
3207+
self.assertIs(type(entry.name), bytes)
3208+
self.assertIs(type(entry.path), bytes)
3209+
31883210
def test_empty_path(self):
31893211
self.assertRaises(FileNotFoundError, os.scandir, '')
31903212

Lib/test/test_posix.py

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

579579
def test_listdir(self):
580-
self.assertTrue(support.TESTFN in posix.listdir(os.curdir))
580+
self.assertIn(support.TESTFN, posix.listdir(os.curdir))
581581

582582
def test_listdir_default(self):
583583
# When listdir is called without argument,
584584
# it's the same as listdir(os.curdir).
585-
self.assertTrue(support.TESTFN in posix.listdir())
585+
self.assertIn(support.TESTFN, posix.listdir())
586586

587587
def test_listdir_bytes(self):
588588
# When listdir is called with a bytes object,
589589
# the returned strings are of type bytes.
590-
self.assertTrue(os.fsencode(support.TESTFN) in posix.listdir(b'.'))
590+
self.assertIn(os.fsencode(support.TESTFN), posix.listdir(b'.'))
591+
592+
def test_listdir_bytes_like(self):
593+
# Deprecated in 3.6.
594+
for cls in bytearray, memoryview:
595+
names = posix.listdir(cls(b'.'))
596+
self.assertIn(os.fsencode(support.TESTFN), names)
597+
for name in names:
598+
self.assertIs(type(name), bytes)
591599

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

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ Extension Modules
5959
Library
6060
-------
6161

62+
- bpo-30879: os.listdir() and os.scandir() now emit bytes names when called
63+
with bytes-like argument.
64+
6265
- bpo-30746: Prohibited the '=' character in environment variable names in
6366
``os.putenv()`` and ``os.spawn*()``.
6467

Modules/posixmodule.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3642,8 +3642,8 @@ _posix_listdir(path_t *path, PyObject *list)
36423642
char *name;
36433643
if (path->narrow) {
36443644
name = path->narrow;
3645-
/* only return bytes if they specified a bytes object */
3646-
return_str = !(PyBytes_Check(path->object));
3645+
/* only return bytes if they specified a bytes-like object */
3646+
return_str = !PyObject_CheckBuffer(path->object);
36473647
}
36483648
else {
36493649
name = ".";
@@ -11960,7 +11960,7 @@ DirEntry_from_posix_info(path_t *path, char *name, Py_ssize_t name_len,
1196011960
if (!joined_path)
1196111961
goto error;
1196211962

11963-
if (!path->narrow || !PyBytes_Check(path->object)) {
11963+
if (!path->narrow || !PyObject_CheckBuffer(path->object)) {
1196411964
entry->name = PyUnicode_DecodeFSDefaultAndSize(name, name_len);
1196511965
entry->path = PyUnicode_DecodeFSDefault(joined_path);
1196611966
}

0 commit comments

Comments
 (0)