bpo-35381 Remove all static state from posixmodule (GH-15892)

After #9665, this moves the remaining types in posixmodule to be heap-allocated to make it compatible with PEP384 as well as modifying all the type accessors to fully make the type opaque.

The original PR that got messed up a rebase: https://github.com/python/cpython/pull/10854. All the issues in that commit have now been addressed since https://github.com/python/cpython/pull/11661 got committed.

This change also removes any state from the data segment and onto the module state itself.


https://bugs.python.org/issue35381



Automerge-Triggered-By: @encukou
This commit is contained in:
Eddie Elizondo 2019-11-05 07:16:14 -08:00 committed by Miss Islington (bot)
parent 5e01a6542a
commit b3966639d2
4 changed files with 307 additions and 228 deletions

View File

@ -3638,6 +3638,24 @@ class ExportsTests(unittest.TestCase):
self.assertIn('walk', os.__all__)
class TestDirEntry(unittest.TestCase):
def setUp(self):
self.path = os.path.realpath(support.TESTFN)
self.addCleanup(support.rmtree, self.path)
os.mkdir(self.path)
def test_uninstantiable(self):
self.assertRaises(TypeError, os.DirEntry)
def test_unpickable(self):
filename = create_file(os.path.join(self.path, "file.txt"), b'python')
entry = [entry for entry in os.scandir(self.path)].pop()
self.assertIsInstance(entry, os.DirEntry)
self.assertEqual(entry.name, "file.txt")
import pickle
self.assertRaises(TypeError, pickle.dumps, entry, filename)
class TestScandir(unittest.TestCase):
check_no_resource_warning = support.check_no_resource_warning
@ -3672,6 +3690,18 @@ class TestScandir(unittest.TestCase):
else:
self.assertEqual(stat1, stat2)
def test_uninstantiable(self):
scandir_iter = os.scandir(self.path)
self.assertRaises(TypeError, type(scandir_iter))
scandir_iter.close()
def test_unpickable(self):
filename = self.create_file("file.txt")
scandir_iter = os.scandir(self.path)
import pickle
self.assertRaises(TypeError, pickle.dumps, scandir_iter, filename)
scandir_iter.close()
def check_entry(self, entry, name, is_dir, is_file, is_symlink):
self.assertIsInstance(entry, os.DirEntry)
self.assertEqual(entry.name, name)

View File

@ -0,0 +1,2 @@
Convert posixmodule.c statically allocated types ``DirEntryType`` and
``ScandirIteratorType`` to heap-allocated types.

View File

@ -2838,7 +2838,7 @@ PyDoc_STRVAR(os_sched_param__doc__,
"sched_param(sched_priority)\n"
"--\n"
"\n"
"Current has only one field: sched_priority\");\n"
"Currently has only one field: sched_priority\n"
"\n"
" sched_priority\n"
" A scheduling parameter.");
@ -8731,4 +8731,4 @@ exit:
#ifndef OS__REMOVE_DLL_DIRECTORY_METHODDEF
#define OS__REMOVE_DLL_DIRECTORY_METHODDEF
#endif /* !defined(OS__REMOVE_DLL_DIRECTORY_METHODDEF) */
/*[clinic end generated code: output=fe7897441fed5402 input=a9049054013a1b77]*/
/*[clinic end generated code: output=c6e67d475eef00c4 input=a9049054013a1b77]*/

View File

