_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(node_offset));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(ns));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(nstype));
+ _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(nt));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(null));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(number));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(obj));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(pos));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(pos1));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(pos2));
+ _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(posix));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(print_file_and_line));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(priority));
_PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(progress));
STRUCT_FOR_ID(node_offset)
STRUCT_FOR_ID(ns)
STRUCT_FOR_ID(nstype)
+ STRUCT_FOR_ID(nt)
STRUCT_FOR_ID(null)
STRUCT_FOR_ID(number)
STRUCT_FOR_ID(obj)
STRUCT_FOR_ID(pos)
STRUCT_FOR_ID(pos1)
STRUCT_FOR_ID(pos2)
+ STRUCT_FOR_ID(posix)
STRUCT_FOR_ID(print_file_and_line)
STRUCT_FOR_ID(priority)
STRUCT_FOR_ID(progress)
--- /dev/null
+#ifndef Py_INTERNAL_OS_H
+#define Py_INTERNAL_OS_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef Py_BUILD_CORE
+# error "this header requires Py_BUILD_CORE define"
+#endif
+
+
+#ifndef MS_WINDOWS
+#define _OS_NEED_TICKS_PER_SECOND
+# define need_ticks_per_second_STATE \
+ long ticks_per_second;
+# define need_ticks_per_second_INIT \
+ .ticks_per_second = -1,
+#else
+# define need_ticks_per_second_STATE
+# define need_ticks_per_second_INIT
+#endif /* MS_WINDOWS */
+
+
+struct _os_runtime_state {
+ int _not_used;
+ need_ticks_per_second_STATE
+};
+# define _OS_RUNTIME_INIT \
+ { \
+ ._not_used = 0, \
+ need_ticks_per_second_INIT \
+ }
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_INTERNAL_OS_H */
#include "pycore_pymem.h" // struct _pymem_allocators
#include "pycore_pyhash.h" // struct pyhash_runtime_state
#include "pycore_obmalloc.h" // struct obmalloc_state
+#include "pycore_os.h" // struct _os_runtime_state
#include "pycore_unicodeobject.h" // struct _Py_unicode_runtime_ids
struct _getargs_runtime_state {
* KeyboardInterrupt exception, suggesting the user pressed ^C. */
int unhandled_keyboard_interrupt;
} signals;
+ struct _os_runtime_state os;
struct pyinterpreters {
PyThread_type_lock mutex;
}, \
.obmalloc = _obmalloc_state_INIT(runtime.obmalloc), \
.pyhash_state = pyhash_state_INIT, \
+ .os = _OS_RUNTIME_INIT, \
.interpreters = { \
/* This prevents interpreters from getting created \
until _PyInterpreterState_Enable() is called. */ \
INIT_ID(node_offset), \
INIT_ID(ns), \
INIT_ID(nstype), \
+ INIT_ID(nt), \
INIT_ID(null), \
INIT_ID(number), \
INIT_ID(obj), \
INIT_ID(pos), \
INIT_ID(pos1), \
INIT_ID(pos2), \
+ INIT_ID(posix), \
INIT_ID(print_file_and_line), \
INIT_ID(priority), \
INIT_ID(progress), \
PyUnicode_InternInPlace(&string);
string = &_Py_ID(nstype);
PyUnicode_InternInPlace(&string);
+ string = &_Py_ID(nt);
+ PyUnicode_InternInPlace(&string);
string = &_Py_ID(null);
PyUnicode_InternInPlace(&string);
string = &_Py_ID(number);
PyUnicode_InternInPlace(&string);
string = &_Py_ID(pos2);
PyUnicode_InternInPlace(&string);
+ string = &_Py_ID(posix);
+ PyUnicode_InternInPlace(&string);
string = &_Py_ID(print_file_and_line);
PyUnicode_InternInPlace(&string);
string = &_Py_ID(priority);
def test_stat_result_pickle(self):
result = os.stat(self.fname)
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
- p = pickle.dumps(result, proto)
- self.assertIn(b'stat_result', p)
- if proto < 4:
- self.assertIn(b'cos\nstat_result\n', p)
- unpickled = pickle.loads(p)
- self.assertEqual(result, unpickled)
+ with self.subTest(f'protocol {proto}'):
+ p = pickle.dumps(result, proto)
+ self.assertIn(b'stat_result', p)
+ if proto < 4:
+ self.assertIn(b'cos\nstat_result\n', p)
+ unpickled = pickle.loads(p)
+ self.assertEqual(result, unpickled)
@unittest.skipUnless(hasattr(os, 'statvfs'), 'test needs os.statvfs()')
def test_statvfs_attributes(self):
$(srcdir)/Include/internal/pycore_object.h \
$(srcdir)/Include/internal/pycore_obmalloc.h \
$(srcdir)/Include/internal/pycore_obmalloc_init.h \
+ $(srcdir)/Include/internal/pycore_os.h \
$(srcdir)/Include/internal/pycore_pathconfig.h \
$(srcdir)/Include/internal/pycore_pyarena.h \
$(srcdir)/Include/internal/pycore_pyerrors.h \
#ifdef MS_WINDOWS
# define INITFUNC PyInit_nt
# define MODNAME "nt"
+# define MODNAME_OBJ &_Py_ID(nt)
#else
# define INITFUNC PyInit_posix
# define MODNAME "posix"
+# define MODNAME_OBJ &_Py_ID(posix)
#endif
#if defined(__sun)
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
PyObject *SchedParamType;
#endif
+ newfunc statresult_new_orig;
PyObject *StatResultType;
PyObject *StatVFSResultType;
PyObject *TerminalSizeType;
5
};
#endif
-static newfunc structseq_new;
static PyObject *
statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
PyStructSequence *result;
int i;
+ // ht_module doesn't get set in PyStructSequence_NewType(),
+ // so we can't use PyType_GetModule().
+ PyObject *mod = PyImport_GetModule(MODNAME_OBJ);
+ if (mod == NULL) {
+ return NULL;
+ }
+ _posixstate *state = get_posix_state(mod);
+ if (state == NULL) {
+ return NULL;
+ }
+#define structseq_new state->statresult_new_orig
+
result = (PyStructSequence*)structseq_new(type, args, kwds);
if (!result)
return NULL;
}
-#ifndef MS_WINDOWS
-#define NEED_TICKS_PER_SECOND
-static long ticks_per_second = -1;
-#endif /* MS_WINDOWS */
+#ifdef _OS_NEED_TICKS_PER_SECOND
+#define ticks_per_second _PyRuntime.os.ticks_per_second
+static void
+ticks_per_second_init(void)
+{
+ if (ticks_per_second != -1) {
+ return;
+ }
+# if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)
+ ticks_per_second = sysconf(_SC_CLK_TCK);
+# elif defined(HZ)
+ ticks_per_second = HZ;
+# else
+ ticks_per_second = 60; /* magic fallback value; may be bogus */
+# endif
+}
+#endif
/*[clinic input]
os.times
(double)0,
(double)0);
}
+#elif !defined(_OS_NEED_TICKS_PER_SECOND)
+# error "missing ticks_per_second"
#else /* MS_WINDOWS */
{
-
-
struct tms t;
clock_t c;
errno = 0;
}
PyModule_AddObject(m, "stat_result", Py_NewRef(StatResultType));
state->StatResultType = StatResultType;
- structseq_new = ((PyTypeObject *)StatResultType)->tp_new;
+ state->statresult_new_orig = ((PyTypeObject *)StatResultType)->tp_new;
((PyTypeObject *)StatResultType)->tp_new = statresult_new;
statvfs_result_desc.name = "os.statvfs_result"; /* see issue #19209 */
}
PyModule_AddObject(m, "statvfs_result", Py_NewRef(StatVFSResultType));
state->StatVFSResultType = StatVFSResultType;
-#ifdef NEED_TICKS_PER_SECOND
-# if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)
- ticks_per_second = sysconf(_SC_CLK_TCK);
-# elif defined(HZ)
- ticks_per_second = HZ;
-# else
- ticks_per_second = 60; /* magic fallback value; may be bogus */
-# endif
+
+#ifdef _OS_NEED_TICKS_PER_SECOND
+ ticks_per_second_init();
#endif
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
<ClInclude Include="..\Include\internal\pycore_object.h" />
<ClInclude Include="..\Include\internal\pycore_obmalloc.h" />
<ClInclude Include="..\Include\internal\pycore_obmalloc_init.h" />
+ <ClInclude Include="..\Include\internal\pycore_os.h" />
<ClInclude Include="..\Include\internal\pycore_pathconfig.h" />
<ClInclude Include="..\Include\internal\pycore_pyarena.h" />
<ClInclude Include="..\Include\internal\pycore_pyerrors.h" />
<ClInclude Include="..\Include\internal\pycore_obmalloc_init.h">
<Filter>Include\internal</Filter>
</ClInclude>
+ <ClInclude Include="..\Include\internal\pycore_os.h">
+ <Filter>Include\internal</Filter>
+ </ClInclude>
<ClInclude Include="..\Include\internal\pycore_pathconfig.h">
<Filter>Include\internal</Filter>
</ClInclude>
##-----------------------
## initialized once
-Modules/posixmodule.c os_dup2_impl dup3_works -
-Modules/posixmodule.c - structseq_new -
-Modules/posixmodule.c - ticks_per_second -
Modules/timemodule.c _PyTime_GetClockWithInfo initialized -
Modules/timemodule.c _PyTime_GetProcessTimeWithInfo ticks_per_second -
# These are effectively const.
##-----------------------
-## process-global resources - set during first init
+## process-global resources
## indicators for resource availability/capability
+# (set during first init)
Python/bootstrap_hash.c py_getrandom getrandom_works -
Python/fileutils.c - _Py_open_cloexec_works -
Python/fileutils.c set_inheritable ioctl_works -
+# (set lazily, *after* first init)
+# XXX Is this thread-safe?
+Modules/posixmodule.c os_dup2_impl dup3_works -
-## resource init
+## resource init - set during first init
Python/thread.c - initialized -
Python/thread_pthread.h - condattr_monotonic -
# safe static buffer used during one-time initialization