Issue #28586: Converted os.scandir() to Argument Clinic.

This commit is contained in:
Serhiy Storchaka 2016-11-06 13:45:33 +02:00
parent 04230c4087
commit 49d02d1659
2 changed files with 297 additions and 103 deletions

View File

@ -5596,6 +5596,209 @@ exit:
#endif /* defined(MS_WINDOWS) */ #endif /* defined(MS_WINDOWS) */
PyDoc_STRVAR(os_DirEntry_is_symlink__doc__,
"is_symlink($self, /)\n"
"--\n"
"\n"
"Return True if the entry is a symbolic link; cached per entry.");
#define OS_DIRENTRY_IS_SYMLINK_METHODDEF \
{"is_symlink", (PyCFunction)os_DirEntry_is_symlink, METH_NOARGS, os_DirEntry_is_symlink__doc__},
static int
os_DirEntry_is_symlink_impl(DirEntry *self);
static PyObject *
os_DirEntry_is_symlink(DirEntry *self, PyObject *Py_UNUSED(ignored))
{
PyObject *return_value = NULL;
int _return_value;
_return_value = os_DirEntry_is_symlink_impl(self);
if ((_return_value == -1) && PyErr_Occurred()) {
goto exit;
}
return_value = PyBool_FromLong((long)_return_value);
exit:
return return_value;
}
PyDoc_STRVAR(os_DirEntry_stat__doc__,
"stat($self, /, *, follow_symlinks=True)\n"
"--\n"
"\n"
"Return stat_result object for the entry; cached per entry.");
#define OS_DIRENTRY_STAT_METHODDEF \
{"stat", (PyCFunction)os_DirEntry_stat, METH_FASTCALL, os_DirEntry_stat__doc__},
static PyObject *
os_DirEntry_stat_impl(DirEntry *self, int follow_symlinks);
static PyObject *
os_DirEntry_stat(DirEntry *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"follow_symlinks", NULL};
static _PyArg_Parser _parser = {"|$p:stat", _keywords, 0};
int follow_symlinks = 1;
if (!_PyArg_ParseStack(args, nargs, kwnames, &_parser,
&follow_symlinks)) {
goto exit;
}
return_value = os_DirEntry_stat_impl(self, follow_symlinks);
exit:
return return_value;
}
PyDoc_STRVAR(os_DirEntry_is_dir__doc__,
"is_dir($self, /, *, follow_symlinks=True)\n"
"--\n"
"\n"
"Return True if the entry is a directory; cached per entry.");
#define OS_DIRENTRY_IS_DIR_METHODDEF \
{"is_dir", (PyCFunction)os_DirEntry_is_dir, METH_FASTCALL, os_DirEntry_is_dir__doc__},
static int
os_DirEntry_is_dir_impl(DirEntry *self, int follow_symlinks);
static PyObject *
os_DirEntry_is_dir(DirEntry *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"follow_symlinks", NULL};
static _PyArg_Parser _parser = {"|$p:is_dir", _keywords, 0};
int follow_symlinks = 1;
int _return_value;
if (!_PyArg_ParseStack(args, nargs, kwnames, &_parser,
&follow_symlinks)) {
goto exit;
}
_return_value = os_DirEntry_is_dir_impl(self, follow_symlinks);
if ((_return_value == -1) && PyErr_Occurred()) {
goto exit;
}
return_value = PyBool_FromLong((long)_return_value);
exit:
return return_value;
}
PyDoc_STRVAR(os_DirEntry_is_file__doc__,
"is_file($self, /, *, follow_symlinks=True)\n"
"--\n"
"\n"
"Return True if the entry is a file; cached per entry.");
#define OS_DIRENTRY_IS_FILE_METHODDEF \
{"is_file", (PyCFunction)os_DirEntry_is_file, METH_FASTCALL, os_DirEntry_is_file__doc__},
static int
os_DirEntry_is_file_impl(DirEntry *self, int follow_symlinks);
static PyObject *
os_DirEntry_is_file(DirEntry *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"follow_symlinks", NULL};
static _PyArg_Parser _parser = {"|$p:is_file", _keywords, 0};
int follow_symlinks = 1;
int _return_value;
if (!_PyArg_ParseStack(args, nargs, kwnames, &_parser,
&follow_symlinks)) {
goto exit;
}
_return_value = os_DirEntry_is_file_impl(self, follow_symlinks);
if ((_return_value == -1) && PyErr_Occurred()) {
goto exit;
}
return_value = PyBool_FromLong((long)_return_value);
exit:
return return_value;
}
PyDoc_STRVAR(os_DirEntry_inode__doc__,
"inode($self, /)\n"
"--\n"
"\n"
"Return inode of the entry; cached per entry.");
#define OS_DIRENTRY_INODE_METHODDEF \
{"inode", (PyCFunction)os_DirEntry_inode, METH_NOARGS, os_DirEntry_inode__doc__},
static PyObject *
os_DirEntry_inode_impl(DirEntry *self);
static PyObject *
os_DirEntry_inode(DirEntry *self, PyObject *Py_UNUSED(ignored))
{
return os_DirEntry_inode_impl(self);
}
PyDoc_STRVAR(os_DirEntry___fspath____doc__,
"__fspath__($self, /)\n"
"--\n"
"\n"
"Returns the path for the entry.");
#define OS_DIRENTRY___FSPATH___METHODDEF \
{"__fspath__", (PyCFunction)os_DirEntry___fspath__, METH_NOARGS, os_DirEntry___fspath____doc__},
static PyObject *
os_DirEntry___fspath___impl(DirEntry *self);
static PyObject *
os_DirEntry___fspath__(DirEntry *self, PyObject *Py_UNUSED(ignored))
{
return os_DirEntry___fspath___impl(self);
}
PyDoc_STRVAR(os_scandir__doc__,
"scandir($module, /, path=None)\n"
"--\n"
"\n"
"Return an iterator of DirEntry objects for given path.\n"
"\n"
"path can be specified as either str, bytes or path-like object. If path\n"
"is bytes, the names of yielded DirEntry objects will also be bytes; in\n"
"all other circumstances they will be str.\n"
"\n"
"If path is None, uses the path=\'.\'.");
#define OS_SCANDIR_METHODDEF \
{"scandir", (PyCFunction)os_scandir, METH_FASTCALL, os_scandir__doc__},
static PyObject *
os_scandir_impl(PyObject *module, path_t *path);
static PyObject *
os_scandir(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"path", NULL};
static _PyArg_Parser _parser = {"|O&:scandir", _keywords, 0};
path_t path = PATH_T_INITIALIZE("scandir", "path", 1, 0);
if (!_PyArg_ParseStack(args, nargs, kwnames, &_parser,
path_converter, &path)) {
goto exit;
}
return_value = os_scandir_impl(module, &path);
exit:
/* Cleanup for path */
path_cleanup(&path);
return return_value;
}
PyDoc_STRVAR(os_fspath__doc__, PyDoc_STRVAR(os_fspath__doc__,
"fspath($module, /, path)\n" "fspath($module, /, path)\n"
"--\n" "--\n"
@ -6148,4 +6351,4 @@ exit:
#ifndef OS_GETRANDOM_METHODDEF #ifndef OS_GETRANDOM_METHODDEF
#define OS_GETRANDOM_METHODDEF #define OS_GETRANDOM_METHODDEF
#endif /* !defined(OS_GETRANDOM_METHODDEF) */ #endif /* !defined(OS_GETRANDOM_METHODDEF) */
/*[clinic end generated code: output=b9ed5703d2feb0d9 input=a9049054013a1b77]*/ /*[clinic end generated code: output=e4a3bd36c7bb8356 input=a9049054013a1b77]*/

View File

@ -11092,10 +11092,10 @@ posix_set_blocking(PyObject *self, PyObject *args)
#endif /* !MS_WINDOWS */ #endif /* !MS_WINDOWS */
PyDoc_STRVAR(posix_scandir__doc__, /*[clinic input]
"scandir(path='.') -> iterator of DirEntry objects for given path"); class os.DirEntry "DirEntry *" "&DirEntryType"
[clinic start generated code]*/
static char *follow_symlinks_keywords[] = {"follow_symlinks", NULL}; /*[clinic end generated code: output=da39a3ee5e6b4b0d input=3138f09f7c683f1d]*/
typedef struct { typedef struct {
PyObject_HEAD PyObject_HEAD
@ -11129,9 +11129,15 @@ DirEntry_dealloc(DirEntry *entry)
static int static int
DirEntry_test_mode(DirEntry *self, int follow_symlinks, unsigned short mode_bits); DirEntry_test_mode(DirEntry *self, int follow_symlinks, unsigned short mode_bits);
/* Set exception and return -1 on error, 0 for False, 1 for True */ /*[clinic input]
os.DirEntry.is_symlink -> bool
Return True if the entry is a symbolic link; cached per entry.
[clinic start generated code]*/
static int static int
DirEntry_is_symlink(DirEntry *self) os_DirEntry_is_symlink_impl(DirEntry *self)
/*[clinic end generated code: output=42244667d7bcfc25 input=1605a1b4b96976c3]*/
{ {
#ifdef MS_WINDOWS #ifdef MS_WINDOWS
return (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK; return (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
@ -11147,17 +11153,6 @@ DirEntry_is_symlink(DirEntry *self)
#endif #endif
} }
static PyObject *
DirEntry_py_is_symlink(DirEntry *self)
{
int result;
result = DirEntry_is_symlink(self);
if (result == -1)
return NULL;
return PyBool_FromLong(result);
}
static PyObject * static PyObject *
DirEntry_fetch_stat(DirEntry *self, int follow_symlinks) DirEntry_fetch_stat(DirEntry *self, int follow_symlinks)
{ {
@ -11200,14 +11195,23 @@ DirEntry_get_lstat(DirEntry *self)
return self->lstat; return self->lstat;
} }
/*[clinic input]
os.DirEntry.stat
*
follow_symlinks: bool = True
Return stat_result object for the entry; cached per entry.
[clinic start generated code]*/
static PyObject * static PyObject *
DirEntry_get_stat(DirEntry *self, int follow_symlinks) os_DirEntry_stat_impl(DirEntry *self, int follow_symlinks)
/*[clinic end generated code: output=008593b3a6d01305 input=280d14c1d6f1d00d]*/
{ {
if (!follow_symlinks) if (!follow_symlinks)
return DirEntry_get_lstat(self); return DirEntry_get_lstat(self);
if (!self->stat) { if (!self->stat) {
int result = DirEntry_is_symlink(self); int result = os_DirEntry_is_symlink_impl(self);
if (result == -1) if (result == -1)
return NULL; return NULL;
else if (result) else if (result)
@ -11220,18 +11224,6 @@ DirEntry_get_stat(DirEntry *self, int follow_symlinks)
return self->stat; return self->stat;
} }
static PyObject *
DirEntry_stat(DirEntry *self, PyObject *args, PyObject *kwargs)
{
int follow_symlinks = 1;
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|$p:DirEntry.stat",
follow_symlinks_keywords, &follow_symlinks))
return NULL;
return DirEntry_get_stat(self, follow_symlinks);
}
/* Set exception and return -1 on error, 0 for False, 1 for True */ /* Set exception and return -1 on error, 0 for False, 1 for True */
static int static int
DirEntry_test_mode(DirEntry *self, int follow_symlinks, unsigned short mode_bits) DirEntry_test_mode(DirEntry *self, int follow_symlinks, unsigned short mode_bits)
@ -11260,7 +11252,7 @@ DirEntry_test_mode(DirEntry *self, int follow_symlinks, unsigned short mode_bits
#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE) #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
if (need_stat) { if (need_stat) {
#endif #endif
stat = DirEntry_get_stat(self, follow_symlinks); stat = os_DirEntry_stat_impl(self, follow_symlinks);
if (!stat) { if (!stat) {
if (PyErr_ExceptionMatches(PyExc_FileNotFoundError)) { if (PyErr_ExceptionMatches(PyExc_FileNotFoundError)) {
/* If file doesn't exist (anymore), then return False /* If file doesn't exist (anymore), then return False
@ -11311,43 +11303,45 @@ error:
return -1; return -1;
} }
static PyObject * /*[clinic input]
DirEntry_py_test_mode(DirEntry *self, int follow_symlinks, unsigned short mode_bits) os.DirEntry.is_dir -> bool
{ *
int result; follow_symlinks: bool = True
result = DirEntry_test_mode(self, follow_symlinks, mode_bits); Return True if the entry is a directory; cached per entry.
if (result == -1) [clinic start generated code]*/
return NULL;
return PyBool_FromLong(result); static int
os_DirEntry_is_dir_impl(DirEntry *self, int follow_symlinks)
/*[clinic end generated code: output=ad2e8d54365da287 input=0135232766f53f58]*/
{
return DirEntry_test_mode(self, follow_symlinks, S_IFDIR);
} }
static PyObject * /*[clinic input]
DirEntry_is_dir(DirEntry *self, PyObject *args, PyObject *kwargs) os.DirEntry.is_file -> bool
*
follow_symlinks: bool = True
Return True if the entry is a file; cached per entry.
[clinic start generated code]*/
static int
os_DirEntry_is_file_impl(DirEntry *self, int follow_symlinks)
/*[clinic end generated code: output=8462ade481d8a476 input=0dc90be168b041ee]*/
{ {
int follow_symlinks = 1; return DirEntry_test_mode(self, follow_symlinks, S_IFREG);
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|$p:DirEntry.is_dir",
follow_symlinks_keywords, &follow_symlinks))
return NULL;
return DirEntry_py_test_mode(self, follow_symlinks, S_IFDIR);
} }
static PyObject * /*[clinic input]
DirEntry_is_file(DirEntry *self, PyObject *args, PyObject *kwargs) os.DirEntry.inode
{
int follow_symlinks = 1;
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|$p:DirEntry.is_file", Return inode of the entry; cached per entry.
follow_symlinks_keywords, &follow_symlinks)) [clinic start generated code]*/
return NULL;
return DirEntry_py_test_mode(self, follow_symlinks, S_IFREG);
}
static PyObject * static PyObject *
DirEntry_inode(DirEntry *self) os_DirEntry_inode_impl(DirEntry *self)
/*[clinic end generated code: output=156bb3a72162440e input=3ee7b872ae8649f0]*/
{ {
#ifdef MS_WINDOWS #ifdef MS_WINDOWS
if (!self->got_file_index) { if (!self->got_file_index) {
@ -11384,8 +11378,15 @@ DirEntry_repr(DirEntry *self)
return PyUnicode_FromFormat("<DirEntry %R>", self->name); return PyUnicode_FromFormat("<DirEntry %R>", self->name);
} }
/*[clinic input]
os.DirEntry.__fspath__
Returns the path for the entry.
[clinic start generated code]*/
static PyObject * static PyObject *
DirEntry_fspath(DirEntry *self) os_DirEntry___fspath___impl(DirEntry *self)
/*[clinic end generated code: output=6dd7f7ef752e6f4f input=3c49d0cf38df4fac]*/
{ {
Py_INCREF(self->path); Py_INCREF(self->path);
return self->path; return self->path;
@ -11399,25 +11400,15 @@ static PyMemberDef DirEntry_members[] = {
{NULL} {NULL}
}; };
#include "clinic/posixmodule.c.h"
static PyMethodDef DirEntry_methods[] = { static PyMethodDef DirEntry_methods[] = {
{"is_dir", (PyCFunction)DirEntry_is_dir, METH_VARARGS | METH_KEYWORDS, OS_DIRENTRY_IS_DIR_METHODDEF
"return True if the entry is a directory; cached per entry" OS_DIRENTRY_IS_FILE_METHODDEF
}, OS_DIRENTRY_IS_SYMLINK_METHODDEF
{"is_file", (PyCFunction)DirEntry_is_file, METH_VARARGS | METH_KEYWORDS, OS_DIRENTRY_STAT_METHODDEF
"return True if the entry is a file; cached per entry" OS_DIRENTRY_INODE_METHODDEF
}, OS_DIRENTRY___FSPATH___METHODDEF
{"is_symlink", (PyCFunction)DirEntry_py_is_symlink, METH_NOARGS,
"return True if the entry is a symbolic link; cached per entry"
},
{"stat", (PyCFunction)DirEntry_stat, METH_VARARGS | METH_KEYWORDS,
"return stat_result object for the entry; cached per entry"
},
{"inode", (PyCFunction)DirEntry_inode, METH_NOARGS,
"return inode of the entry; cached per entry",
},
{"__fspath__", (PyCFunction)DirEntry_fspath, METH_NOARGS,
"returns the path for the entry",
},
{NULL} {NULL}
}; };
@ -11890,23 +11881,34 @@ static PyTypeObject ScandirIteratorType = {
(destructor)ScandirIterator_finalize, /* tp_finalize */ (destructor)ScandirIterator_finalize, /* tp_finalize */
}; };
/*[clinic input]
os.scandir
path : path_t(nullable=True) = None
Return an iterator of DirEntry objects for given path.
path can be specified as either str, bytes or path-like object. If path
is bytes, the names of yielded DirEntry objects will also be bytes; in
all other circumstances they will be str.
If path is None, uses the path='.'.
[clinic start generated code]*/
static PyObject * static PyObject *
posix_scandir(PyObject *self, PyObject *args, PyObject *kwargs) os_scandir_impl(PyObject *module, path_t *path)
/*[clinic end generated code: output=6eb2668b675ca89e input=e62b08b3cd41f604]*/
{ {
ScandirIterator *iterator; ScandirIterator *iterator;
static char *keywords[] = {"path", NULL};
#ifdef MS_WINDOWS #ifdef MS_WINDOWS
wchar_t *path_strW; wchar_t *path_strW;
#else #else
const char *path; const char *path_str;
#endif #endif
iterator = PyObject_New(ScandirIterator, &ScandirIteratorType); iterator = PyObject_New(ScandirIterator, &ScandirIteratorType);
if (!iterator) if (!iterator)
return NULL; return NULL;
memset(&iterator->path, 0, sizeof(path_t));
iterator->path.function_name = "scandir";
iterator->path.nullable = 1;
#ifdef MS_WINDOWS #ifdef MS_WINDOWS
iterator->handle = INVALID_HANDLE_VALUE; iterator->handle = INVALID_HANDLE_VALUE;
@ -11914,15 +11916,13 @@ posix_scandir(PyObject *self, PyObject *args, PyObject *kwargs)
iterator->dirp = NULL; iterator->dirp = NULL;
#endif #endif
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O&:scandir", keywords, memcpy(&iterator->path, path, sizeof(path_t));
path_converter, &iterator->path))
goto error;
/* path_converter doesn't keep path.object around, so do it /* path_converter doesn't keep path.object around, so do it
manually for the lifetime of the iterator here (the refcount manually for the lifetime of the iterator here (the refcount
is decremented in ScandirIterator_dealloc) is decremented in ScandirIterator_dealloc)
*/ */
Py_XINCREF(iterator->path.object); Py_XINCREF(iterator->path.object);
Py_XINCREF(iterator->path.cleanup);
#ifdef MS_WINDOWS #ifdef MS_WINDOWS
iterator->first_time = 1; iterator->first_time = 1;
@ -11943,13 +11943,13 @@ posix_scandir(PyObject *self, PyObject *args, PyObject *kwargs)
} }
#else /* POSIX */ #else /* POSIX */
if (iterator->path.narrow) if (iterator->path.narrow)
path = iterator->path.narrow; path_str = iterator->path.narrow;
else else
path = "."; path_str = ".";
errno = 0; errno = 0;
Py_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS
iterator->dirp = opendir(path); iterator->dirp = opendir(path_str);
Py_END_ALLOW_THREADS Py_END_ALLOW_THREADS
if (!iterator->dirp) { if (!iterator->dirp) {
@ -12092,13 +12092,6 @@ error:
} }
#endif /* HAVE_GETRANDOM_SYSCALL */ #endif /* HAVE_GETRANDOM_SYSCALL */
#include "clinic/posixmodule.c.h"
/*[clinic input]
dump buffer
[clinic start generated code]*/
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=524ce2e021e4eba6]*/
static PyMethodDef posix_methods[] = { static PyMethodDef posix_methods[] = {
@ -12288,9 +12281,7 @@ static PyMethodDef posix_methods[] = {
{"get_blocking", posix_get_blocking, METH_VARARGS, get_blocking__doc__}, {"get_blocking", posix_get_blocking, METH_VARARGS, get_blocking__doc__},
{"set_blocking", posix_set_blocking, METH_VARARGS, set_blocking__doc__}, {"set_blocking", posix_set_blocking, METH_VARARGS, set_blocking__doc__},
#endif #endif
{"scandir", (PyCFunction)posix_scandir, OS_SCANDIR_METHODDEF
METH_VARARGS | METH_KEYWORDS,
posix_scandir__doc__},
OS_FSPATH_METHODDEF OS_FSPATH_METHODDEF
OS_GETRANDOM_METHODDEF OS_GETRANDOM_METHODDEF
{NULL, NULL} /* Sentinel */ {NULL, NULL} /* Sentinel */