@ -217,6 +217,7 @@ corresponding Unix manual entries for more information on calls.");
#endif /* _MSC_VER */
#endif /* ! __WATCOMC__ || __QNX__ */
_Py_IDENTIFIER(__fspath__);
/*[clinic input]
# one of the few times we lie about this name!
@ -537,7 +538,7 @@ _Py_Uid_Converter(PyObject *obj, void *p)
if (index == NULL) {
PyErr_Format(PyExc_TypeError,
"uid should be integer, not %.200s",
Py_TYPE(obj)->tp_name);
_PyType_Name(Py_TYPE(obj)));
return 0;
}
@ -643,7 +644,7 @@ _Py_Gid_Converter(PyObject *obj, void *p)
if (index == NULL) {
PyErr_Format(PyExc_TypeError,
"gid should be integer, not %.200s",
Py_TYPE(obj)->tp_name);
_PyType_Name(Py_TYPE(obj)));
return 0;
}
@ -810,11 +811,37 @@ dir_fd_converter(PyObject *o, void *p)
else {
PyErr_Format(PyExc_TypeError,
"argument should be integer or None, not %.200s",
Py_TYPE(o)->tp_name);
_PyType_Name(Py_TYPE(o)));
return 0;
}
}
typedef struct {
PyObject *billion;
PyObject *posix_putenv_garbage;
PyObject *DirEntryType;
PyObject *ScandirIteratorType;
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
PyObject *SchedParamType;
#endif
PyObject *StatResultType;
PyObject *StatVFSResultType;
PyObject *TerminalSizeType;
PyObject *TimesResultType;
PyObject *UnameResultType;
#if defined(HAVE_WAITID) && !defined(__APPLE__)
PyObject *WaitidResultType;
#endif
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
PyObject *struct_rusage;
#endif
PyObject *st_mode;
} _posixstate;
static struct PyModuleDef posixmodule;
#define _posixstate(o) ((_posixstate *)PyModule_GetState(o))
#define _posixstate_global ((_posixstate *)PyModule_GetState(PyState_FindModule(&posixmodule)))
/*
* A PyArg_ParseTuple "converter" function
@ -984,7 +1011,6 @@ path_converter(PyObject *o, void *p)
if (!is_index && !is_buffer && !is_unicode && !is_bytes) {
/* Inline PyOS_FSPath() for better error messages. */
_Py_IDENTIFIER(__fspath__);
PyObject *func, *res;
func = _PyObject_LookupSpecial(o, &PyId___fspath__);
@ -1005,8 +1031,8 @@ path_converter(PyObject *o, void *p)
else {
PyErr_Format(PyExc_TypeError,
"expected %.200s.__fspath__() to return str or bytes, "
"not %.200s", Py_TYPE(o)->tp_name,
Py_TYPE(res)->tp_name);
"not %.200s", _PyType_Name(Py_TYPE(o)),
_PyType_Name(Py_TYPE(res)));
Py_DECREF(res);
goto error_exit;
}
@ -1058,7 +1084,7 @@ path_converter(PyObject *o, void *p)
path->allow_fd ? "string, bytes, os.PathLike or integer" :
path->nullable ? "string, bytes, os.PathLike or None" :
"string, bytes or os.PathLike",
Py_TYPE(o)->tp_name)) {
_PyType_Name(Py_TYPE(o)))) {
goto error_exit;
}
bytes = PyBytes_FromObject(o);
@ -1089,7 +1115,7 @@ path_converter(PyObject *o, void *p)
path->allow_fd ? "string, bytes, os.PathLike or integer" :
path->nullable ? "string, bytes, os.PathLike or None" :
"string, bytes or os.PathLike",
Py_TYPE(o)->tp_name);
_PyType_Name(Py_TYPE(o)));
goto error_exit;
}
@ -2047,14 +2073,6 @@ static PyStructSequence_Desc waitid_result_desc = {
waitid_result_fields,
5
};
static PyTypeObject* WaitidResultType;
#endif
static int initialized;
static PyTypeObject* StatResultType;
static PyTypeObject* StatVFSResultType;
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
static PyTypeObject* SchedParamType;
#endif
static newfunc structseq_new;
@ -2080,8 +2098,61 @@ statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
return (PyObject*)result;
}
static int
_posix_clear(PyObject *module)
{
Py_CLEAR(_posixstate(module)->billion);
Py_CLEAR(_posixstate(module)->posix_putenv_garbage);
Py_CLEAR(_posixstate(module)->DirEntryType);
Py_CLEAR(_posixstate(module)->ScandirIteratorType);
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
Py_CLEAR(_posixstate(module)->SchedParamType);
#endif
Py_CLEAR(_posixstate(module)->StatResultType);
Py_CLEAR(_posixstate(module)->StatVFSResultType);
Py_CLEAR(_posixstate(module)->TerminalSizeType);
Py_CLEAR(_posixstate(module)->TimesResultType);
Py_CLEAR(_posixstate(module)->UnameResultType);
#if defined(HAVE_WAITID) && !defined(__APPLE__)
Py_CLEAR(_posixstate(module)->WaitidResultType);
#endif
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
Py_CLEAR(_posixstate(module)->struct_rusage);
#endif
Py_CLEAR(_posixstate(module)->st_mode);
return 0;
}
static PyObject *billion = NULL;
static int
_posix_traverse(PyObject *module, visitproc visit, void *arg)
{
Py_VISIT(_posixstate(module)->billion);
Py_VISIT(_posixstate(module)->posix_putenv_garbage);
Py_VISIT(_posixstate(module)->DirEntryType);
Py_VISIT(_posixstate(module)->ScandirIteratorType);
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
Py_VISIT(_posixstate(module)->SchedParamType);
#endif
Py_VISIT(_posixstate(module)->StatResultType);
Py_VISIT(_posixstate(module)->StatVFSResultType);
Py_VISIT(_posixstate(module)->TerminalSizeType);
Py_VISIT(_posixstate(module)->TimesResultType);
Py_VISIT(_posixstate(module)->UnameResultType);
#if defined(HAVE_WAITID) && !defined(__APPLE__)
Py_VISIT(_posixstate(module)->WaitidResultType);
#endif
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
Py_VISIT(_posixstate(module)->struct_rusage);
#endif
Py_VISIT(_posixstate(module)->st_mode);
return 0;
}
static void
_posix_free(void *module)
{
_posix_clear((PyObject *)module);
}
static void
fill_time(PyObject *v, int index, time_t sec, unsigned long nsec)
@ -2095,7 +2166,7 @@ fill_time(PyObject *v, int index, time_t sec, unsigned long nsec)
if (!(s && ns_fractional))
goto exit;
s_in_ns = PyNumber_Multiply(s, billion);
s_in_ns = PyNumber_Multiply(s, _posixstate_global->billion);
if (!s_in_ns)
goto exit;
@ -2128,7 +2199,8 @@ static PyObject*
_pystat_fromstructstat(STRUCT_STAT *st)
{
unsigned long ansec, mnsec, cnsec;
PyObject *v = PyStructSequence_New(StatResultType);
PyObject *StatResultType = _posixstate_global->StatResultType;
PyObject *v = PyStructSequence_New((PyTypeObject *)StatResultType);
if (v == NULL)
return NULL;
@ -4505,15 +4577,12 @@ or via the attributes sysname, nodename, release, version, and machine.\n\
See os.uname for more information.");
static PyStructSequence_Desc uname_result_desc = {
"uname_result", /* name */
MODNAME ".uname_result", /* name */
uname_result__doc__, /* doc */
uname_result_fields,
5
};
static PyTypeObject* UnameResultType;
#ifdef HAVE_UNAME
/*[clinic input]
os.uname
@ -4539,7 +4608,8 @@ os_uname_impl(PyObject *module)
if (res < 0)
return posix_error();
value = PyStructSequence_New(UnameResultType);
PyObject *UnameResultType = _posixstate(module)->UnameResultType;
value = PyStructSequence_New((PyTypeObject *)UnameResultType);
if (value == NULL)
return NULL;
@ -4720,13 +4790,13 @@ split_py_long_to_s_and_ns(PyObject *py_long, time_t *s, long *ns)
{
int result = 0;
PyObject *divmod;
divmod = PyNumber_Divmod(py_long, billion);
divmod = PyNumber_Divmod(py_long, _posixstate_global->billion);
if (!divmod)
goto exit;
if (!PyTuple_Check(divmod) || PyTuple_GET_SIZE(divmod) != 2) {
PyErr_Format(PyExc_TypeError,
"%.200s.__divmod__() must return a 2-tuple, not %.200s",
Py_TYPE(py_long)->tp_name, Py_TYPE(divmod)->tp_name);
_PyType_Name(Py_TYPE(py_long)), _PyType_Name(Py_TYPE(divmod)));
goto exit;
}
*s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0));
@ -5973,7 +6043,7 @@ check_null_or_callable(PyObject *obj, const char* obj_name)
{
if (obj && !PyCallable_Check(obj)) {
PyErr_Format(PyExc_TypeError, "'%s' must be callable, not %s",
obj_name, Py_TYPE(obj)->tp_name);
obj_name, _PyType_Name(Py_TYPE(obj)));
return -1;
}
return 0;
@ -6177,12 +6247,12 @@ os.sched_param.__new__
sched_priority: object
A scheduling parameter.
Current has only one field: sched_priority");
Currently has only one field: sched_priority
[clinic start generated code]*/
static PyObject *
os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority)
/*[clinic end generated code: output=48f4067d60f48c13 input=ab4de35a9a7811f2]*/
/*[clinic end generated code: output=48f4067d60f48c13 input=eb42909a2c0e3e6c]*/
{
PyObject *res;
@ -6194,7 +6264,6 @@ os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority)
return res;
}
PyDoc_VAR(os_sched_param__doc__);
static PyStructSequence_Field sched_param_fields[] = {
@ -6214,7 +6283,8 @@ convert_sched_param(PyObject *param, struct sched_param *res)
{
long priority;
if (Py_TYPE(param) != SchedParamType) {
PyObject *SchedParamType = _posixstate_global->SchedParamType;
if (Py_TYPE(param) != (PyTypeObject *)SchedParamType) {
PyErr_SetString(PyExc_TypeError, "must have a sched_param object");
return 0;
}
@ -6285,7 +6355,8 @@ os_sched_getparam_impl(PyObject *module, pid_t pid)
if (sched_getparam(pid, &param))
return posix_error();
result = PyStructSequence_New(SchedParamType);
PyObject *SchedParamType = _posixstate_global->SchedParamType;
result = PyStructSequence_New((PyTypeObject *)SchedParamType);
if (!result)
return NULL;
priority = PyLong_FromLong(param.sched_priority);
@ -7494,8 +7565,7 @@ static PyObject *
wait_helper(pid_t pid, int status, struct rusage *ru)
{
PyObject *result;
static PyObject *struct_rusage;
_Py_IDENTIFIER(struct_rusage);
PyObject *struct_rusage;
if (pid == -1)
return posix_error();
@ -7506,15 +7576,13 @@ wait_helper(pid_t pid, int status, struct rusage *ru)
memset(ru, 0, sizeof(*ru));
}
if (struct_rusage == NULL) {
PyObject *m = PyImport_ImportModuleNoBlock("resource");
if (m == NULL)
return NULL;
struct_rusage = _PyObject_GetAttrId(m, &PyId_struct_rusage);
Py_DECREF(m);
if (struct_rusage == NULL)
return NULL;
}
PyObject *m = PyImport_ImportModuleNoBlock("resource");
if (m == NULL)
return NULL;
struct_rusage = PyObject_GetAttr(m, _posixstate_global->struct_rusage);
Py_DECREF(m);
if (struct_rusage == NULL)
return NULL;
/* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */
result = PyStructSequence_New((PyTypeObject*) struct_rusage);
@ -7668,7 +7736,8 @@ os_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options)
if (si.si_pid == 0)
Py_RETURN_NONE;
result = PyStructSequence_New(WaitidResultType);
PyObject *WaitidResultType = _posixstate(module)->WaitidResultType;
result = PyStructSequence_New((PyTypeObject *)WaitidResultType);
if (!result)
return NULL;
@ -8119,8 +8188,6 @@ static PyStructSequence_Desc times_result_desc = {
5
};
static PyTypeObject* TimesResultType;
#ifdef MS_WINDOWS
#define HAVE_TIMES /* mandatory, for the method table */
#endif
@ -8132,7 +8199,8 @@ build_times_result(double user, double system,
double children_user, double children_system,
double elapsed)
{
PyObject *value = PyStructSequence_New(TimesResultType);
PyObject *TimesResultType = _posixstate_global->TimesResultType;
PyObject *value = PyStructSequence_New((PyTypeObject *)TimesResultType);
if (value == NULL)
return NULL;
@ -9953,10 +10021,6 @@ os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset,
#ifdef HAVE_PUTENV
/* Save putenv() parameters as values here, so we can collect them when they
* get re-set with another call for the same key. */
static PyObject *posix_putenv_garbage;
static void
posix_putenv_garbage_setitem(PyObject *name, PyObject *value)
{
@ -9964,7 +10028,7 @@ posix_putenv_garbage_setitem(PyObject *name, PyObject *value)
* this will cause previous value to be collected. This has to
* happen after the real putenv() call because the old value
* was still accessible until then. */
if (PyDict_SetItem(posix_putenv_garbage, name, value))
if (PyDict_SetItem(_posixstate_global->posix_putenv_garbage, name, value))
/* really not much we can do; just leak */
PyErr_Clear();
else
@ -10101,7 +10165,7 @@ os_unsetenv_impl(PyObject *module, PyObject *name)
* happen after the real unsetenv() call because the
* old value was still accessible until then.
*/
if (PyDict_DelItem(posix_putenv_garbage, name)) {
if (PyDict_DelItem(_posixstate(module)->posix_putenv_garbage, name)) {
/* really not much we can do; just leak */
if (!PyErr_ExceptionMatches(PyExc_KeyError)) {
return NULL;
@ -10312,7 +10376,8 @@ os_WSTOPSIG_impl(PyObject *module, int status)
static PyObject*
_pystatvfs_fromstructstatvfs(struct statvfs st) {
PyObject *v = PyStructSequence_New(StatVFSResultType);
PyObject *StatVFSResultType = _posixstate_global->StatVFSResultType;
PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType);
if (v == NULL)
return NULL;
@ -12089,8 +12154,6 @@ os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags)
/* Terminal size querying */
static PyTypeObject* TerminalSizeType;
PyDoc_STRVAR(TerminalSize_docstring,
"A tuple of (columns, lines) for holding terminal window size");
@ -12181,7 +12244,8 @@ get_terminal_size(PyObject *self, PyObject *args)
}
#endif /* TERMSIZE_USE_CONIO */
termsize = PyStructSequence_New(TerminalSizeType);
PyObject *TerminalSizeType = _posixstate(self)->TerminalSizeType;
termsize = PyStructSequence_New((PyTypeObject *)TerminalSizeType);
if (termsize == NULL)
return NULL;
PyStructSequence_SET_ITEM(termsize, 0, PyLong_FromLong(columns));
@ -12379,9 +12443,9 @@ os_set_blocking_impl(PyObject *module, int fd, int blocking)
/*[clinic input]
class os.DirEntry "DirEntry *" "&DirEntryType"
class os.DirEntry "DirEntry *" "DirEntryType"
[clinic start generated code]*/
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=3138f09f7c683f1d]*/
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=3c18c7a448247980]*/
typedef struct {
PyObject_HEAD
@ -12402,14 +12466,25 @@ typedef struct {
#endif
} DirEntry;
static PyObject *
_disabled_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
{
PyErr_Format(PyExc_TypeError,
"cannot create '%.100s' instances", _PyType_Name(type));
return NULL;
}
static void
DirEntry_dealloc(DirEntry *entry)
{
PyTypeObject *tp = Py_TYPE(entry);
Py_XDECREF(entry->name);
Py_XDECREF(entry->path);
Py_XDECREF(entry->stat);
Py_XDECREF(entry->lstat);
Py_TYPE(entry)->tp_free((PyObject *)entry);
freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
free_func(entry);
Py_DECREF(tp);
}
/* Forward reference */
@ -12538,7 +12613,6 @@ DirEntry_test_mode(DirEntry *self, int follow_symlinks, unsigned short mode_bits
#ifdef MS_WINDOWS
unsigned long dir_bits;
#endif
_Py_IDENTIFIER(st_mode);
#ifdef MS_WINDOWS
is_symlink = (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
@ -12561,7 +12635,7 @@ DirEntry_test_mode(DirEntry *self, int follow_symlinks, unsigned short mode_bits
}
goto error;
}
st_mode = _PyObject_GetAttrId(stat, &PyId_st_mode);
st_mode = PyObject_GetAttr(stat, _posixstate_global->st_mode);
if (!st_mode)
goto error;
@ -12709,39 +12783,24 @@ static PyMethodDef DirEntry_methods[] = {
{NULL}
};
static PyTypeObject DirEntryType = {
PyVarObject_HEAD_INIT(NULL, 0)
MODNAME ".DirEntry", /* tp_name */
sizeof(DirEntry), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
(destructor)DirEntry_dealloc, /* tp_dealloc */
0, /* tp_vectorcall_offset */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_as_async */
(reprfunc)DirEntry_repr, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
DirEntry_methods, /* tp_methods */
DirEntry_members, /* tp_members */
static PyType_Slot DirEntryType_slots[] = {
{Py_tp_new, _disabled_new},
{Py_tp_dealloc, DirEntry_dealloc},
{Py_tp_repr, DirEntry_repr},
{Py_tp_methods, DirEntry_methods},
{Py_tp_members, DirEntry_members},
{0, 0},
};
static PyType_Spec DirEntryType_spec = {
MODNAME ".DirEntry",
sizeof(DirEntry),
0,
Py_TPFLAGS_DEFAULT,
DirEntryType_slots
};
#ifdef MS_WINDOWS
static wchar_t *
@ -12785,7 +12844,8 @@ DirEntry_from_find_data(path_t *path, WIN32_FIND_DATAW *dataW)
ULONG reparse_tag;
wchar_t *joined_path;
entry = PyObject_New(DirEntry, &DirEntryType);
PyObject *DirEntryType = _posixstate_global->DirEntryType;
entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
if (!entry)
return NULL;
entry->name = NULL;
@ -12872,7 +12932,8 @@ DirEntry_from_posix_info(path_t *path, const char *name, Py_ssize_t name_len,
DirEntry *entry;
char *joined_path;
entry = PyObject_New(DirEntry, &DirEntryType);
PyObject *DirEntryType = _posixstate_global->DirEntryType;
entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
if (!entry)
return NULL;
entry->name = NULL;
@ -13134,10 +13195,13 @@ ScandirIterator_finalize(ScandirIterator *iterator)
static void
ScandirIterator_dealloc(ScandirIterator *iterator)
{
PyTypeObject *tp = Py_TYPE(iterator);
if (PyObject_CallFinalizerFromDealloc((PyObject *)iterator) < 0)
return;
Py_TYPE(iterator)->tp_free((PyObject *)iterator);
freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
free_func(iterator);
Py_DECREF(tp);
}
static PyMethodDef ScandirIterator_methods[] = {
@ -13147,56 +13211,22 @@ static PyMethodDef ScandirIterator_methods[] = {
{NULL}
};
static PyTypeObject ScandirIteratorType = {
PyVarObject_HEAD_INIT(NULL, 0)
MODNAME ".ScandirIterator", /* tp_name */
sizeof(ScandirIterator), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
(destructor)ScandirIterator_dealloc, /* tp_dealloc */
0, /* tp_vectorcall_offset */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_as_async */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
PyObject_SelfIter, /* tp_iter */
(iternextfunc)ScandirIterator_iternext, /* tp_iternext */
ScandirIterator_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
0, /* tp_new */
0, /* tp_free */
0, /* tp_is_gc */
0, /* tp_bases */
0, /* tp_mro */
0, /* tp_cache */
0, /* tp_subclasses */
0, /* tp_weaklist */
0, /* tp_del */
0, /* tp_version_tag */
(destructor)ScandirIterator_finalize, /* tp_finalize */
static PyType_Slot ScandirIteratorType_slots[] = {
{Py_tp_new, _disabled_new},
{Py_tp_dealloc, ScandirIterator_dealloc},
{Py_tp_finalize, ScandirIterator_finalize},
{Py_tp_iter, PyObject_SelfIter},
{Py_tp_iternext, ScandirIterator_iternext},
{Py_tp_methods, ScandirIterator_methods},
{0, 0},
};
static PyType_Spec ScandirIteratorType_spec = {
MODNAME ".ScandirIterator",
sizeof(ScandirIterator),
0,
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_FINALIZE,
ScandirIteratorType_slots
};
/*[clinic input]
@ -13232,7 +13262,8 @@ os_scandir_impl(PyObject *module, path_t *path)
return NULL;
}
iterator = PyObject_New(ScandirIterator, &ScandirIteratorType);
PyObject *ScandirIteratorType = _posixstate(module)->ScandirIteratorType;
iterator = PyObject_New(ScandirIterator, (PyTypeObject *)ScandirIteratorType);
if (!iterator)
return NULL;
@ -13322,7 +13353,6 @@ PyOS_FSPath(PyObject *path)
{
/* For error message reasons, this function is manually inlined in
path_converter(). */
_Py_IDENTIFIER(__fspath__);
PyObject *func = NULL;
PyObject *path_repr = NULL;
@ -13336,7 +13366,7 @@ PyOS_FSPath(PyObject *path)
return PyErr_Format(PyExc_TypeError,
"expected str, bytes or os.PathLike object, "
"not %.200s",
Py_TYPE(path)->tp_name);
_PyType_Name(Py_TYPE(path)));
}
path_repr = _PyObject_CallNoArg(func);
@ -13348,8 +13378,8 @@ PyOS_FSPath(PyObject *path)
if (!(PyUnicode_Check(path_repr) || PyBytes_Check(path_repr))) {
PyErr_Format(PyExc_TypeError,
"expected %.200s.__fspath__() to return str or bytes, "
"not %.200s", Py_TYPE(path)->tp_name,
Py_TYPE(path_repr)->tp_name);
"not %.200s", _PyType_Name(Py_TYPE(path)),
_PyType_Name(Py_TYPE(path_repr)));
Py_DECREF(path_repr);
return NULL;
}
@ -14258,12 +14288,12 @@ static struct PyModuleDef posixmodule = {
PyModuleDef_HEAD_INIT,
MODNAME,
posix__doc__,
-1,
sizeof(_posixstate),
posix_methods,
NULL,
NULL,
NULL,
NULL
_posix_traverse,
_posix_clear,
_posix_free,
};
@ -14408,6 +14438,12 @@ INITFUNC(void)
PyObject *list;
const char * const *trace;
m = PyState_FindModule(&posixmodule);
if (m != NULL) {
Py_INCREF(m);
return m;
}
m = PyModule_Create(&posixmodule);
if (m == NULL)
return NULL;
@ -14429,94 +14465,106 @@ INITFUNC(void)
PyModule_AddObject(m, "error", PyExc_OSError);
#ifdef HAVE_PUTENV
if (posix_putenv_garbage == NULL)
posix_putenv_garbage = PyDict_New();
/* Save putenv() parameters as values here, so we can collect them when they
* get re-set with another call for the same key. */
_posixstate(m)->posix_putenv_garbage = PyDict_New();
#endif
if (!initialized) {
#if defined(HAVE_WAITID) && !defined(__APPLE__)
waitid_result_desc.name = MODNAME ".waitid_result";
WaitidResultType = PyStructSequence_NewType(&waitid_result_desc);
if (WaitidResultType == NULL) {
return NULL;
}
waitid_result_desc.name = MODNAME ".waitid_result";
PyObject *WaitidResultType = (PyObject *)PyStructSequence_NewType(&waitid_result_desc);
if (WaitidResultType == NULL) {
return NULL;
}
Py_INCREF(WaitidResultType);
PyModule_AddObject(m, "waitid_result", WaitidResultType);
_posixstate(m)->WaitidResultType = WaitidResultType;
#endif
stat_result_desc.name = "os.stat_result"; /* see issue #19209 */
stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;
StatResultType = PyStructSequence_NewType(&stat_result_desc);
if (StatResultType == NULL) {
return NULL;
}
structseq_new = StatResultType->tp_new;
StatResultType->tp_new = statresult_new;
stat_result_desc.name = "os.stat_result"; /* see issue #19209 */
stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;
PyObject *StatResultType = (PyObject *)PyStructSequence_NewType(&stat_result_desc);
if (StatResultType == NULL) {
return NULL;
}
Py_INCREF(StatResultType);
PyModule_AddObject(m, "stat_result", StatResultType);
_posixstate(m)->StatResultType = StatResultType;
structseq_new = ((PyTypeObject *)StatResultType)->tp_new;
((PyTypeObject *)StatResultType)->tp_new = statresult_new;
statvfs_result_desc.name = "os.statvfs_result"; /* see issue #19209 */
StatVFSResultType = PyStructSequence_NewType(&statvfs_result_desc);
if (StatVFSResultType == NULL) {
return NULL;
}
statvfs_result_desc.name = "os.statvfs_result"; /* see issue #19209 */
PyObject *StatVFSResultType = (PyObject *)PyStructSequence_NewType(&statvfs_result_desc);
if (StatVFSResultType == NULL) {
return NULL;
}
Py_INCREF(StatVFSResultType);
PyModule_AddObject(m, "statvfs_result", StatVFSResultType);
_posixstate(m)->StatVFSResultType = StatVFSResultType;
#ifdef NEED_TICKS_PER_SECOND
# if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)
ticks_per_second = sysconf(_SC_CLK_TCK);
ticks_per_second = sysconf(_SC_CLK_TCK);
# elif defined(HZ)
ticks_per_second = HZ;
ticks_per_second = HZ;
# else
ticks_per_second = 60; /* magic fallback value; may be bogus */
ticks_per_second = 60; /* magic fallback value; may be bogus */
# endif
#endif
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
sched_param_desc.name = MODNAME ".sched_param";
SchedParamType = PyStructSequence_NewType(&sched_param_desc);
if (SchedParamType == NULL) {
return NULL;
}
SchedParamType->tp_new = os_sched_param;
#endif
/* initialize TerminalSize_info */
TerminalSizeType = PyStructSequence_NewType(&TerminalSize_desc);
if (TerminalSizeType == NULL) {
return NULL;
}
/* initialize scandir types */
if (PyType_Ready(&ScandirIteratorType) < 0)
return NULL;
if (PyType_Ready(&DirEntryType) < 0)
return NULL;
sched_param_desc.name = MODNAME ".sched_param";
PyObject *SchedParamType = (PyObject *)PyStructSequence_NewType(&sched_param_desc);
if (SchedParamType == NULL) {
return NULL;
}
#if defined(HAVE_WAITID) && !defined(__APPLE__)
Py_INCREF((PyObject*) WaitidResultType);
PyModule_AddObject(m, "waitid_result", (PyObject*) WaitidResultType);
#endif
Py_INCREF((PyObject*) StatResultType);
PyModule_AddObject(m, "stat_result", (PyObject*) StatResultType);
Py_INCREF((PyObject*) StatVFSResultType);
PyModule_AddObject(m, "statvfs_result",
(PyObject*) StatVFSResultType);
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER)
Py_INCREF(SchedParamType);
PyModule_AddObject(m, "sched_param", (PyObject *)SchedParamType);
PyModule_AddObject(m, "sched_param", SchedParamType);
_posixstate(m)->SchedParamType = SchedParamType;
((PyTypeObject *)SchedParamType)->tp_new = os_sched_param;
#endif
/* initialize TerminalSize_info */
PyObject *TerminalSizeType = (PyObject *)PyStructSequence_NewType(&TerminalSize_desc);
if (TerminalSizeType == NULL) {
return NULL;
}
Py_INCREF(TerminalSizeType);
PyModule_AddObject(m, "terminal_size", TerminalSizeType);
_posixstate(m)->TerminalSizeType = TerminalSizeType;
/* initialize scandir types */
PyObject *ScandirIteratorType = PyType_FromSpec(&ScandirIteratorType_spec);
if (ScandirIteratorType == NULL) {
return NULL;
}
_posixstate(m)->ScandirIteratorType = ScandirIteratorType;
PyObject *DirEntryType = PyType_FromSpec(&DirEntryType_spec);
if (DirEntryType == NULL) {
return NULL;
}
Py_INCREF(DirEntryType);
PyModule_AddObject(m, "DirEntry", DirEntryType);
_posixstate(m)->DirEntryType = DirEntryType;
times_result_desc.name = MODNAME ".times_result";
TimesResultType = PyStructSequence_NewType(&times_result_desc);
PyObject *TimesResultType = (PyObject *)PyStructSequence_NewType(&times_result_desc);
if (TimesResultType == NULL) {
return NULL;
}
PyModule_AddObject(m, "times_result", (PyObject *)TimesResultType);
Py_INCREF(TimesResultType);
PyModule_AddObject(m, "times_result", TimesResultType);
_posixstate(m)->TimesResultType = TimesResultType;
uname_result_desc.name = MODNAME ".uname_result";
UnameResultType = PyStructSequence_NewType(&uname_result_desc);
PyTypeObject *UnameResultType = PyStructSequence_NewType(&uname_result_desc);
if (UnameResultType == NULL) {
return NULL;
}
Py_INCREF(UnameResultType);
PyModule_AddObject(m, "uname_result", (PyObject *)UnameResultType);
_posixstate(m)->UnameResultType = (PyObject *)UnameResultType;
#ifdef __APPLE__
/*
@ -14556,11 +14604,15 @@ INITFUNC(void)
#endif /* __APPLE__ */
Py_INCREF(TerminalSizeType);
PyModule_AddObject(m, "terminal_size", (PyObject*)TerminalSizeType);
billion = PyLong_FromLong(1000000000);
if (!billion)
if ((_posixstate(m)->billion = PyLong_FromLong(1000000000)) == NULL)
return NULL;
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
_posixstate(m)->struct_rusage = PyUnicode_InternFromString("struct_rusage");
if (_posixstate(m)->struct_rusage == NULL)
return NULL;
#endif
_posixstate(m)->st_mode = PyUnicode_InternFromString("st_mode");
if (_posixstate(m)->st_mode == NULL)
return NULL;
/* suppress "function not used" warnings */
@ -14590,11 +14642,6 @@ INITFUNC(void)
}
PyModule_AddObject(m, "_have_functions", list);
Py_INCREF((PyObject *) &DirEntryType);
PyModule_AddObject(m, "DirEntry", (PyObject *)&DirEntryType);
initialized = 1;
return m;
}