From 49d02d1659b4b642757aff5aab8dc3fa668a8bd2 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sun, 6 Nov 2016 13:45:33 +0200 Subject: Issue #28586: Converted os.scandir() to Argument Clinic. --- Modules/clinic/posixmodule.c.h | 205 ++++++++++++++++++++++++++++++++++++++++- Modules/posixmodule.c | 191 ++++++++++++++++++-------------------- 2 files changed, 295 insertions(+), 101 deletions(-) diff --git a/Modules/clinic/posixmodule.c.h b/Modules/clinic/posixmodule.c.h index 72d7834..9de5b03 100644 --- a/Modules/clinic/posixmodule.c.h +++ b/Modules/clinic/posixmodule.c.h @@ -5596,6 +5596,209 @@ exit: #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__, "fspath($module, /, path)\n" "--\n" @@ -6148,4 +6351,4 @@ exit: #ifndef OS_GETRANDOM_METHODDEF #define OS_GETRANDOM_METHODDEF #endif /* !defined(OS_GETRANDOM_METHODDEF) */ -/*[clinic end generated code: output=b9ed5703d2feb0d9 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=e4a3bd36c7bb8356 input=a9049054013a1b77]*/ diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 7aae5c7..adcadc2 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -11092,10 +11092,10 @@ posix_set_blocking(PyObject *self, PyObject *args) #endif /* !MS_WINDOWS */ -PyDoc_STRVAR(posix_scandir__doc__, -"scandir(path='.') -> iterator of DirEntry objects for given path"); - -static char *follow_symlinks_keywords[] = {"follow_symlinks", NULL}; +/*[clinic input] +class os.DirEntry "DirEntry *" "&DirEntryType" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=3138f09f7c683f1d]*/ typedef struct { PyObject_HEAD @@ -11129,9 +11129,15 @@ DirEntry_dealloc(DirEntry *entry) static int 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 -DirEntry_is_symlink(DirEntry *self) +os_DirEntry_is_symlink_impl(DirEntry *self) +/*[clinic end generated code: output=42244667d7bcfc25 input=1605a1b4b96976c3]*/ { #ifdef MS_WINDOWS return (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK; @@ -11148,17 +11154,6 @@ DirEntry_is_symlink(DirEntry *self) } 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 * DirEntry_fetch_stat(DirEntry *self, int follow_symlinks) { int result; @@ -11200,14 +11195,23 @@ DirEntry_get_lstat(DirEntry *self) 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 * -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) return DirEntry_get_lstat(self); if (!self->stat) { - int result = DirEntry_is_symlink(self); + int result = os_DirEntry_is_symlink_impl(self); if (result == -1) return NULL; else if (result) @@ -11220,18 +11224,6 @@ DirEntry_get_stat(DirEntry *self, int follow_symlinks) 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 */ static int 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 (need_stat) { #endif - stat = DirEntry_get_stat(self, follow_symlinks); + stat = os_DirEntry_stat_impl(self, follow_symlinks); if (!stat) { if (PyErr_ExceptionMatches(PyExc_FileNotFoundError)) { /* If file doesn't exist (anymore), then return False @@ -11311,43 +11303,45 @@ error: return -1; } -static PyObject * -DirEntry_py_test_mode(DirEntry *self, int follow_symlinks, unsigned short mode_bits) -{ - int result; +/*[clinic input] +os.DirEntry.is_dir -> bool + * + follow_symlinks: bool = True - result = DirEntry_test_mode(self, follow_symlinks, mode_bits); - if (result == -1) - return NULL; - return PyBool_FromLong(result); -} +Return True if the entry is a directory; cached per entry. +[clinic start generated code]*/ -static PyObject * -DirEntry_is_dir(DirEntry *self, PyObject *args, PyObject *kwargs) +static int +os_DirEntry_is_dir_impl(DirEntry *self, int follow_symlinks) +/*[clinic end generated code: output=ad2e8d54365da287 input=0135232766f53f58]*/ { - int follow_symlinks = 1; + return DirEntry_test_mode(self, follow_symlinks, S_IFDIR); +} - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|$p:DirEntry.is_dir", - follow_symlinks_keywords, &follow_symlinks)) - return NULL; +/*[clinic input] +os.DirEntry.is_file -> bool + * + follow_symlinks: bool = True - return DirEntry_py_test_mode(self, follow_symlinks, S_IFDIR); -} +Return True if the entry is a file; cached per entry. +[clinic start generated code]*/ -static PyObject * -DirEntry_is_file(DirEntry *self, PyObject *args, PyObject *kwargs) +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_file", - follow_symlinks_keywords, &follow_symlinks)) - return NULL; +/*[clinic input] +os.DirEntry.inode - return DirEntry_py_test_mode(self, follow_symlinks, S_IFREG); -} +Return inode of the entry; cached per entry. +[clinic start generated code]*/ static PyObject * -DirEntry_inode(DirEntry *self) +os_DirEntry_inode_impl(DirEntry *self) +/*[clinic end generated code: output=156bb3a72162440e input=3ee7b872ae8649f0]*/ { #ifdef MS_WINDOWS if (!self->got_file_index) { @@ -11384,8 +11378,15 @@ DirEntry_repr(DirEntry *self) return PyUnicode_FromFormat("", self->name); } +/*[clinic input] +os.DirEntry.__fspath__ + +Returns the path for the entry. +[clinic start generated code]*/ + static PyObject * -DirEntry_fspath(DirEntry *self) +os_DirEntry___fspath___impl(DirEntry *self) +/*[clinic end generated code: output=6dd7f7ef752e6f4f input=3c49d0cf38df4fac]*/ { Py_INCREF(self->path); return self->path; @@ -11399,25 +11400,15 @@ static PyMemberDef DirEntry_members[] = { {NULL} }; +#include "clinic/posixmodule.c.h" + static PyMethodDef DirEntry_methods[] = { - {"is_dir", (PyCFunction)DirEntry_is_dir, METH_VARARGS | METH_KEYWORDS, - "return True if the entry is a directory; cached per entry" - }, - {"is_file", (PyCFunction)DirEntry_is_file, METH_VARARGS | METH_KEYWORDS, - "return True if the entry is a file; cached per entry" - }, - {"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", - }, + OS_DIRENTRY_IS_DIR_METHODDEF + OS_DIRENTRY_IS_FILE_METHODDEF + OS_DIRENTRY_IS_SYMLINK_METHODDEF + OS_DIRENTRY_STAT_METHODDEF + OS_DIRENTRY_INODE_METHODDEF + OS_DIRENTRY___FSPATH___METHODDEF {NULL} }; @@ -11890,23 +11881,34 @@ static PyTypeObject ScandirIteratorType = { (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 * -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; - static char *keywords[] = {"path", NULL}; #ifdef MS_WINDOWS wchar_t *path_strW; #else - const char *path; + const char *path_str; #endif iterator = PyObject_New(ScandirIterator, &ScandirIteratorType); if (!iterator) return NULL; - memset(&iterator->path, 0, sizeof(path_t)); - iterator->path.function_name = "scandir"; - iterator->path.nullable = 1; #ifdef MS_WINDOWS iterator->handle = INVALID_HANDLE_VALUE; @@ -11914,15 +11916,13 @@ posix_scandir(PyObject *self, PyObject *args, PyObject *kwargs) iterator->dirp = NULL; #endif - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O&:scandir", keywords, - path_converter, &iterator->path)) - goto error; - + memcpy(&iterator->path, path, sizeof(path_t)); /* path_converter doesn't keep path.object around, so do it manually for the lifetime of the iterator here (the refcount is decremented in ScandirIterator_dealloc) */ Py_XINCREF(iterator->path.object); + Py_XINCREF(iterator->path.cleanup); #ifdef MS_WINDOWS iterator->first_time = 1; @@ -11943,13 +11943,13 @@ posix_scandir(PyObject *self, PyObject *args, PyObject *kwargs) } #else /* POSIX */ if (iterator->path.narrow) - path = iterator->path.narrow; + path_str = iterator->path.narrow; else - path = "."; + path_str = "."; errno = 0; Py_BEGIN_ALLOW_THREADS - iterator->dirp = opendir(path); + iterator->dirp = opendir(path_str); Py_END_ALLOW_THREADS if (!iterator->dirp) { @@ -12092,13 +12092,6 @@ error: } #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[] = { @@ -12288,9 +12281,7 @@ static PyMethodDef posix_methods[] = { {"get_blocking", posix_get_blocking, METH_VARARGS, get_blocking__doc__}, {"set_blocking", posix_set_blocking, METH_VARARGS, set_blocking__doc__}, #endif - {"scandir", (PyCFunction)posix_scandir, - METH_VARARGS | METH_KEYWORDS, - posix_scandir__doc__}, + OS_SCANDIR_METHODDEF OS_FSPATH_METHODDEF OS_GETRANDOM_METHODDEF {NULL, NULL} /* Sentinel */ -- cgit v0.12