Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit fdaea06

Browse files
committed
Issue #15176: Clarified behavior, documentation, and implementation
of os.listdir().
1 parent 3b52778 commit fdaea06

4 files changed

Lines changed: 46 additions & 26 deletions

File tree

Doc/library/os.rst

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1488,16 +1488,19 @@ features:
14881488
.. function:: listdir(path='.')
14891489

14901490
Return a list containing the names of the entries in the directory given by
1491-
*path* (default: ``'.'``). The list is in arbitrary order. It does not
1492-
include the special entries ``'.'`` and ``'..'`` even if they are present in
1493-
the directory.
1491+
*path*. The list is in arbitrary order, and does not include the special
1492+
entries ``'.'`` and ``'..'`` even if they are present in the directory.
14941493

1495-
This function can be called with a bytes or string argument, and returns
1496-
filenames of the same datatype.
1494+
*path* may be either of type ``str`` or of type ``bytes``. If *path*
1495+
is of type ``bytes``, the filenames returned will also be of type ``bytes``;
1496+
in all other circumstances, they will be of type ``str``.
14971497

14981498
This function can also support :ref:`specifying a file descriptor
14991499
<path_fd>`; the file descriptor must refer to a directory.
15001500

1501+
.. note::
1502+
To encode ``str`` filenames to ``bytes``, use :func:`~os.fsencode`.
1503+
15011504
Availability: Unix, Windows.
15021505

15031506
.. versionchanged:: 3.2

Lib/test/test_posix.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -448,16 +448,21 @@ def test_chdir(self):
448448
self.assertRaises(OSError, posix.chdir, support.TESTFN)
449449

450450
def test_listdir(self):
451-
if hasattr(posix, 'listdir'):
452-
self.assertTrue(support.TESTFN in posix.listdir(os.curdir))
451+
self.assertTrue(support.TESTFN in posix.listdir(os.curdir))
453452

454453
def test_listdir_default(self):
455-
# When listdir is called without argument, it's the same as listdir(os.curdir)
456-
if hasattr(posix, 'listdir'):
457-
self.assertTrue(support.TESTFN in posix.listdir())
458-
459-
@unittest.skipUnless(os.listdir in os.supports_fd, "test needs fd support for os.listdir()")
460-
def test_flistdir(self):
454+
# When listdir is called without argument,
455+
# it's the same as listdir(os.curdir).
456+
self.assertTrue(support.TESTFN in posix.listdir())
457+
458+
def test_listdir_bytes(self):
459+
# When listdir is called with a bytes object,
460+
# the returned strings are of type bytes.
461+
self.assertTrue(os.fsencode(support.TESTFN) in posix.listdir(b'.'))
462+
463+
@unittest.skipUnless(posix.listdir in os.supports_fd,
464+
"test needs fd support for posix.listdir()")
465+
def test_listdir_fd(self):
461466
f = posix.open(posix.getcwd(), posix.O_RDONLY)
462467
self.addCleanup(posix.close, f)
463468
self.assertEqual(

Misc/NEWS

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

62+
- Issue #15176: Clarified behavior, documentation, and implementation
63+
of os.listdir().
64+
6265
- Issue #15164: Change return value of platform.uname() from a
6366
plain tuple to a collections.namedtuple.
6467

Modules/posixmodule.c

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3272,14 +3272,16 @@ posix_link(PyObject *self, PyObject *args, PyObject *kwargs)
32723272

32733273

32743274
PyDoc_STRVAR(posix_listdir__doc__,
3275-
"listdir(path='.') -> list_of_strings\n\n\
3276-
Return a list containing the names of the entries in the directory.\n\
3277-
\n\
3275+
"listdir(path='.') -> list_of_filenames\n\n\
3276+
Return a list containing the names of the files in the directory.\n\
32783277
The list is in arbitrary order. It does not include the special\n\
32793278
entries '.' and '..' even if they are present in the directory.\n\
32803279
\n\
3281-
path can always be specified as a string.\n\
3282-
On some platforms, path may also be specified as an open file descriptor.\n\
3280+
path can be specified as either str or bytes. If path is bytes,\n\
3281+
the filenames returned will also be bytes; in all other circumstances\n\
3282+
the filenames returned will be str.\n\
3283+
On some platforms, path may also be specified as an open file descriptor;\n\
3284+
the file descriptor must refer to a directory.\n\
32833285
If this functionality is unavailable, using it raises NotImplementedError.");
32843286

32853287
static PyObject *
@@ -3316,7 +3318,7 @@ posix_listdir(PyObject *self, PyObject *args, PyObject *kwargs)
33163318
PyObject *v;
33173319
DIR *dirp = NULL;
33183320
struct dirent *ep;
3319-
int arg_is_unicode = 1;
3321+
int return_str; /* if false, return bytes */
33203322
#endif
33213323

33223324
memset(&path, 0, sizeof(path));
@@ -3538,11 +3540,6 @@ posix_listdir(PyObject *self, PyObject *args, PyObject *kwargs)
35383540
#else
35393541

35403542
errno = 0;
3541-
/* v is never read, so it does not need to be initialized yet. */
3542-
if (path.narrow && !PyArg_ParseTuple(args, "U:listdir", &v)) {
3543-
arg_is_unicode = 0;
3544-
PyErr_Clear();
3545-
}
35463543
#ifdef HAVE_FDOPENDIR
35473544
if (path.fd != -1) {
35483545
/* closedir() closes the FD, so we duplicate it */
@@ -3555,14 +3552,26 @@ posix_listdir(PyObject *self, PyObject *args, PyObject *kwargs)
35553552
goto exit;
35563553
}
35573554

3555+
return_str = 1;
3556+
35583557
Py_BEGIN_ALLOW_THREADS
35593558
dirp = fdopendir(fd);
35603559
Py_END_ALLOW_THREADS
35613560
}
35623561
else
35633562
#endif
35643563
{
3565-
char *name = path.narrow ? path.narrow : ".";
3564+
char *name;
3565+
if (path.narrow) {
3566+
name = path.narrow;
3567+
/* only return bytes if they specified a bytes object */
3568+
return_str = !(PyBytes_Check(path.object));
3569+
}
3570+
else {
3571+
name = ".";
3572+
return_str = 1;
3573+
}
3574+
35663575
Py_BEGIN_ALLOW_THREADS
35673576
dirp = opendir(name);
35683577
Py_END_ALLOW_THREADS
@@ -3593,7 +3602,7 @@ posix_listdir(PyObject *self, PyObject *args, PyObject *kwargs)
35933602
(NAMLEN(ep) == 1 ||
35943603
(ep->d_name[1] == '.' && NAMLEN(ep) == 2)))
35953604
continue;
3596-
if (arg_is_unicode)
3605+
if (return_str)
35973606
v = PyUnicode_DecodeFSDefaultAndSize(ep->d_name, NAMLEN(ep));
35983607
else
35993608
v = PyBytes_FromStringAndSize(ep->d_name, NAMLEN(ep));

0 commit comments

Comments
 (0)