Skip to content

Commit ecfe4f6

Browse files
[3.6] bpo-30879: os.listdir() and os.scandir() now emit bytes names when (GH-2634) (#2656)
called with bytes-like argument.. (cherry picked from commit 1180e5a)
1 parent fe6e686 commit ecfe4f6

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
@@ -3402,6 +3402,22 @@ def test_bytes(self):
34023402
self.assertEqual(entry.path,
34033403
os.fsencode(os.path.join(self.path, 'file.txt')))
34043404

3405+
def test_bytes_like(self):
3406+
self.create_file("file.txt")
3407+
3408+
for cls in bytearray, memoryview:
3409+
path_bytes = cls(os.fsencode(self.path))
3410+
with self.assertWarns(DeprecationWarning):
3411+
entries = list(os.scandir(path_bytes))
3412+
self.assertEqual(len(entries), 1, entries)
3413+
entry = entries[0]
3414+
3415+
self.assertEqual(entry.name, b'file.txt')
3416+
self.assertEqual(entry.path,
3417+
os.fsencode(os.path.join(self.path, 'file.txt')))
3418+
self.assertIs(type(entry.name), bytes)
3419+
self.assertIs(type(entry.path), bytes)
3420+
34053421
def test_empty_path(self):
34063422
self.assertRaises(FileNotFoundError, os.scandir, '')
34073423

Lib/test/test_posix.py

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

583583
def test_listdir(self):
584-
self.assertTrue(support.TESTFN in posix.listdir(os.curdir))
584+
self.assertIn(support.TESTFN, posix.listdir(os.curdir))
585585

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

591591
def test_listdir_bytes(self):
592592
# When listdir is called with a bytes object,
593593
# the returned strings are of type bytes.
594-
self.assertTrue(os.fsencode(support.TESTFN) in posix.listdir(b'.'))
594+
self.assertIn(os.fsencode(support.TESTFN), posix.listdir(b'.'))
595+
596+
def test_listdir_bytes_like(self):
597+
for cls in bytearray, memoryview:
598+
with self.assertWarns(DeprecationWarning):
599+
names = posix.listdir(cls(b'.'))
600+
self.assertIn(os.fsencode(support.TESTFN), names)
601+
for name in names:
602+
self.assertIs(type(name), bytes)
595603

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

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ Core and Builtins
1818
Library
1919
-------
2020

21+
- bpo-30879: os.listdir() and os.scandir() now emit bytes names when called
22+
with bytes-like argument.
23+
2124
- bpo-30746: Prohibited the '=' character in environment variable names in
2225
``os.putenv()`` and ``os.spawn*()``.
2326

Modules/posixmodule.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -949,6 +949,8 @@ path_converter(PyObject *o, void *p)
949949
Py_INCREF(bytes);
950950
}
951951
else if (is_buffer) {
952+
/* XXX Replace PyObject_CheckBuffer with PyBytes_Check in other code
953+
after removing suport of non-bytes buffer objects. */
952954
if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
953955
"%s%s%s should be %s, not %.200s",
954956
path->function_name ? path->function_name : "",
@@ -3511,8 +3513,8 @@ _posix_listdir(path_t *path, PyObject *list)
35113513
const char *name;
35123514
if (path->narrow) {
35133515
name = path->narrow;
3514-
/* only return bytes if they specified a bytes object */
3515-
return_str = !(PyBytes_Check(path->object));
3516+
/* only return bytes if they specified a bytes-like object */
3517+
return_str = !PyObject_CheckBuffer(path->object);
35163518
}
35173519
else {
35183520
name = ".";
@@ -11708,7 +11710,7 @@ DirEntry_from_posix_info(path_t *path, const char *name, Py_ssize_t name_len,
1170811710
if (!joined_path)
1170911711
goto error;
1171011712

11711-
if (!path->narrow || !PyBytes_Check(path->object)) {
11713+
if (!path->narrow || !PyObject_CheckBuffer(path->object)) {
1171211714
entry->name = PyUnicode_DecodeFSDefaultAndSize(name, name_len);
1171311715
entry->path = PyUnicode_DecodeFSDefault(joined_path);
1171411716
}

0 commit comments

Comments
 (0)