• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /* System module */
3 
4 /*
5 Various bits of information used by the interpreter are collected in
6 module 'sys'.
7 Function member:
8 - exit(sts): raise SystemExit
9 Data members:
10 - stdin, stdout, stderr: standard file objects
11 - modules: the table of modules (dictionary)
12 - path: module search path (list of strings)
13 - argv: script arguments (list of strings)
14 - ps1, ps2: optional primary and secondary prompts (strings)
15 */
16 
17 #include "Python.h"
18 #include "pycore_call.h"          // _PyObject_CallNoArgs()
19 #include "pycore_ceval.h"         // _PyEval_SetAsyncGenFinalizer()
20 #include "pycore_dict.h"          // _PyDict_GetItemWithError()
21 #include "pycore_frame.h"         // _PyInterpreterFrame
22 #include "pycore_initconfig.h"    // _PyStatus_EXCEPTION()
23 #include "pycore_long.h"          // _PY_LONG_MAX_STR_DIGITS_THRESHOLD
24 #include "pycore_modsupport.h"    // _PyModule_CreateInitialized()
25 #include "pycore_namespace.h"     // _PyNamespace_New()
26 #include "pycore_object.h"        // _PyObject_DebugTypeStats()
27 #include "pycore_pathconfig.h"    // _PyPathConfig_ComputeSysPath0()
28 #include "pycore_pyerrors.h"      // _PyErr_GetRaisedException()
29 #include "pycore_pylifecycle.h"   // _PyErr_WriteUnraisableDefaultHook()
30 #include "pycore_pymath.h"        // _PY_SHORT_FLOAT_REPR
31 #include "pycore_pymem.h"         // _PyMem_SetDefaultAllocator()
32 #include "pycore_pystate.h"       // _PyThreadState_GET()
33 #include "pycore_pystats.h"       // _Py_PrintSpecializationStats()
34 #include "pycore_structseq.h"     // _PyStructSequence_InitBuiltinWithFlags()
35 #include "pycore_sysmodule.h"     // export _PySys_GetSizeOf()
36 #include "pycore_tuple.h"         // _PyTuple_FromArray()
37 
38 #include "pydtrace.h"             // PyDTrace_AUDIT()
39 #include "osdefs.h"               // DELIM
40 #include "stdlib_module_names.h"  // _Py_stdlib_module_names
41 
42 #ifdef HAVE_UNISTD_H
43 #  include <unistd.h>             // getpid()
44 #endif
45 
46 #ifdef MS_WINDOWS
47 #  define WIN32_LEAN_AND_MEAN
48 #  include <windows.h>
49 #endif /* MS_WINDOWS */
50 
51 #ifdef MS_COREDLL
52 extern void *PyWin_DLLhModule;
53 /* A string loaded from the DLL at startup: */
54 extern const char *PyWin_DLLVersionString;
55 #endif
56 
57 #ifdef __EMSCRIPTEN__
58 #  include <emscripten.h>
59 #endif
60 
61 #ifdef HAVE_FCNTL_H
62 #  include <fcntl.h>
63 #endif
64 
65 /*[clinic input]
66 module sys
67 [clinic start generated code]*/
68 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=3726b388feee8cea]*/
69 
70 #include "clinic/sysmodule.c.h"
71 
72 
73 PyObject *
_PySys_GetAttr(PyThreadState * tstate,PyObject * name)74 _PySys_GetAttr(PyThreadState *tstate, PyObject *name)
75 {
76     PyObject *sd = tstate->interp->sysdict;
77     if (sd == NULL) {
78         return NULL;
79     }
80     PyObject *exc = _PyErr_GetRaisedException(tstate);
81     /* XXX Suppress a new exception if it was raised and restore
82      * the old one. */
83     PyObject *value = _PyDict_GetItemWithError(sd, name);
84     _PyErr_SetRaisedException(tstate, exc);
85     return value;
86 }
87 
88 static PyObject *
_PySys_GetObject(PyInterpreterState * interp,const char * name)89 _PySys_GetObject(PyInterpreterState *interp, const char *name)
90 {
91     PyObject *sysdict = interp->sysdict;
92     if (sysdict == NULL) {
93         return NULL;
94     }
95     PyObject *value;
96     if (PyDict_GetItemStringRef(sysdict, name, &value) != 1) {
97         return NULL;
98     }
99     Py_DECREF(value);  // return a borrowed reference
100     return value;
101 }
102 
103 PyObject *
PySys_GetObject(const char * name)104 PySys_GetObject(const char *name)
105 {
106     PyThreadState *tstate = _PyThreadState_GET();
107 
108     PyObject *exc = _PyErr_GetRaisedException(tstate);
109     PyObject *value = _PySys_GetObject(tstate->interp, name);
110     /* XXX Suppress a new exception if it was raised and restore
111      * the old one. */
112     if (_PyErr_Occurred(tstate)) {
113         PyErr_FormatUnraisable("Exception ignored in PySys_GetObject()");
114     }
115     _PyErr_SetRaisedException(tstate, exc);
116     return value;
117 }
118 
119 static int
sys_set_object(PyInterpreterState * interp,PyObject * key,PyObject * v)120 sys_set_object(PyInterpreterState *interp, PyObject *key, PyObject *v)
121 {
122     if (key == NULL) {
123         return -1;
124     }
125     PyObject *sd = interp->sysdict;
126     if (v == NULL) {
127         if (PyDict_Pop(sd, key, NULL) < 0) {
128             return -1;
129         }
130         return 0;
131     }
132     else {
133         return PyDict_SetItem(sd, key, v);
134     }
135 }
136 
137 int
_PySys_SetAttr(PyObject * key,PyObject * v)138 _PySys_SetAttr(PyObject *key, PyObject *v)
139 {
140     PyInterpreterState *interp = _PyInterpreterState_GET();
141     return sys_set_object(interp, key, v);
142 }
143 
144 static int
sys_set_object_str(PyInterpreterState * interp,const char * name,PyObject * v)145 sys_set_object_str(PyInterpreterState *interp, const char *name, PyObject *v)
146 {
147     PyObject *key = v ? PyUnicode_InternFromString(name)
148                       : PyUnicode_FromString(name);
149     int r = sys_set_object(interp, key, v);
150     Py_XDECREF(key);
151     return r;
152 }
153 
154 int
PySys_SetObject(const char * name,PyObject * v)155 PySys_SetObject(const char *name, PyObject *v)
156 {
157     PyInterpreterState *interp = _PyInterpreterState_GET();
158     return sys_set_object_str(interp, name, v);
159 }
160 
161 int
_PySys_ClearAttrString(PyInterpreterState * interp,const char * name,int verbose)162 _PySys_ClearAttrString(PyInterpreterState *interp,
163                        const char *name, int verbose)
164 {
165     if (verbose) {
166         PySys_WriteStderr("# clear sys.%s\n", name);
167     }
168     /* To play it safe, we set the attr to None instead of deleting it. */
169     if (PyDict_SetItemString(interp->sysdict, name, Py_None) < 0) {
170         return -1;
171     }
172     return 0;
173 }
174 
175 
176 static int
should_audit(PyInterpreterState * interp)177 should_audit(PyInterpreterState *interp)
178 {
179     /* interp must not be NULL, but test it just in case for extra safety */
180     assert(interp != NULL);
181     if (!interp) {
182         return 0;
183     }
184     return (interp->runtime->audit_hooks.head
185             || interp->audit_hooks
186             || PyDTrace_AUDIT_ENABLED());
187 }
188 
189 
190 static int
sys_audit_tstate(PyThreadState * ts,const char * event,const char * argFormat,va_list vargs)191 sys_audit_tstate(PyThreadState *ts, const char *event,
192                  const char *argFormat, va_list vargs)
193 {
194     assert(event != NULL);
195     assert(!argFormat || !strchr(argFormat, 'N'));
196 
197     if (!ts) {
198         /* Audit hooks cannot be called with a NULL thread state */
199         return 0;
200     }
201 
202     /* The current implementation cannot be called if tstate is not
203        the current Python thread state. */
204     assert(ts == _PyThreadState_GET());
205 
206     /* Early exit when no hooks are registered */
207     PyInterpreterState *is = ts->interp;
208     if (!should_audit(is)) {
209         return 0;
210     }
211 
212     PyObject *eventName = NULL;
213     PyObject *eventArgs = NULL;
214     PyObject *hooks = NULL;
215     PyObject *hook = NULL;
216     int res = -1;
217 
218     int dtrace = PyDTrace_AUDIT_ENABLED();
219 
220 
221     PyObject *exc = _PyErr_GetRaisedException(ts);
222 
223     /* Initialize event args now */
224     if (argFormat && argFormat[0]) {
225         eventArgs = Py_VaBuildValue(argFormat, vargs);
226         if (eventArgs && !PyTuple_Check(eventArgs)) {
227             PyObject *argTuple = PyTuple_Pack(1, eventArgs);
228             Py_SETREF(eventArgs, argTuple);
229         }
230     }
231     else {
232         eventArgs = PyTuple_New(0);
233     }
234     if (!eventArgs) {
235         goto exit;
236     }
237 
238     /* Call global hooks
239      *
240      * We don't worry about any races on hooks getting added,
241      * since that would not leave is in an inconsistent state. */
242     _Py_AuditHookEntry *e = is->runtime->audit_hooks.head;
243     for (; e; e = e->next) {
244         if (e->hookCFunction(event, eventArgs, e->userData) < 0) {
245             goto exit;
246         }
247     }
248 
249     /* Dtrace USDT point */
250     if (dtrace) {
251         PyDTrace_AUDIT(event, (void *)eventArgs);
252     }
253 
254     /* Call interpreter hooks */
255     if (is->audit_hooks) {
256         eventName = PyUnicode_FromString(event);
257         if (!eventName) {
258             goto exit;
259         }
260 
261         hooks = PyObject_GetIter(is->audit_hooks);
262         if (!hooks) {
263             goto exit;
264         }
265 
266         /* Disallow tracing in hooks unless explicitly enabled */
267         PyThreadState_EnterTracing(ts);
268         while ((hook = PyIter_Next(hooks)) != NULL) {
269             PyObject *o;
270             int canTrace = PyObject_GetOptionalAttr(hook, &_Py_ID(__cantrace__), &o);
271             if (o) {
272                 canTrace = PyObject_IsTrue(o);
273                 Py_DECREF(o);
274             }
275             if (canTrace < 0) {
276                 break;
277             }
278             if (canTrace) {
279                 PyThreadState_LeaveTracing(ts);
280             }
281             PyObject* args[2] = {eventName, eventArgs};
282             o = _PyObject_VectorcallTstate(ts, hook, args, 2, NULL);
283             if (canTrace) {
284                 PyThreadState_EnterTracing(ts);
285             }
286             if (!o) {
287                 break;
288             }
289             Py_DECREF(o);
290             Py_CLEAR(hook);
291         }
292         PyThreadState_LeaveTracing(ts);
293         if (_PyErr_Occurred(ts)) {
294             goto exit;
295         }
296     }
297 
298     res = 0;
299 
300 exit:
301     Py_XDECREF(hook);
302     Py_XDECREF(hooks);
303     Py_XDECREF(eventName);
304     Py_XDECREF(eventArgs);
305 
306     if (!res) {
307         _PyErr_SetRaisedException(ts, exc);
308     }
309     else {
310         assert(_PyErr_Occurred(ts));
311         Py_XDECREF(exc);
312     }
313 
314     return res;
315 }
316 
317 int
_PySys_Audit(PyThreadState * tstate,const char * event,const char * argFormat,...)318 _PySys_Audit(PyThreadState *tstate, const char *event,
319              const char *argFormat, ...)
320 {
321     va_list vargs;
322     va_start(vargs, argFormat);
323     int res = sys_audit_tstate(tstate, event, argFormat, vargs);
324     va_end(vargs);
325     return res;
326 }
327 
328 int
PySys_Audit(const char * event,const char * argFormat,...)329 PySys_Audit(const char *event, const char *argFormat, ...)
330 {
331     PyThreadState *tstate = _PyThreadState_GET();
332     va_list vargs;
333     va_start(vargs, argFormat);
334     int res = sys_audit_tstate(tstate, event, argFormat, vargs);
335     va_end(vargs);
336     return res;
337 }
338 
339 int
PySys_AuditTuple(const char * event,PyObject * args)340 PySys_AuditTuple(const char *event, PyObject *args)
341 {
342     if (args == NULL) {
343         return PySys_Audit(event, NULL);
344     }
345 
346     if (!PyTuple_Check(args)) {
347         PyErr_Format(PyExc_TypeError, "args must be tuple, got %s",
348                      Py_TYPE(args)->tp_name);
349         return -1;
350     }
351     return PySys_Audit(event, "O", args);
352 }
353 
354 /* We expose this function primarily for our own cleanup during
355  * finalization. In general, it should not need to be called,
356  * and as such the function is not exported.
357  *
358  * Must be finalizing to clear hooks */
359 void
_PySys_ClearAuditHooks(PyThreadState * ts)360 _PySys_ClearAuditHooks(PyThreadState *ts)
361 {
362     assert(ts != NULL);
363     if (!ts) {
364         return;
365     }
366 
367     _PyRuntimeState *runtime = ts->interp->runtime;
368     /* The hooks are global so we have to check for runtime finalization. */
369     PyThreadState *finalizing = _PyRuntimeState_GetFinalizing(runtime);
370     assert(finalizing == ts);
371     if (finalizing != ts) {
372         return;
373     }
374 
375     const PyConfig *config = _PyInterpreterState_GetConfig(ts->interp);
376     if (config->verbose) {
377         PySys_WriteStderr("# clear sys.audit hooks\n");
378     }
379 
380     /* Hooks can abort later hooks for this event, but cannot
381        abort the clear operation itself. */
382     _PySys_Audit(ts, "cpython._PySys_ClearAuditHooks", NULL);
383     _PyErr_Clear(ts);
384 
385     /* We don't worry about the very unlikely race right here,
386      * since it's entirely benign.  Nothing else removes entries
387      * from the list and adding an entry right now would not cause
388      * any trouble. */
389     _Py_AuditHookEntry *e = runtime->audit_hooks.head, *n;
390     runtime->audit_hooks.head = NULL;
391     while (e) {
392         n = e->next;
393         PyMem_RawFree(e);
394         e = n;
395     }
396 }
397 
398 static void
add_audit_hook_entry_unlocked(_PyRuntimeState * runtime,_Py_AuditHookEntry * entry)399 add_audit_hook_entry_unlocked(_PyRuntimeState *runtime,
400                               _Py_AuditHookEntry *entry)
401 {
402     if (runtime->audit_hooks.head == NULL) {
403         runtime->audit_hooks.head = entry;
404     }
405     else {
406         _Py_AuditHookEntry *last = runtime->audit_hooks.head;
407         while (last->next) {
408             last = last->next;
409         }
410         last->next = entry;
411     }
412 }
413 
414 int
PySys_AddAuditHook(Py_AuditHookFunction hook,void * userData)415 PySys_AddAuditHook(Py_AuditHookFunction hook, void *userData)
416 {
417     /* tstate can be NULL, so access directly _PyRuntime:
418        PySys_AddAuditHook() can be called before Python is initialized. */
419     _PyRuntimeState *runtime = &_PyRuntime;
420     PyThreadState *tstate;
421     if (runtime->initialized) {
422         tstate = _PyThreadState_GET();
423     }
424     else {
425         tstate = NULL;
426     }
427 
428     /* Invoke existing audit hooks to allow them an opportunity to abort. */
429     /* Cannot invoke hooks until we are initialized */
430     if (tstate != NULL) {
431         if (_PySys_Audit(tstate, "sys.addaudithook", NULL) < 0) {
432             if (_PyErr_ExceptionMatches(tstate, PyExc_RuntimeError)) {
433                 /* We do not report errors derived from RuntimeError */
434                 _PyErr_Clear(tstate);
435                 return 0;
436             }
437             return -1;
438         }
439     }
440 
441     _Py_AuditHookEntry *e = (_Py_AuditHookEntry*)PyMem_RawMalloc(
442             sizeof(_Py_AuditHookEntry));
443     if (!e) {
444         if (tstate != NULL) {
445             _PyErr_NoMemory(tstate);
446         }
447         return -1;
448     }
449     e->next = NULL;
450     e->hookCFunction = (Py_AuditHookFunction)hook;
451     e->userData = userData;
452 
453     PyMutex_Lock(&runtime->audit_hooks.mutex);
454     add_audit_hook_entry_unlocked(runtime, e);
455     PyMutex_Unlock(&runtime->audit_hooks.mutex);
456 
457     return 0;
458 }
459 
460 /*[clinic input]
461 sys.addaudithook
462 
463     hook: object
464 
465 Adds a new audit hook callback.
466 [clinic start generated code]*/
467 
468 static PyObject *
sys_addaudithook_impl(PyObject * module,PyObject * hook)469 sys_addaudithook_impl(PyObject *module, PyObject *hook)
470 /*[clinic end generated code: output=4f9c17aaeb02f44e input=0f3e191217a45e34]*/
471 {
472     PyThreadState *tstate = _PyThreadState_GET();
473 
474     /* Invoke existing audit hooks to allow them an opportunity to abort. */
475     if (_PySys_Audit(tstate, "sys.addaudithook", NULL) < 0) {
476         if (_PyErr_ExceptionMatches(tstate, PyExc_Exception)) {
477             /* We do not report errors derived from Exception */
478             _PyErr_Clear(tstate);
479             Py_RETURN_NONE;
480         }
481         return NULL;
482     }
483 
484     PyInterpreterState *interp = tstate->interp;
485     if (interp->audit_hooks == NULL) {
486         interp->audit_hooks = PyList_New(0);
487         if (interp->audit_hooks == NULL) {
488             return NULL;
489         }
490         /* Avoid having our list of hooks show up in the GC module */
491         PyObject_GC_UnTrack(interp->audit_hooks);
492     }
493 
494     if (PyList_Append(interp->audit_hooks, hook) < 0) {
495         return NULL;
496     }
497 
498     Py_RETURN_NONE;
499 }
500 
501 PyDoc_STRVAR(audit_doc,
502 "audit($module, event, /, *args)\n\
503 --\n\
504 \n\
505 Passes the event to any audit hooks that are attached.");
506 
507 static PyObject *
sys_audit(PyObject * self,PyObject * const * args,Py_ssize_t argc)508 sys_audit(PyObject *self, PyObject *const *args, Py_ssize_t argc)
509 {
510     PyThreadState *tstate = _PyThreadState_GET();
511     _Py_EnsureTstateNotNULL(tstate);
512 
513     if (argc == 0) {
514         _PyErr_SetString(tstate, PyExc_TypeError,
515                          "audit() missing 1 required positional argument: "
516                          "'event'");
517         return NULL;
518     }
519 
520     assert(args[0] != NULL);
521 
522     if (!should_audit(tstate->interp)) {
523         Py_RETURN_NONE;
524     }
525 
526     PyObject *auditEvent = args[0];
527     if (!auditEvent) {
528         _PyErr_SetString(tstate, PyExc_TypeError,
529                          "expected str for argument 'event'");
530         return NULL;
531     }
532     if (!PyUnicode_Check(auditEvent)) {
533         _PyErr_Format(tstate, PyExc_TypeError,
534                       "expected str for argument 'event', not %.200s",
535                       Py_TYPE(auditEvent)->tp_name);
536         return NULL;
537     }
538     const char *event = PyUnicode_AsUTF8(auditEvent);
539     if (!event) {
540         return NULL;
541     }
542 
543     PyObject *auditArgs = _PyTuple_FromArray(args + 1, argc - 1);
544     if (!auditArgs) {
545         return NULL;
546     }
547 
548     int res = _PySys_Audit(tstate, event, "O", auditArgs);
549     Py_DECREF(auditArgs);
550 
551     if (res < 0) {
552         return NULL;
553     }
554 
555     Py_RETURN_NONE;
556 }
557 
558 
559 static PyObject *
sys_breakpointhook(PyObject * self,PyObject * const * args,Py_ssize_t nargs,PyObject * keywords)560 sys_breakpointhook(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *keywords)
561 {
562     PyThreadState *tstate = _PyThreadState_GET();
563     assert(!_PyErr_Occurred(tstate));
564     char *envar = Py_GETENV("PYTHONBREAKPOINT");
565 
566     if (envar == NULL || strlen(envar) == 0) {
567         envar = "pdb.set_trace";
568     }
569     else if (!strcmp(envar, "0")) {
570         /* The breakpoint is explicitly no-op'd. */
571         Py_RETURN_NONE;
572     }
573     /* According to POSIX the string returned by getenv() might be invalidated
574      * or the string content might be overwritten by a subsequent call to
575      * getenv().  Since importing a module can performs the getenv() calls,
576      * we need to save a copy of envar. */
577     envar = _PyMem_RawStrdup(envar);
578     if (envar == NULL) {
579         _PyErr_NoMemory(tstate);
580         return NULL;
581     }
582     const char *last_dot = strrchr(envar, '.');
583     const char *attrname = NULL;
584     PyObject *modulepath = NULL;
585 
586     if (last_dot == NULL) {
587         /* The breakpoint is a built-in, e.g. PYTHONBREAKPOINT=int */
588         modulepath = PyUnicode_FromString("builtins");
589         attrname = envar;
590     }
591     else if (last_dot != envar) {
592         /* Split on the last dot; */
593         modulepath = PyUnicode_FromStringAndSize(envar, last_dot - envar);
594         attrname = last_dot + 1;
595     }
596     else {
597         goto warn;
598     }
599     if (modulepath == NULL) {
600         PyMem_RawFree(envar);
601         return NULL;
602     }
603 
604     PyObject *module = PyImport_Import(modulepath);
605     Py_DECREF(modulepath);
606 
607     if (module == NULL) {
608         if (_PyErr_ExceptionMatches(tstate, PyExc_ImportError)) {
609             goto warn;
610         }
611         PyMem_RawFree(envar);
612         return NULL;
613     }
614 
615     PyObject *hook = PyObject_GetAttrString(module, attrname);
616     Py_DECREF(module);
617 
618     if (hook == NULL) {
619         if (_PyErr_ExceptionMatches(tstate, PyExc_AttributeError)) {
620             goto warn;
621         }
622         PyMem_RawFree(envar);
623         return NULL;
624     }
625     PyMem_RawFree(envar);
626     PyObject *retval = PyObject_Vectorcall(hook, args, nargs, keywords);
627     Py_DECREF(hook);
628     return retval;
629 
630   warn:
631     /* If any of the imports went wrong, then warn and ignore. */
632     _PyErr_Clear(tstate);
633     int status = PyErr_WarnFormat(
634         PyExc_RuntimeWarning, 0,
635         "Ignoring unimportable $PYTHONBREAKPOINT: \"%s\"", envar);
636     PyMem_RawFree(envar);
637     if (status < 0) {
638         /* Printing the warning raised an exception. */
639         return NULL;
640     }
641     /* The warning was (probably) issued. */
642     Py_RETURN_NONE;
643 }
644 
645 PyDoc_STRVAR(breakpointhook_doc,
646 "breakpointhook($module, /, *args, **kwargs)\n"
647 "--\n"
648 "\n"
649 "This hook function is called by built-in breakpoint().\n"
650 );
651 
652 /* Write repr(o) to sys.stdout using sys.stdout.encoding and 'backslashreplace'
653    error handler. If sys.stdout has a buffer attribute, use
654    sys.stdout.buffer.write(encoded), otherwise redecode the string and use
655    sys.stdout.write(redecoded).
656 
657    Helper function for sys_displayhook(). */
658 static int
sys_displayhook_unencodable(PyObject * outf,PyObject * o)659 sys_displayhook_unencodable(PyObject *outf, PyObject *o)
660 {
661     PyObject *stdout_encoding = NULL;
662     PyObject *encoded, *escaped_str, *repr_str, *buffer, *result;
663     const char *stdout_encoding_str;
664     int ret;
665 
666     stdout_encoding = PyObject_GetAttr(outf, &_Py_ID(encoding));
667     if (stdout_encoding == NULL)
668         goto error;
669     stdout_encoding_str = PyUnicode_AsUTF8(stdout_encoding);
670     if (stdout_encoding_str == NULL)
671         goto error;
672 
673     repr_str = PyObject_Repr(o);
674     if (repr_str == NULL)
675         goto error;
676     encoded = PyUnicode_AsEncodedString(repr_str,
677                                         stdout_encoding_str,
678                                         "backslashreplace");
679     Py_DECREF(repr_str);
680     if (encoded == NULL)
681         goto error;
682 
683     if (PyObject_GetOptionalAttr(outf, &_Py_ID(buffer), &buffer) < 0) {
684         Py_DECREF(encoded);
685         goto error;
686     }
687     if (buffer) {
688         result = PyObject_CallMethodOneArg(buffer, &_Py_ID(write), encoded);
689         Py_DECREF(buffer);
690         Py_DECREF(encoded);
691         if (result == NULL)
692             goto error;
693         Py_DECREF(result);
694     }
695     else {
696         escaped_str = PyUnicode_FromEncodedObject(encoded,
697                                                   stdout_encoding_str,
698                                                   "strict");
699         Py_DECREF(encoded);
700         if (PyFile_WriteObject(escaped_str, outf, Py_PRINT_RAW) != 0) {
701             Py_DECREF(escaped_str);
702             goto error;
703         }
704         Py_DECREF(escaped_str);
705     }
706     ret = 0;
707     goto finally;
708 
709 error:
710     ret = -1;
711 finally:
712     Py_XDECREF(stdout_encoding);
713     return ret;
714 }
715 
716 /*[clinic input]
717 sys.displayhook
718 
719     object as o: object
720     /
721 
722 Print an object to sys.stdout and also save it in builtins._
723 [clinic start generated code]*/
724 
725 static PyObject *
sys_displayhook(PyObject * module,PyObject * o)726 sys_displayhook(PyObject *module, PyObject *o)
727 /*[clinic end generated code: output=347477d006df92ed input=08ba730166d7ef72]*/
728 {
729     PyObject *outf;
730     PyObject *builtins;
731     PyThreadState *tstate = _PyThreadState_GET();
732 
733     builtins = PyImport_GetModule(&_Py_ID(builtins));
734     if (builtins == NULL) {
735         if (!_PyErr_Occurred(tstate)) {
736             _PyErr_SetString(tstate, PyExc_RuntimeError,
737                              "lost builtins module");
738         }
739         return NULL;
740     }
741     Py_DECREF(builtins);
742 
743     /* Print value except if None */
744     /* After printing, also assign to '_' */
745     /* Before, set '_' to None to avoid recursion */
746     if (o == Py_None) {
747         Py_RETURN_NONE;
748     }
749     if (PyObject_SetAttr(builtins, _Py_LATIN1_CHR('_'), Py_None) != 0)
750         return NULL;
751     outf = _PySys_GetAttr(tstate, &_Py_ID(stdout));
752     if (outf == NULL || outf == Py_None) {
753         _PyErr_SetString(tstate, PyExc_RuntimeError, "lost sys.stdout");
754         return NULL;
755     }
756     if (PyFile_WriteObject(o, outf, 0) != 0) {
757         if (_PyErr_ExceptionMatches(tstate, PyExc_UnicodeEncodeError)) {
758             int err;
759             /* repr(o) is not encodable to sys.stdout.encoding with
760              * sys.stdout.errors error handler (which is probably 'strict') */
761             _PyErr_Clear(tstate);
762             err = sys_displayhook_unencodable(outf, o);
763             if (err) {
764                 return NULL;
765             }
766         }
767         else {
768             return NULL;
769         }
770     }
771     if (PyFile_WriteObject(_Py_LATIN1_CHR('\n'), outf, Py_PRINT_RAW) != 0)
772         return NULL;
773     if (PyObject_SetAttr(builtins, _Py_LATIN1_CHR('_'), o) != 0)
774         return NULL;
775     Py_RETURN_NONE;
776 }
777 
778 
779 /*[clinic input]
780 sys.excepthook
781 
782     exctype:   object
783     value:     object
784     traceback: object
785     /
786 
787 Handle an exception by displaying it with a traceback on sys.stderr.
788 [clinic start generated code]*/
789 
790 static PyObject *
sys_excepthook_impl(PyObject * module,PyObject * exctype,PyObject * value,PyObject * traceback)791 sys_excepthook_impl(PyObject *module, PyObject *exctype, PyObject *value,
792                     PyObject *traceback)
793 /*[clinic end generated code: output=18d99fdda21b6b5e input=ecf606fa826f19d9]*/
794 {
795     PyErr_Display(NULL, value, traceback);
796     Py_RETURN_NONE;
797 }
798 
799 
800 /*[clinic input]
801 sys.exception
802 
803 Return the current exception.
804 
805 Return the most recent exception caught by an except clause
806 in the current stack frame or in an older stack frame, or None
807 if no such exception exists.
808 [clinic start generated code]*/
809 
810 static PyObject *
sys_exception_impl(PyObject * module)811 sys_exception_impl(PyObject *module)
812 /*[clinic end generated code: output=2381ee2f25953e40 input=c88fbb94b6287431]*/
813 {
814     _PyErr_StackItem *err_info = _PyErr_GetTopmostException(_PyThreadState_GET());
815     if (err_info->exc_value != NULL) {
816         return Py_NewRef(err_info->exc_value);
817     }
818     Py_RETURN_NONE;
819 }
820 
821 
822 /*[clinic input]
823 sys.exc_info
824 
825 Return current exception information: (type, value, traceback).
826 
827 Return information about the most recent exception caught by an except
828 clause in the current stack frame or in an older stack frame.
829 [clinic start generated code]*/
830 
831 static PyObject *
sys_exc_info_impl(PyObject * module)832 sys_exc_info_impl(PyObject *module)
833 /*[clinic end generated code: output=3afd0940cf3a4d30 input=b5c5bf077788a3e5]*/
834 {
835     _PyErr_StackItem *err_info = _PyErr_GetTopmostException(_PyThreadState_GET());
836     return _PyErr_StackItemToExcInfoTuple(err_info);
837 }
838 
839 
840 /*[clinic input]
841 sys.unraisablehook
842 
843     unraisable: object
844     /
845 
846 Handle an unraisable exception.
847 
848 The unraisable argument has the following attributes:
849 
850 * exc_type: Exception type.
851 * exc_value: Exception value, can be None.
852 * exc_traceback: Exception traceback, can be None.
853 * err_msg: Error message, can be None.
854 * object: Object causing the exception, can be None.
855 [clinic start generated code]*/
856 
857 static PyObject *
sys_unraisablehook(PyObject * module,PyObject * unraisable)858 sys_unraisablehook(PyObject *module, PyObject *unraisable)
859 /*[clinic end generated code: output=bb92838b32abaa14 input=ec3af148294af8d3]*/
860 {
861     return _PyErr_WriteUnraisableDefaultHook(unraisable);
862 }
863 
864 
865 /*[clinic input]
866 sys.exit
867 
868     status: object = None
869     /
870 
871 Exit the interpreter by raising SystemExit(status).
872 
873 If the status is omitted or None, it defaults to zero (i.e., success).
874 If the status is an integer, it will be used as the system exit status.
875 If it is another kind of object, it will be printed and the system
876 exit status will be one (i.e., failure).
877 [clinic start generated code]*/
878 
879 static PyObject *
sys_exit_impl(PyObject * module,PyObject * status)880 sys_exit_impl(PyObject *module, PyObject *status)
881 /*[clinic end generated code: output=13870986c1ab2ec0 input=b86ca9497baa94f2]*/
882 {
883     /* Raise SystemExit so callers may catch it or clean up. */
884     PyErr_SetObject(PyExc_SystemExit, status);
885     return NULL;
886 }
887 
888 
889 static PyObject *
get_utf8_unicode(void)890 get_utf8_unicode(void)
891 {
892     _Py_DECLARE_STR(utf_8, "utf-8");
893     PyObject *ret = &_Py_STR(utf_8);
894     return Py_NewRef(ret);
895 }
896 
897 /*[clinic input]
898 sys.getdefaultencoding
899 
900 Return the current default encoding used by the Unicode implementation.
901 [clinic start generated code]*/
902 
903 static PyObject *
sys_getdefaultencoding_impl(PyObject * module)904 sys_getdefaultencoding_impl(PyObject *module)
905 /*[clinic end generated code: output=256d19dfcc0711e6 input=d416856ddbef6909]*/
906 {
907     return get_utf8_unicode();
908 }
909 
910 /*[clinic input]
911 sys.getfilesystemencoding
912 
913 Return the encoding used to convert Unicode filenames to OS filenames.
914 [clinic start generated code]*/
915 
916 static PyObject *
sys_getfilesystemencoding_impl(PyObject * module)917 sys_getfilesystemencoding_impl(PyObject *module)
918 /*[clinic end generated code: output=1dc4bdbe9be44aa7 input=8475f8649b8c7d8c]*/
919 {
920     PyInterpreterState *interp = _PyInterpreterState_GET();
921     const PyConfig *config = _PyInterpreterState_GetConfig(interp);
922 
923     if (wcscmp(config->filesystem_encoding, L"utf-8") == 0) {
924         return get_utf8_unicode();
925     }
926 
927     PyObject *u = PyUnicode_FromWideChar(config->filesystem_encoding, -1);
928     if (u == NULL) {
929         return NULL;
930     }
931     _PyUnicode_InternImmortal(interp, &u);
932     return u;
933 }
934 
935 /*[clinic input]
936 sys.getfilesystemencodeerrors
937 
938 Return the error mode used Unicode to OS filename conversion.
939 [clinic start generated code]*/
940 
941 static PyObject *
sys_getfilesystemencodeerrors_impl(PyObject * module)942 sys_getfilesystemencodeerrors_impl(PyObject *module)
943 /*[clinic end generated code: output=ba77b36bbf7c96f5 input=22a1e8365566f1e5]*/
944 {
945     PyInterpreterState *interp = _PyInterpreterState_GET();
946     const PyConfig *config = _PyInterpreterState_GetConfig(interp);
947     PyObject *u = PyUnicode_FromWideChar(config->filesystem_errors, -1);
948     if (u == NULL) {
949         return NULL;
950     }
951     _PyUnicode_InternImmortal(interp, &u);
952     return u;
953 }
954 
955 /*[clinic input]
956 sys.intern
957 
958     string as s: unicode
959     /
960 
961 ``Intern'' the given string.
962 
963 This enters the string in the (global) table of interned strings whose
964 purpose is to speed up dictionary lookups. Return the string itself or
965 the previously interned string object with the same value.
966 [clinic start generated code]*/
967 
968 static PyObject *
sys_intern_impl(PyObject * module,PyObject * s)969 sys_intern_impl(PyObject *module, PyObject *s)
970 /*[clinic end generated code: output=be680c24f5c9e5d6 input=849483c006924e2f]*/
971 {
972     if (PyUnicode_CheckExact(s)) {
973         PyInterpreterState *interp = _PyInterpreterState_GET();
974         Py_INCREF(s);
975         _PyUnicode_InternMortal(interp, &s);
976         return s;
977     }
978     else {
979         PyErr_Format(PyExc_TypeError,
980                      "can't intern %.400s", Py_TYPE(s)->tp_name);
981         return NULL;
982     }
983 }
984 
985 
986 /*[clinic input]
987 sys._is_interned -> bool
988 
989   string: unicode
990   /
991 
992 Return True if the given string is "interned".
993 [clinic start generated code]*/
994 
995 static int
sys__is_interned_impl(PyObject * module,PyObject * string)996 sys__is_interned_impl(PyObject *module, PyObject *string)
997 /*[clinic end generated code: output=c3678267b4e9d7ed input=039843e17883b606]*/
998 {
999     return PyUnicode_CHECK_INTERNED(string);
1000 }
1001 
1002 
1003 /*
1004  * Cached interned string objects used for calling the profile and
1005  * trace functions.
1006  */
1007 static PyObject *whatstrings[8] = {
1008    &_Py_ID(call),
1009    &_Py_ID(exception),
1010    &_Py_ID(line),
1011    &_Py_ID(return),
1012    &_Py_ID(c_call),
1013    &_Py_ID(c_exception),
1014    &_Py_ID(c_return),
1015    &_Py_ID(opcode),
1016 };
1017 
1018 
1019 static PyObject *
call_trampoline(PyThreadState * tstate,PyObject * callback,PyFrameObject * frame,int what,PyObject * arg)1020 call_trampoline(PyThreadState *tstate, PyObject* callback,
1021                 PyFrameObject *frame, int what, PyObject *arg)
1022 {
1023     /* call the Python-level function */
1024     if (arg == NULL) {
1025         arg = Py_None;
1026     }
1027     PyObject *args[3] = {(PyObject *)frame, whatstrings[what], arg};
1028     PyObject *result = _PyObject_VectorcallTstate(tstate, callback, args, 3, NULL);
1029 
1030     return result;
1031 }
1032 
1033 static int
profile_trampoline(PyObject * self,PyFrameObject * frame,int what,PyObject * arg)1034 profile_trampoline(PyObject *self, PyFrameObject *frame,
1035                    int what, PyObject *arg)
1036 {
1037     PyThreadState *tstate = _PyThreadState_GET();
1038     PyObject *result = call_trampoline(tstate, self, frame, what, arg);
1039     if (result == NULL) {
1040         _PyEval_SetProfile(tstate, NULL, NULL);
1041         return -1;
1042     }
1043 
1044     Py_DECREF(result);
1045     return 0;
1046 }
1047 
1048 static int
trace_trampoline(PyObject * self,PyFrameObject * frame,int what,PyObject * arg)1049 trace_trampoline(PyObject *self, PyFrameObject *frame,
1050                  int what, PyObject *arg)
1051 {
1052     PyObject *callback;
1053     if (what == PyTrace_CALL) {
1054         callback = self;
1055     }
1056     else {
1057         callback = frame->f_trace;
1058     }
1059     if (callback == NULL) {
1060         return 0;
1061     }
1062 
1063     PyThreadState *tstate = _PyThreadState_GET();
1064     PyObject *result = call_trampoline(tstate, callback, frame, what, arg);
1065     if (result == NULL) {
1066         _PyEval_SetTrace(tstate, NULL, NULL);
1067         Py_CLEAR(frame->f_trace);
1068         return -1;
1069     }
1070 
1071     if (result != Py_None) {
1072         Py_XSETREF(frame->f_trace, result);
1073     }
1074     else {
1075         Py_DECREF(result);
1076     }
1077     return 0;
1078 }
1079 
1080 /*[clinic input]
1081 sys.settrace
1082 
1083     function: object
1084     /
1085 
1086 Set the global debug tracing function.
1087 
1088 It will be called on each function call.  See the debugger chapter
1089 in the library manual.
1090 [clinic start generated code]*/
1091 
1092 static PyObject *
sys_settrace(PyObject * module,PyObject * function)1093 sys_settrace(PyObject *module, PyObject *function)
1094 /*[clinic end generated code: output=999d12e9d6ec4678 input=8107feb01c5f1c4e]*/
1095 {
1096     PyThreadState *tstate = _PyThreadState_GET();
1097     if (function == Py_None) {
1098         if (_PyEval_SetTrace(tstate, NULL, NULL) < 0) {
1099             return NULL;
1100         }
1101     }
1102     else {
1103         if (_PyEval_SetTrace(tstate, trace_trampoline, function) < 0) {
1104             return NULL;
1105         }
1106     }
1107     Py_RETURN_NONE;
1108 }
1109 
1110 /*[clinic input]
1111 sys._settraceallthreads
1112 
1113     function as arg: object
1114     /
1115 
1116 Set the global debug tracing function in all running threads belonging to the current interpreter.
1117 
1118 It will be called on each function call. See the debugger chapter
1119 in the library manual.
1120 [clinic start generated code]*/
1121 
1122 static PyObject *
sys__settraceallthreads(PyObject * module,PyObject * arg)1123 sys__settraceallthreads(PyObject *module, PyObject *arg)
1124 /*[clinic end generated code: output=161cca30207bf3ca input=d4bde1f810d73675]*/
1125 {
1126     PyObject* argument = NULL;
1127     Py_tracefunc func = NULL;
1128 
1129     if (arg != Py_None) {
1130         func = trace_trampoline;
1131         argument = arg;
1132     }
1133 
1134 
1135     PyEval_SetTraceAllThreads(func, argument);
1136 
1137     Py_RETURN_NONE;
1138 }
1139 
1140 /*[clinic input]
1141 sys.gettrace
1142 
1143 Return the global debug tracing function set with sys.settrace.
1144 
1145 See the debugger chapter in the library manual.
1146 [clinic start generated code]*/
1147 
1148 static PyObject *
sys_gettrace_impl(PyObject * module)1149 sys_gettrace_impl(PyObject *module)
1150 /*[clinic end generated code: output=e97e3a4d8c971b6e input=373b51bb2147f4d8]*/
1151 {
1152     PyThreadState *tstate = _PyThreadState_GET();
1153     PyObject *temp = tstate->c_traceobj;
1154 
1155     if (temp == NULL)
1156         temp = Py_None;
1157     return Py_NewRef(temp);
1158 }
1159 
1160 /*[clinic input]
1161 sys.setprofile
1162 
1163     function: object
1164     /
1165 
1166 Set the profiling function.
1167 
1168 It will be called on each function call and return.  See the profiler
1169 chapter in the library manual.
1170 [clinic start generated code]*/
1171 
1172 static PyObject *
sys_setprofile(PyObject * module,PyObject * function)1173 sys_setprofile(PyObject *module, PyObject *function)
1174 /*[clinic end generated code: output=1c3503105939db9c input=055d0d7961413a62]*/
1175 {
1176     PyThreadState *tstate = _PyThreadState_GET();
1177     if (function == Py_None) {
1178         if (_PyEval_SetProfile(tstate, NULL, NULL) < 0) {
1179             return NULL;
1180         }
1181     }
1182     else {
1183         if (_PyEval_SetProfile(tstate, profile_trampoline, function) < 0) {
1184             return NULL;
1185         }
1186     }
1187     Py_RETURN_NONE;
1188 }
1189 
1190 /*[clinic input]
1191 sys._setprofileallthreads
1192 
1193     function as arg: object
1194     /
1195 
1196 Set the profiling function in all running threads belonging to the current interpreter.
1197 
1198 It will be called on each function call and return.  See the profiler
1199 chapter in the library manual.
1200 [clinic start generated code]*/
1201 
1202 static PyObject *
sys__setprofileallthreads(PyObject * module,PyObject * arg)1203 sys__setprofileallthreads(PyObject *module, PyObject *arg)
1204 /*[clinic end generated code: output=2d61319e27b309fe input=a10589439ba20cee]*/
1205 {
1206     PyObject* argument = NULL;
1207     Py_tracefunc func = NULL;
1208 
1209     if (arg != Py_None) {
1210         func = profile_trampoline;
1211         argument = arg;
1212     }
1213 
1214     PyEval_SetProfileAllThreads(func, argument);
1215 
1216     Py_RETURN_NONE;
1217 }
1218 
1219 /*[clinic input]
1220 sys.getprofile
1221 
1222 Return the profiling function set with sys.setprofile.
1223 
1224 See the profiler chapter in the library manual.
1225 [clinic start generated code]*/
1226 
1227 static PyObject *
sys_getprofile_impl(PyObject * module)1228 sys_getprofile_impl(PyObject *module)
1229 /*[clinic end generated code: output=579b96b373448188 input=1b3209d89a32965d]*/
1230 {
1231     PyThreadState *tstate = _PyThreadState_GET();
1232     PyObject *temp = tstate->c_profileobj;
1233 
1234     if (temp == NULL)
1235         temp = Py_None;
1236     return Py_NewRef(temp);
1237 }
1238 
1239 
1240 /*[clinic input]
1241 sys.setswitchinterval
1242 
1243     interval: double
1244     /
1245 
1246 Set the ideal thread switching delay inside the Python interpreter.
1247 
1248 The actual frequency of switching threads can be lower if the
1249 interpreter executes long sequences of uninterruptible code
1250 (this is implementation-specific and workload-dependent).
1251 
1252 The parameter must represent the desired switching delay in seconds
1253 A typical value is 0.005 (5 milliseconds).
1254 [clinic start generated code]*/
1255 
1256 static PyObject *
sys_setswitchinterval_impl(PyObject * module,double interval)1257 sys_setswitchinterval_impl(PyObject *module, double interval)
1258 /*[clinic end generated code: output=65a19629e5153983 input=561b477134df91d9]*/
1259 {
1260     if (interval <= 0.0) {
1261         PyErr_SetString(PyExc_ValueError,
1262                         "switch interval must be strictly positive");
1263         return NULL;
1264     }
1265     _PyEval_SetSwitchInterval((unsigned long) (1e6 * interval));
1266     Py_RETURN_NONE;
1267 }
1268 
1269 
1270 /*[clinic input]
1271 sys.getswitchinterval -> double
1272 
1273 Return the current thread switch interval; see sys.setswitchinterval().
1274 [clinic start generated code]*/
1275 
1276 static double
sys_getswitchinterval_impl(PyObject * module)1277 sys_getswitchinterval_impl(PyObject *module)
1278 /*[clinic end generated code: output=a38c277c85b5096d input=bdf9d39c0ebbbb6f]*/
1279 {
1280     return 1e-6 * _PyEval_GetSwitchInterval();
1281 }
1282 
1283 /*[clinic input]
1284 sys.setrecursionlimit
1285 
1286     limit as new_limit: int
1287     /
1288 
1289 Set the maximum depth of the Python interpreter stack to n.
1290 
1291 This limit prevents infinite recursion from causing an overflow of the C
1292 stack and crashing Python.  The highest possible limit is platform-
1293 dependent.
1294 [clinic start generated code]*/
1295 
1296 static PyObject *
sys_setrecursionlimit_impl(PyObject * module,int new_limit)1297 sys_setrecursionlimit_impl(PyObject *module, int new_limit)
1298 /*[clinic end generated code: output=35e1c64754800ace input=b0f7a23393924af3]*/
1299 {
1300     PyThreadState *tstate = _PyThreadState_GET();
1301 
1302     if (new_limit < 1) {
1303         _PyErr_SetString(tstate, PyExc_ValueError,
1304                          "recursion limit must be greater or equal than 1");
1305         return NULL;
1306     }
1307 
1308     /* Reject too low new limit if the current recursion depth is higher than
1309        the new low-water mark. */
1310     int depth = tstate->py_recursion_limit - tstate->py_recursion_remaining;
1311     if (depth >= new_limit) {
1312         _PyErr_Format(tstate, PyExc_RecursionError,
1313                       "cannot set the recursion limit to %i at "
1314                       "the recursion depth %i: the limit is too low",
1315                       new_limit, depth);
1316         return NULL;
1317     }
1318 
1319     Py_SetRecursionLimit(new_limit);
1320     Py_RETURN_NONE;
1321 }
1322 
1323 /*[clinic input]
1324 sys.set_coroutine_origin_tracking_depth
1325 
1326   depth: int
1327 
1328 Enable or disable origin tracking for coroutine objects in this thread.
1329 
1330 Coroutine objects will track 'depth' frames of traceback information
1331 about where they came from, available in their cr_origin attribute.
1332 
1333 Set a depth of 0 to disable.
1334 [clinic start generated code]*/
1335 
1336 static PyObject *
sys_set_coroutine_origin_tracking_depth_impl(PyObject * module,int depth)1337 sys_set_coroutine_origin_tracking_depth_impl(PyObject *module, int depth)
1338 /*[clinic end generated code: output=0a2123c1cc6759c5 input=a1d0a05f89d2c426]*/
1339 {
1340     if (_PyEval_SetCoroutineOriginTrackingDepth(depth) < 0) {
1341         return NULL;
1342     }
1343     Py_RETURN_NONE;
1344 }
1345 
1346 /*[clinic input]
1347 sys.get_coroutine_origin_tracking_depth -> int
1348 
1349 Check status of origin tracking for coroutine objects in this thread.
1350 [clinic start generated code]*/
1351 
1352 static int
sys_get_coroutine_origin_tracking_depth_impl(PyObject * module)1353 sys_get_coroutine_origin_tracking_depth_impl(PyObject *module)
1354 /*[clinic end generated code: output=3699f7be95a3afb8 input=335266a71205b61a]*/
1355 {
1356     return _PyEval_GetCoroutineOriginTrackingDepth();
1357 }
1358 
1359 static PyTypeObject AsyncGenHooksType;
1360 
1361 PyDoc_STRVAR(asyncgen_hooks_doc,
1362 "asyncgen_hooks\n\
1363 \n\
1364 A named tuple providing information about asynchronous\n\
1365 generators hooks.  The attributes are read only.");
1366 
1367 static PyStructSequence_Field asyncgen_hooks_fields[] = {
1368     {"firstiter", "Hook to intercept first iteration"},
1369     {"finalizer", "Hook to intercept finalization"},
1370     {0}
1371 };
1372 
1373 static PyStructSequence_Desc asyncgen_hooks_desc = {
1374     "asyncgen_hooks",          /* name */
1375     asyncgen_hooks_doc,        /* doc */
1376     asyncgen_hooks_fields ,    /* fields */
1377     2
1378 };
1379 
1380 static PyObject *
sys_set_asyncgen_hooks(PyObject * self,PyObject * args,PyObject * kw)1381 sys_set_asyncgen_hooks(PyObject *self, PyObject *args, PyObject *kw)
1382 {
1383     static char *keywords[] = {"firstiter", "finalizer", NULL};
1384     PyObject *firstiter = NULL;
1385     PyObject *finalizer = NULL;
1386 
1387     if (!PyArg_ParseTupleAndKeywords(
1388             args, kw, "|OO", keywords,
1389             &firstiter, &finalizer)) {
1390         return NULL;
1391     }
1392 
1393     if (finalizer && finalizer != Py_None) {
1394         if (!PyCallable_Check(finalizer)) {
1395             PyErr_Format(PyExc_TypeError,
1396                          "callable finalizer expected, got %.50s",
1397                          Py_TYPE(finalizer)->tp_name);
1398             return NULL;
1399         }
1400     }
1401 
1402     if (firstiter && firstiter != Py_None) {
1403         if (!PyCallable_Check(firstiter)) {
1404             PyErr_Format(PyExc_TypeError,
1405                          "callable firstiter expected, got %.50s",
1406                          Py_TYPE(firstiter)->tp_name);
1407             return NULL;
1408         }
1409     }
1410 
1411     PyObject *cur_finalizer = _PyEval_GetAsyncGenFinalizer();
1412 
1413     if (finalizer && finalizer != Py_None) {
1414         if (_PyEval_SetAsyncGenFinalizer(finalizer) < 0) {
1415             return NULL;
1416         }
1417     }
1418     else if (finalizer == Py_None && _PyEval_SetAsyncGenFinalizer(NULL) < 0) {
1419         return NULL;
1420     }
1421 
1422     if (firstiter && firstiter != Py_None) {
1423         if (_PyEval_SetAsyncGenFirstiter(firstiter) < 0) {
1424             goto error;
1425         }
1426     }
1427     else if (firstiter == Py_None && _PyEval_SetAsyncGenFirstiter(NULL) < 0) {
1428         goto error;
1429     }
1430 
1431     Py_RETURN_NONE;
1432 
1433 error:
1434     _PyEval_SetAsyncGenFinalizer(cur_finalizer);
1435     return NULL;
1436 }
1437 
1438 PyDoc_STRVAR(set_asyncgen_hooks_doc,
1439 "set_asyncgen_hooks([firstiter] [, finalizer])\n\
1440 \n\
1441 Set a finalizer for async generators objects."
1442 );
1443 
1444 /*[clinic input]
1445 sys.get_asyncgen_hooks
1446 
1447 Return the installed asynchronous generators hooks.
1448 
1449 This returns a namedtuple of the form (firstiter, finalizer).
1450 [clinic start generated code]*/
1451 
1452 static PyObject *
sys_get_asyncgen_hooks_impl(PyObject * module)1453 sys_get_asyncgen_hooks_impl(PyObject *module)
1454 /*[clinic end generated code: output=53a253707146f6cf input=3676b9ea62b14625]*/
1455 {
1456     PyObject *res;
1457     PyObject *firstiter = _PyEval_GetAsyncGenFirstiter();
1458     PyObject *finalizer = _PyEval_GetAsyncGenFinalizer();
1459 
1460     res = PyStructSequence_New(&AsyncGenHooksType);
1461     if (res == NULL) {
1462         return NULL;
1463     }
1464 
1465     if (firstiter == NULL) {
1466         firstiter = Py_None;
1467     }
1468 
1469     if (finalizer == NULL) {
1470         finalizer = Py_None;
1471     }
1472 
1473     PyStructSequence_SET_ITEM(res, 0, Py_NewRef(firstiter));
1474     PyStructSequence_SET_ITEM(res, 1, Py_NewRef(finalizer));
1475 
1476     return res;
1477 }
1478 
1479 
1480 static PyTypeObject Hash_InfoType;
1481 
1482 PyDoc_STRVAR(hash_info_doc,
1483 "hash_info\n\
1484 \n\
1485 A named tuple providing parameters used for computing\n\
1486 hashes. The attributes are read only.");
1487 
1488 static PyStructSequence_Field hash_info_fields[] = {
1489     {"width", "width of the type used for hashing, in bits"},
1490     {"modulus", "prime number giving the modulus on which the hash "
1491                 "function is based"},
1492     {"inf", "value to be used for hash of a positive infinity"},
1493     {"nan", "value to be used for hash of a nan"},
1494     {"imag", "multiplier used for the imaginary part of a complex number"},
1495     {"algorithm", "name of the algorithm for hashing of str, bytes and "
1496                   "memoryviews"},
1497     {"hash_bits", "internal output size of hash algorithm"},
1498     {"seed_bits", "seed size of hash algorithm"},
1499     {"cutoff", "small string optimization cutoff"},
1500     {NULL, NULL}
1501 };
1502 
1503 static PyStructSequence_Desc hash_info_desc = {
1504     "sys.hash_info",
1505     hash_info_doc,
1506     hash_info_fields,
1507     9,
1508 };
1509 
1510 static PyObject *
get_hash_info(PyThreadState * tstate)1511 get_hash_info(PyThreadState *tstate)
1512 {
1513     PyObject *hash_info;
1514     int field = 0;
1515     PyHash_FuncDef *hashfunc;
1516     hash_info = PyStructSequence_New(&Hash_InfoType);
1517     if (hash_info == NULL) {
1518         return NULL;
1519     }
1520     hashfunc = PyHash_GetFuncDef();
1521 
1522 #define SET_HASH_INFO_ITEM(CALL)                             \
1523     do {                                                     \
1524         PyObject *item = (CALL);                             \
1525         if (item == NULL) {                                  \
1526             Py_CLEAR(hash_info);                             \
1527             return NULL;                                     \
1528         }                                                    \
1529         PyStructSequence_SET_ITEM(hash_info, field++, item); \
1530     } while(0)
1531 
1532     SET_HASH_INFO_ITEM(PyLong_FromLong(8 * sizeof(Py_hash_t)));
1533     SET_HASH_INFO_ITEM(PyLong_FromSsize_t(_PyHASH_MODULUS));
1534     SET_HASH_INFO_ITEM(PyLong_FromLong(_PyHASH_INF));
1535     SET_HASH_INFO_ITEM(PyLong_FromLong(0));  // This is no longer used
1536     SET_HASH_INFO_ITEM(PyLong_FromLong(_PyHASH_IMAG));
1537     SET_HASH_INFO_ITEM(PyUnicode_FromString(hashfunc->name));
1538     SET_HASH_INFO_ITEM(PyLong_FromLong(hashfunc->hash_bits));
1539     SET_HASH_INFO_ITEM(PyLong_FromLong(hashfunc->seed_bits));
1540     SET_HASH_INFO_ITEM(PyLong_FromLong(Py_HASH_CUTOFF));
1541 
1542 #undef SET_HASH_INFO_ITEM
1543 
1544     return hash_info;
1545 }
1546 /*[clinic input]
1547 sys.getrecursionlimit
1548 
1549 Return the current value of the recursion limit.
1550 
1551 The recursion limit is the maximum depth of the Python interpreter
1552 stack.  This limit prevents infinite recursion from causing an overflow
1553 of the C stack and crashing Python.
1554 [clinic start generated code]*/
1555 
1556 static PyObject *
sys_getrecursionlimit_impl(PyObject * module)1557 sys_getrecursionlimit_impl(PyObject *module)
1558 /*[clinic end generated code: output=d571fb6b4549ef2e input=1c6129fd2efaeea8]*/
1559 {
1560     return PyLong_FromLong(Py_GetRecursionLimit());
1561 }
1562 
1563 #ifdef MS_WINDOWS
1564 
1565 static PyTypeObject WindowsVersionType = {0, 0, 0, 0, 0, 0};
1566 
1567 static PyStructSequence_Field windows_version_fields[] = {
1568     {"major", "Major version number"},
1569     {"minor", "Minor version number"},
1570     {"build", "Build number"},
1571     {"platform", "Operating system platform"},
1572     {"service_pack", "Latest Service Pack installed on the system"},
1573     {"service_pack_major", "Service Pack major version number"},
1574     {"service_pack_minor", "Service Pack minor version number"},
1575     {"suite_mask", "Bit mask identifying available product suites"},
1576     {"product_type", "System product type"},
1577     {"platform_version", "Diagnostic version number"},
1578     {0}
1579 };
1580 
1581 static PyStructSequence_Desc windows_version_desc = {
1582     "sys.getwindowsversion",       /* name */
1583     sys_getwindowsversion__doc__,  /* doc */
1584     windows_version_fields,        /* fields */
1585     5                              /* For backward compatibility,
1586                                       only the first 5 items are accessible
1587                                       via indexing, the rest are name only */
1588 };
1589 
1590 static PyObject *
_sys_getwindowsversion_from_kernel32(void)1591 _sys_getwindowsversion_from_kernel32(void)
1592 {
1593 #ifndef MS_WINDOWS_DESKTOP
1594     return NULL;
1595 #else
1596     HANDLE hKernel32;
1597     wchar_t kernel32_path[MAX_PATH];
1598     LPVOID verblock;
1599     DWORD verblock_size;
1600     VS_FIXEDFILEINFO *ffi;
1601     UINT ffi_len;
1602     DWORD realMajor, realMinor, realBuild;
1603 
1604     Py_BEGIN_ALLOW_THREADS
1605     hKernel32 = GetModuleHandleW(L"kernel32.dll");
1606     Py_END_ALLOW_THREADS
1607     if (!hKernel32 || !GetModuleFileNameW(hKernel32, kernel32_path, MAX_PATH)) {
1608         PyErr_SetFromWindowsErr(0);
1609         return NULL;
1610     }
1611     verblock_size = GetFileVersionInfoSizeW(kernel32_path, NULL);
1612     if (!verblock_size) {
1613         PyErr_SetFromWindowsErr(0);
1614         return NULL;
1615     }
1616     verblock = PyMem_RawMalloc(verblock_size);
1617     if (!verblock ||
1618         !GetFileVersionInfoW(kernel32_path, 0, verblock_size, verblock) ||
1619         !VerQueryValueW(verblock, L"", (LPVOID)&ffi, &ffi_len)) {
1620         PyErr_SetFromWindowsErr(0);
1621         return NULL;
1622     }
1623 
1624     realMajor = HIWORD(ffi->dwProductVersionMS);
1625     realMinor = LOWORD(ffi->dwProductVersionMS);
1626     realBuild = HIWORD(ffi->dwProductVersionLS);
1627     PyMem_RawFree(verblock);
1628     return Py_BuildValue("(kkk)", realMajor, realMinor, realBuild);
1629 #endif /* !MS_WINDOWS_DESKTOP */
1630 }
1631 
1632 /* Disable deprecation warnings about GetVersionEx as the result is
1633    being passed straight through to the caller, who is responsible for
1634    using it correctly. */
1635 #pragma warning(push)
1636 #pragma warning(disable:4996)
1637 
1638 /*[clinic input]
1639 sys.getwindowsversion
1640 
1641 Return info about the running version of Windows as a named tuple.
1642 
1643 The members are named: major, minor, build, platform, service_pack,
1644 service_pack_major, service_pack_minor, suite_mask, product_type and
1645 platform_version. For backward compatibility, only the first 5 items
1646 are available by indexing. All elements are numbers, except
1647 service_pack and platform_type which are strings, and platform_version
1648 which is a 3-tuple. Platform is always 2. Product_type may be 1 for a
1649 workstation, 2 for a domain controller, 3 for a server.
1650 Platform_version is a 3-tuple containing a version number that is
1651 intended for identifying the OS rather than feature detection.
1652 [clinic start generated code]*/
1653 
1654 static PyObject *
sys_getwindowsversion_impl(PyObject * module)1655 sys_getwindowsversion_impl(PyObject *module)
1656 /*[clinic end generated code: output=1ec063280b932857 input=73a228a328fee63a]*/
1657 {
1658     PyObject *version;
1659     int pos = 0;
1660     OSVERSIONINFOEXW ver;
1661 
1662     if (PyObject_GetOptionalAttrString(module, "_cached_windows_version", &version) < 0) {
1663         return NULL;
1664     };
1665     if (version && PyObject_TypeCheck(version, &WindowsVersionType)) {
1666         return version;
1667     }
1668     Py_XDECREF(version);
1669 
1670     ver.dwOSVersionInfoSize = sizeof(ver);
1671     if (!GetVersionExW((OSVERSIONINFOW*) &ver))
1672         return PyErr_SetFromWindowsErr(0);
1673 
1674     version = PyStructSequence_New(&WindowsVersionType);
1675     if (version == NULL)
1676         return NULL;
1677 
1678 #define SET_VERSION_INFO(CALL)                               \
1679     do {                                                     \
1680         PyObject *item = (CALL);                             \
1681         if (item == NULL) {                                  \
1682             goto error;                                      \
1683         }                                                    \
1684         PyStructSequence_SET_ITEM(version, pos++, item);     \
1685     } while(0)
1686 
1687     SET_VERSION_INFO(PyLong_FromLong(ver.dwMajorVersion));
1688     SET_VERSION_INFO(PyLong_FromLong(ver.dwMinorVersion));
1689     SET_VERSION_INFO(PyLong_FromLong(ver.dwBuildNumber));
1690     SET_VERSION_INFO(PyLong_FromLong(ver.dwPlatformId));
1691     SET_VERSION_INFO(PyUnicode_FromWideChar(ver.szCSDVersion, -1));
1692     SET_VERSION_INFO(PyLong_FromLong(ver.wServicePackMajor));
1693     SET_VERSION_INFO(PyLong_FromLong(ver.wServicePackMinor));
1694     SET_VERSION_INFO(PyLong_FromLong(ver.wSuiteMask));
1695     SET_VERSION_INFO(PyLong_FromLong(ver.wProductType));
1696 
1697     // GetVersion will lie if we are running in a compatibility mode.
1698     // We need to read the version info from a system file resource
1699     // to accurately identify the OS version. If we fail for any reason,
1700     // just return whatever GetVersion said.
1701     PyObject *realVersion = _sys_getwindowsversion_from_kernel32();
1702     if (!realVersion) {
1703         if (!PyErr_ExceptionMatches(PyExc_WindowsError)) {
1704             return NULL;
1705         }
1706 
1707         PyErr_Clear();
1708         realVersion = Py_BuildValue("(kkk)",
1709             ver.dwMajorVersion,
1710             ver.dwMinorVersion,
1711             ver.dwBuildNumber
1712         );
1713     }
1714 
1715     SET_VERSION_INFO(realVersion);
1716 
1717 #undef SET_VERSION_INFO
1718 
1719     if (PyObject_SetAttrString(module, "_cached_windows_version", version) < 0) {
1720         goto error;
1721     }
1722 
1723     return version;
1724 
1725 error:
1726     Py_DECREF(version);
1727     return NULL;
1728 }
1729 
1730 #pragma warning(pop)
1731 
1732 /*[clinic input]
1733 sys._enablelegacywindowsfsencoding
1734 
1735 Changes the default filesystem encoding to mbcs:replace.
1736 
1737 This is done for consistency with earlier versions of Python. See PEP
1738 529 for more information.
1739 
1740 This is equivalent to defining the PYTHONLEGACYWINDOWSFSENCODING
1741 environment variable before launching Python.
1742 [clinic start generated code]*/
1743 
1744 static PyObject *
sys__enablelegacywindowsfsencoding_impl(PyObject * module)1745 sys__enablelegacywindowsfsencoding_impl(PyObject *module)
1746 /*[clinic end generated code: output=f5c3855b45e24fe9 input=2bfa931a20704492]*/
1747 {
1748     if (PyErr_WarnEx(PyExc_DeprecationWarning,
1749         "sys._enablelegacywindowsfsencoding() is deprecated and will be "
1750         "removed in Python 3.16. Use PYTHONLEGACYWINDOWSFSENCODING "
1751         "instead.", 1))
1752     {
1753         return NULL;
1754     }
1755     if (_PyUnicode_EnableLegacyWindowsFSEncoding() < 0) {
1756         return NULL;
1757     }
1758     Py_RETURN_NONE;
1759 }
1760 
1761 #endif /* MS_WINDOWS */
1762 
1763 #ifdef HAVE_DLOPEN
1764 
1765 /*[clinic input]
1766 sys.setdlopenflags
1767 
1768     flags as new_val: int
1769     /
1770 
1771 Set the flags used by the interpreter for dlopen calls.
1772 
1773 This is used, for example, when the interpreter loads extension
1774 modules. Among other things, this will enable a lazy resolving of
1775 symbols when importing a module, if called as sys.setdlopenflags(0).
1776 To share symbols across extension modules, call as
1777 sys.setdlopenflags(os.RTLD_GLOBAL).  Symbolic names for the flag
1778 modules can be found in the os module (RTLD_xxx constants, e.g.
1779 os.RTLD_LAZY).
1780 [clinic start generated code]*/
1781 
1782 static PyObject *
sys_setdlopenflags_impl(PyObject * module,int new_val)1783 sys_setdlopenflags_impl(PyObject *module, int new_val)
1784 /*[clinic end generated code: output=ec918b7fe0a37281 input=4c838211e857a77f]*/
1785 {
1786     PyInterpreterState *interp = _PyInterpreterState_GET();
1787     _PyImport_SetDLOpenFlags(interp, new_val);
1788     Py_RETURN_NONE;
1789 }
1790 
1791 
1792 /*[clinic input]
1793 sys.getdlopenflags
1794 
1795 Return the current value of the flags that are used for dlopen calls.
1796 
1797 The flag constants are defined in the os module.
1798 [clinic start generated code]*/
1799 
1800 static PyObject *
sys_getdlopenflags_impl(PyObject * module)1801 sys_getdlopenflags_impl(PyObject *module)
1802 /*[clinic end generated code: output=e92cd1bc5005da6e input=dc4ea0899c53b4b6]*/
1803 {
1804     PyInterpreterState *interp = _PyInterpreterState_GET();
1805     return PyLong_FromLong(
1806             _PyImport_GetDLOpenFlags(interp));
1807 }
1808 
1809 #endif  /* HAVE_DLOPEN */
1810 
1811 #ifdef USE_MALLOPT
1812 /* Link with -lmalloc (or -lmpc) on an SGI */
1813 #include <malloc.h>
1814 
1815 /*[clinic input]
1816 sys.mdebug
1817 
1818     flag: int
1819     /
1820 [clinic start generated code]*/
1821 
1822 static PyObject *
sys_mdebug_impl(PyObject * module,int flag)1823 sys_mdebug_impl(PyObject *module, int flag)
1824 /*[clinic end generated code: output=5431d545847c3637 input=151d150ae1636f8a]*/
1825 {
1826     int flag;
1827     mallopt(M_DEBUG, flag);
1828     Py_RETURN_NONE;
1829 }
1830 #endif /* USE_MALLOPT */
1831 
1832 
1833 /*[clinic input]
1834 sys.get_int_max_str_digits
1835 
1836 Return the maximum string digits limit for non-binary int<->str conversions.
1837 [clinic start generated code]*/
1838 
1839 static PyObject *
sys_get_int_max_str_digits_impl(PyObject * module)1840 sys_get_int_max_str_digits_impl(PyObject *module)
1841 /*[clinic end generated code: output=0042f5e8ae0e8631 input=61bf9f99bc8b112d]*/
1842 {
1843     PyInterpreterState *interp = _PyInterpreterState_GET();
1844     return PyLong_FromLong(interp->long_state.max_str_digits);
1845 }
1846 
1847 /*[clinic input]
1848 sys.set_int_max_str_digits
1849 
1850     maxdigits: int
1851 
1852 Set the maximum string digits limit for non-binary int<->str conversions.
1853 [clinic start generated code]*/
1854 
1855 static PyObject *
sys_set_int_max_str_digits_impl(PyObject * module,int maxdigits)1856 sys_set_int_max_str_digits_impl(PyObject *module, int maxdigits)
1857 /*[clinic end generated code: output=734d4c2511f2a56d input=d7e3f325db6910c5]*/
1858 {
1859     PyThreadState *tstate = _PyThreadState_GET();
1860     if ((!maxdigits) || (maxdigits >= _PY_LONG_MAX_STR_DIGITS_THRESHOLD)) {
1861         tstate->interp->long_state.max_str_digits = maxdigits;
1862         Py_RETURN_NONE;
1863     } else {
1864         PyErr_Format(
1865             PyExc_ValueError, "maxdigits must be 0 or larger than %d",
1866             _PY_LONG_MAX_STR_DIGITS_THRESHOLD);
1867         return NULL;
1868     }
1869 }
1870 
1871 size_t
_PySys_GetSizeOf(PyObject * o)1872 _PySys_GetSizeOf(PyObject *o)
1873 {
1874     PyObject *res = NULL;
1875     PyObject *method;
1876     Py_ssize_t size;
1877     PyThreadState *tstate = _PyThreadState_GET();
1878 
1879     /* Make sure the type is initialized. float gets initialized late */
1880     if (PyType_Ready(Py_TYPE(o)) < 0) {
1881         return (size_t)-1;
1882     }
1883 
1884     method = _PyObject_LookupSpecial(o, &_Py_ID(__sizeof__));
1885     if (method == NULL) {
1886         if (!_PyErr_Occurred(tstate)) {
1887             _PyErr_Format(tstate, PyExc_TypeError,
1888                           "Type %.100s doesn't define __sizeof__",
1889                           Py_TYPE(o)->tp_name);
1890         }
1891     }
1892     else {
1893         res = _PyObject_CallNoArgs(method);
1894         Py_DECREF(method);
1895     }
1896 
1897     if (res == NULL)
1898         return (size_t)-1;
1899 
1900     size = PyLong_AsSsize_t(res);
1901     Py_DECREF(res);
1902     if (size == -1 && _PyErr_Occurred(tstate))
1903         return (size_t)-1;
1904 
1905     if (size < 0) {
1906         _PyErr_SetString(tstate, PyExc_ValueError,
1907                           "__sizeof__() should return >= 0");
1908         return (size_t)-1;
1909     }
1910 
1911     size_t presize = 0;
1912     if (!Py_IS_TYPE(o, &PyType_Type) ||
1913          PyType_HasFeature((PyTypeObject *)o, Py_TPFLAGS_HEAPTYPE))
1914     {
1915         /* Add the size of the pre-header if "o" is not a static type */
1916         presize = _PyType_PreHeaderSize(Py_TYPE(o));
1917     }
1918 
1919     return (size_t)size + presize;
1920 }
1921 
1922 static PyObject *
sys_getsizeof(PyObject * self,PyObject * args,PyObject * kwds)1923 sys_getsizeof(PyObject *self, PyObject *args, PyObject *kwds)
1924 {
1925     static char *kwlist[] = {"object", "default", 0};
1926     size_t size;
1927     PyObject *o, *dflt = NULL;
1928     PyThreadState *tstate = _PyThreadState_GET();
1929 
1930     if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:getsizeof",
1931                                      kwlist, &o, &dflt)) {
1932         return NULL;
1933     }
1934 
1935     size = _PySys_GetSizeOf(o);
1936 
1937     if (size == (size_t)-1 && _PyErr_Occurred(tstate)) {
1938         /* Has a default value been given */
1939         if (dflt != NULL && _PyErr_ExceptionMatches(tstate, PyExc_TypeError)) {
1940             _PyErr_Clear(tstate);
1941             return Py_NewRef(dflt);
1942         }
1943         else
1944             return NULL;
1945     }
1946 
1947     return PyLong_FromSize_t(size);
1948 }
1949 
1950 PyDoc_STRVAR(getsizeof_doc,
1951 "getsizeof(object [, default]) -> int\n\
1952 \n\
1953 Return the size of object in bytes.");
1954 
1955 /*[clinic input]
1956 sys.getrefcount -> Py_ssize_t
1957 
1958     object:  object
1959     /
1960 
1961 Return the reference count of object.
1962 
1963 The count returned is generally one higher than you might expect,
1964 because it includes the (temporary) reference as an argument to
1965 getrefcount().
1966 [clinic start generated code]*/
1967 
1968 static Py_ssize_t
sys_getrefcount_impl(PyObject * module,PyObject * object)1969 sys_getrefcount_impl(PyObject *module, PyObject *object)
1970 /*[clinic end generated code: output=5fd477f2264b85b2 input=bf474efd50a21535]*/
1971 {
1972     return Py_REFCNT(object);
1973 }
1974 
1975 #ifdef Py_REF_DEBUG
1976 /*[clinic input]
1977 sys.gettotalrefcount -> Py_ssize_t
1978 [clinic start generated code]*/
1979 
1980 static Py_ssize_t
sys_gettotalrefcount_impl(PyObject * module)1981 sys_gettotalrefcount_impl(PyObject *module)
1982 /*[clinic end generated code: output=4103886cf17c25bc input=53b744faa5d2e4f6]*/
1983 {
1984     /* It may make sense to return the total for the current interpreter
1985        or have a second function that does so. */
1986     return _Py_GetGlobalRefTotal();
1987 }
1988 
1989 #endif /* Py_REF_DEBUG */
1990 
1991 /*[clinic input]
1992 sys.getallocatedblocks -> Py_ssize_t
1993 
1994 Return the number of memory blocks currently allocated.
1995 [clinic start generated code]*/
1996 
1997 static Py_ssize_t
sys_getallocatedblocks_impl(PyObject * module)1998 sys_getallocatedblocks_impl(PyObject *module)
1999 /*[clinic end generated code: output=f0c4e873f0b6dcf7 input=dab13ee346a0673e]*/
2000 {
2001     // It might make sense to return the count
2002     // for just the current interpreter.
2003     return _Py_GetGlobalAllocatedBlocks();
2004 }
2005 
2006 /*[clinic input]
2007 sys.getunicodeinternedsize -> Py_ssize_t
2008 
2009     *
2010     _only_immortal: bool = False
2011 
2012 Return the number of elements of the unicode interned dictionary
2013 [clinic start generated code]*/
2014 
2015 static Py_ssize_t
sys_getunicodeinternedsize_impl(PyObject * module,int _only_immortal)2016 sys_getunicodeinternedsize_impl(PyObject *module, int _only_immortal)
2017 /*[clinic end generated code: output=29a6377a94a14f70 input=0330b3408dd5bcc6]*/
2018 {
2019     if (_only_immortal) {
2020         return _PyUnicode_InternedSize_Immortal();
2021     }
2022     else {
2023         return _PyUnicode_InternedSize();
2024     }
2025 }
2026 
2027 /*[clinic input]
2028 sys._getframe
2029 
2030     depth: int = 0
2031     /
2032 
2033 Return a frame object from the call stack.
2034 
2035 If optional integer depth is given, return the frame object that many
2036 calls below the top of the stack.  If that is deeper than the call
2037 stack, ValueError is raised.  The default for depth is zero, returning
2038 the frame at the top of the call stack.
2039 
2040 This function should be used for internal and specialized purposes
2041 only.
2042 [clinic start generated code]*/
2043 
2044 static PyObject *
sys__getframe_impl(PyObject * module,int depth)2045 sys__getframe_impl(PyObject *module, int depth)
2046 /*[clinic end generated code: output=d438776c04d59804 input=c1be8a6464b11ee5]*/
2047 {
2048     PyThreadState *tstate = _PyThreadState_GET();
2049     _PyInterpreterFrame *frame = tstate->current_frame;
2050 
2051     if (frame != NULL) {
2052         while (depth > 0) {
2053             frame = _PyFrame_GetFirstComplete(frame->previous);
2054             if (frame == NULL) {
2055                 break;
2056             }
2057             --depth;
2058         }
2059     }
2060     if (frame == NULL) {
2061         _PyErr_SetString(tstate, PyExc_ValueError,
2062                          "call stack is not deep enough");
2063         return NULL;
2064     }
2065 
2066     PyObject *pyFrame = Py_XNewRef((PyObject *)_PyFrame_GetFrameObject(frame));
2067     if (pyFrame && _PySys_Audit(tstate, "sys._getframe", "(O)", pyFrame) < 0) {
2068         Py_DECREF(pyFrame);
2069         return NULL;
2070     }
2071     return pyFrame;
2072 }
2073 
2074 /*[clinic input]
2075 sys._current_frames
2076 
2077 Return a dict mapping each thread's thread id to its current stack frame.
2078 
2079 This function should be used for specialized purposes only.
2080 [clinic start generated code]*/
2081 
2082 static PyObject *
sys__current_frames_impl(PyObject * module)2083 sys__current_frames_impl(PyObject *module)
2084 /*[clinic end generated code: output=d2a41ac0a0a3809a input=2a9049c5f5033691]*/
2085 {
2086     return _PyThread_CurrentFrames();
2087 }
2088 
2089 /*[clinic input]
2090 sys._current_exceptions
2091 
2092 Return a dict mapping each thread's identifier to its current raised exception.
2093 
2094 This function should be used for specialized purposes only.
2095 [clinic start generated code]*/
2096 
2097 static PyObject *
sys__current_exceptions_impl(PyObject * module)2098 sys__current_exceptions_impl(PyObject *module)
2099 /*[clinic end generated code: output=2ccfd838c746f0ba input=0e91818fbf2edc1f]*/
2100 {
2101     return _PyThread_CurrentExceptions();
2102 }
2103 
2104 /*[clinic input]
2105 sys.call_tracing
2106 
2107     func: object
2108     args as funcargs: object(subclass_of='&PyTuple_Type')
2109     /
2110 
2111 Call func(*args), while tracing is enabled.
2112 
2113 The tracing state is saved, and restored afterwards.  This is intended
2114 to be called from a debugger from a checkpoint, to recursively debug
2115 some other code.
2116 [clinic start generated code]*/
2117 
2118 static PyObject *
sys_call_tracing_impl(PyObject * module,PyObject * func,PyObject * funcargs)2119 sys_call_tracing_impl(PyObject *module, PyObject *func, PyObject *funcargs)
2120 /*[clinic end generated code: output=7e4999853cd4e5a6 input=5102e8b11049f92f]*/
2121 {
2122     return _PyEval_CallTracing(func, funcargs);
2123 }
2124 
2125 /*[clinic input]
2126 sys._debugmallocstats
2127 
2128 Print summary info to stderr about the state of pymalloc's structures.
2129 
2130 In Py_DEBUG mode, also perform some expensive internal consistency
2131 checks.
2132 [clinic start generated code]*/
2133 
2134 static PyObject *
sys__debugmallocstats_impl(PyObject * module)2135 sys__debugmallocstats_impl(PyObject *module)
2136 /*[clinic end generated code: output=ec3565f8c7cee46a input=33c0c9c416f98424]*/
2137 {
2138 #ifdef WITH_PYMALLOC
2139     if (_PyObject_DebugMallocStats(stderr)) {
2140         fputc('\n', stderr);
2141     }
2142 #endif
2143     _PyObject_DebugTypeStats(stderr);
2144 
2145     Py_RETURN_NONE;
2146 }
2147 
2148 #ifdef Py_TRACE_REFS
2149 /* Defined in objects.c because it uses static globals in that file */
2150 extern PyObject *_Py_GetObjects(PyObject *, PyObject *);
2151 #endif
2152 
2153 
2154 /*[clinic input]
2155 sys._clear_type_cache
2156 
2157 Clear the internal type lookup cache.
2158 [clinic start generated code]*/
2159 
2160 static PyObject *
sys__clear_type_cache_impl(PyObject * module)2161 sys__clear_type_cache_impl(PyObject *module)
2162 /*[clinic end generated code: output=20e48ca54a6f6971 input=127f3e04a8d9b555]*/
2163 {
2164     PyType_ClearCache();
2165     Py_RETURN_NONE;
2166 }
2167 
2168 /*[clinic input]
2169 sys._clear_internal_caches
2170 
2171 Clear all internal performance-related caches.
2172 [clinic start generated code]*/
2173 
2174 static PyObject *
sys__clear_internal_caches_impl(PyObject * module)2175 sys__clear_internal_caches_impl(PyObject *module)
2176 /*[clinic end generated code: output=0ee128670a4966d6 input=253e741ca744f6e8]*/
2177 {
2178 #ifdef _Py_TIER2
2179     PyInterpreterState *interp = _PyInterpreterState_GET();
2180     _Py_Executors_InvalidateAll(interp, 0);
2181 #endif
2182     PyType_ClearCache();
2183     Py_RETURN_NONE;
2184 }
2185 
2186 /* Note that, for now, we do not have a per-interpreter equivalent
2187   for sys.is_finalizing(). */
2188 
2189 /*[clinic input]
2190 sys.is_finalizing
2191 
2192 Return True if Python is exiting.
2193 [clinic start generated code]*/
2194 
2195 static PyObject *
sys_is_finalizing_impl(PyObject * module)2196 sys_is_finalizing_impl(PyObject *module)
2197 /*[clinic end generated code: output=735b5ff7962ab281 input=f0df747a039948a5]*/
2198 {
2199     return PyBool_FromLong(Py_IsFinalizing());
2200 }
2201 
2202 
2203 #ifdef Py_STATS
2204 /*[clinic input]
2205 sys._stats_on
2206 
2207 Turns on stats gathering (stats gathering is off by default).
2208 [clinic start generated code]*/
2209 
2210 static PyObject *
sys__stats_on_impl(PyObject * module)2211 sys__stats_on_impl(PyObject *module)
2212 /*[clinic end generated code: output=aca53eafcbb4d9fe input=43b5bfe145299e55]*/
2213 {
2214     _Py_StatsOn();
2215     Py_RETURN_NONE;
2216 }
2217 
2218 /*[clinic input]
2219 sys._stats_off
2220 
2221 Turns off stats gathering (stats gathering is off by default).
2222 [clinic start generated code]*/
2223 
2224 static PyObject *
sys__stats_off_impl(PyObject * module)2225 sys__stats_off_impl(PyObject *module)
2226 /*[clinic end generated code: output=1534c1ee63812214 input=d1a84c60c56cbce2]*/
2227 {
2228     _Py_StatsOff();
2229     Py_RETURN_NONE;
2230 }
2231 
2232 /*[clinic input]
2233 sys._stats_clear
2234 
2235 Clears the stats.
2236 [clinic start generated code]*/
2237 
2238 static PyObject *
sys__stats_clear_impl(PyObject * module)2239 sys__stats_clear_impl(PyObject *module)
2240 /*[clinic end generated code: output=fb65a2525ee50604 input=3e03f2654f44da96]*/
2241 {
2242     _Py_StatsClear();
2243     Py_RETURN_NONE;
2244 }
2245 
2246 /*[clinic input]
2247 sys._stats_dump -> bool
2248 
2249 Dump stats to file, and clears the stats.
2250 
2251 Return False if no statistics were not dumped because stats gathering was off.
2252 [clinic start generated code]*/
2253 
2254 static int
sys__stats_dump_impl(PyObject * module)2255 sys__stats_dump_impl(PyObject *module)
2256 /*[clinic end generated code: output=6e346b4ba0de4489 input=31a489e39418b2a5]*/
2257 {
2258     int res = _Py_PrintSpecializationStats(1);
2259     _Py_StatsClear();
2260     return res;
2261 }
2262 #endif   // Py_STATS
2263 
2264 
2265 #ifdef ANDROID_API_LEVEL
2266 /*[clinic input]
2267 sys.getandroidapilevel
2268 
2269 Return the build time API version of Android as an integer.
2270 [clinic start generated code]*/
2271 
2272 static PyObject *
sys_getandroidapilevel_impl(PyObject * module)2273 sys_getandroidapilevel_impl(PyObject *module)
2274 /*[clinic end generated code: output=214abf183a1c70c1 input=3e6d6c9fcdd24ac6]*/
2275 {
2276     return PyLong_FromLong(ANDROID_API_LEVEL);
2277 }
2278 #endif   /* ANDROID_API_LEVEL */
2279 
2280 /*[clinic input]
2281 sys.activate_stack_trampoline
2282 
2283     backend: str
2284     /
2285 
2286 Activate stack profiler trampoline *backend*.
2287 [clinic start generated code]*/
2288 
2289 static PyObject *
sys_activate_stack_trampoline_impl(PyObject * module,const char * backend)2290 sys_activate_stack_trampoline_impl(PyObject *module, const char *backend)
2291 /*[clinic end generated code: output=5783cdeb51874b43 input=a12df928758a82b4]*/
2292 {
2293 #ifdef PY_HAVE_PERF_TRAMPOLINE
2294     if (strcmp(backend, "perf") == 0) {
2295         _PyPerf_Callbacks cur_cb;
2296         _PyPerfTrampoline_GetCallbacks(&cur_cb);
2297         if (cur_cb.write_state != _Py_perfmap_callbacks.write_state) {
2298             if (_PyPerfTrampoline_SetCallbacks(&_Py_perfmap_callbacks) < 0 ) {
2299                 PyErr_SetString(PyExc_ValueError, "can't activate perf trampoline");
2300                 return NULL;
2301             }
2302         }
2303         else if (strcmp(backend, "perf_jit") == 0) {
2304             _PyPerf_Callbacks cur_cb;
2305             _PyPerfTrampoline_GetCallbacks(&cur_cb);
2306             if (cur_cb.write_state != _Py_perfmap_jit_callbacks.write_state) {
2307                 if (_PyPerfTrampoline_SetCallbacks(&_Py_perfmap_jit_callbacks) < 0 ) {
2308                     PyErr_SetString(PyExc_ValueError, "can't activate perf jit trampoline");
2309                     return NULL;
2310                 }
2311             }
2312         }
2313     }
2314     else {
2315         PyErr_Format(PyExc_ValueError, "invalid backend: %s", backend);
2316         return NULL;
2317     }
2318     if (_PyPerfTrampoline_Init(1) < 0) {
2319         return NULL;
2320     }
2321     Py_RETURN_NONE;
2322 #else
2323     PyErr_SetString(PyExc_ValueError, "perf trampoline not available");
2324     return NULL;
2325 #endif
2326 }
2327 
2328 
2329 /*[clinic input]
2330 sys.deactivate_stack_trampoline
2331 
2332 Deactivate the current stack profiler trampoline backend.
2333 
2334 If no stack profiler is activated, this function has no effect.
2335 [clinic start generated code]*/
2336 
2337 static PyObject *
sys_deactivate_stack_trampoline_impl(PyObject * module)2338 sys_deactivate_stack_trampoline_impl(PyObject *module)
2339 /*[clinic end generated code: output=b50da25465df0ef1 input=9f629a6be9fe7fc8]*/
2340 {
2341     if  (_PyPerfTrampoline_Init(0) < 0) {
2342         return NULL;
2343     }
2344     Py_RETURN_NONE;
2345 }
2346 
2347 /*[clinic input]
2348 sys.is_stack_trampoline_active
2349 
2350 Return *True* if a stack profiler trampoline is active.
2351 [clinic start generated code]*/
2352 
2353 static PyObject *
sys_is_stack_trampoline_active_impl(PyObject * module)2354 sys_is_stack_trampoline_active_impl(PyObject *module)
2355 /*[clinic end generated code: output=ab2746de0ad9d293 input=29616b7bf6a0b703]*/
2356 {
2357 #ifdef PY_HAVE_PERF_TRAMPOLINE
2358     if (_PyIsPerfTrampolineActive()) {
2359         Py_RETURN_TRUE;
2360     }
2361 #endif
2362     Py_RETURN_FALSE;
2363 }
2364 
2365 
2366 /*[clinic input]
2367 sys._getframemodulename
2368 
2369     depth: int = 0
2370 
2371 Return the name of the module for a calling frame.
2372 
2373 The default depth returns the module containing the call to this API.
2374 A more typical use in a library will pass a depth of 1 to get the user's
2375 module rather than the library module.
2376 
2377 If no frame, module, or name can be found, returns None.
2378 [clinic start generated code]*/
2379 
2380 static PyObject *
sys__getframemodulename_impl(PyObject * module,int depth)2381 sys__getframemodulename_impl(PyObject *module, int depth)
2382 /*[clinic end generated code: output=1d70ef691f09d2db input=d4f1a8ed43b8fb46]*/
2383 {
2384     if (PySys_Audit("sys._getframemodulename", "i", depth) < 0) {
2385         return NULL;
2386     }
2387     _PyInterpreterFrame *f = _PyThreadState_GET()->current_frame;
2388     while (f && (_PyFrame_IsIncomplete(f) || depth-- > 0)) {
2389         f = f->previous;
2390     }
2391     if (f == NULL || f->f_funcobj == NULL) {
2392         Py_RETURN_NONE;
2393     }
2394     PyObject *r = PyFunction_GetModule(f->f_funcobj);
2395     if (!r) {
2396         PyErr_Clear();
2397         r = Py_None;
2398     }
2399     return Py_NewRef(r);
2400 }
2401 
2402 /*[clinic input]
2403 sys._get_cpu_count_config -> int
2404 
2405 Private function for getting PyConfig.cpu_count
2406 [clinic start generated code]*/
2407 
2408 static int
sys__get_cpu_count_config_impl(PyObject * module)2409 sys__get_cpu_count_config_impl(PyObject *module)
2410 /*[clinic end generated code: output=36611bb5efad16dc input=523e1ade2204084e]*/
2411 {
2412     const PyConfig *config = _Py_GetConfig();
2413     return config->cpu_count;
2414 }
2415 
2416 /*[clinic input]
2417 sys._baserepl
2418 
2419 Private function for getting the base REPL
2420 [clinic start generated code]*/
2421 
2422 static PyObject *
sys__baserepl_impl(PyObject * module)2423 sys__baserepl_impl(PyObject *module)
2424 /*[clinic end generated code: output=f19a36375ebe0a45 input=ade0ebb9fab56f3c]*/
2425 {
2426     PyCompilerFlags cf = _PyCompilerFlags_INIT;
2427     PyRun_AnyFileExFlags(stdin, "<stdin>", 0, &cf);
2428     Py_RETURN_NONE;
2429 }
2430 
2431 /*[clinic input]
2432 sys._is_gil_enabled -> bool
2433 
2434 Return True if the GIL is currently enabled and False otherwise.
2435 [clinic start generated code]*/
2436 
2437 static int
sys__is_gil_enabled_impl(PyObject * module)2438 sys__is_gil_enabled_impl(PyObject *module)
2439 /*[clinic end generated code: output=57732cf53f5b9120 input=7e9c47f15a00e809]*/
2440 {
2441 #ifdef Py_GIL_DISABLED
2442     return _PyEval_IsGILEnabled(_PyThreadState_GET());
2443 #else
2444     return 1;
2445 #endif
2446 }
2447 
2448 
2449 static PerfMapState perf_map_state;
2450 
PyUnstable_PerfMapState_Init(void)2451 PyAPI_FUNC(int) PyUnstable_PerfMapState_Init(void) {
2452 #ifndef MS_WINDOWS
2453     char filename[100];
2454     pid_t pid = getpid();
2455     // Use nofollow flag to prevent symlink attacks.
2456     int flags = O_WRONLY | O_CREAT | O_APPEND | O_NOFOLLOW;
2457 #ifdef O_CLOEXEC
2458     flags |= O_CLOEXEC;
2459 #endif
2460     snprintf(filename, sizeof(filename) - 1, "/tmp/perf-%jd.map",
2461                 (intmax_t)pid);
2462     int fd = open(filename, flags, 0600);
2463     if (fd == -1) {
2464         return -1;
2465     }
2466     else{
2467         perf_map_state.perf_map = fdopen(fd, "a");
2468         if (perf_map_state.perf_map == NULL) {
2469             close(fd);
2470             return -1;
2471         }
2472     }
2473     perf_map_state.map_lock = PyThread_allocate_lock();
2474     if (perf_map_state.map_lock == NULL) {
2475         fclose(perf_map_state.perf_map);
2476         return -2;
2477     }
2478 #endif
2479     return 0;
2480 }
2481 
PyUnstable_WritePerfMapEntry(const void * code_addr,unsigned int code_size,const char * entry_name)2482 PyAPI_FUNC(int) PyUnstable_WritePerfMapEntry(
2483     const void *code_addr,
2484     unsigned int code_size,
2485     const char *entry_name
2486 ) {
2487 #ifndef MS_WINDOWS
2488     if (perf_map_state.perf_map == NULL) {
2489         int ret = PyUnstable_PerfMapState_Init();
2490         if (ret != 0){
2491             return ret;
2492         }
2493     }
2494     PyThread_acquire_lock(perf_map_state.map_lock, 1);
2495     fprintf(perf_map_state.perf_map, "%" PRIxPTR " %x %s\n", (uintptr_t) code_addr, code_size, entry_name);
2496     fflush(perf_map_state.perf_map);
2497     PyThread_release_lock(perf_map_state.map_lock);
2498 #endif
2499     return 0;
2500 }
2501 
PyUnstable_PerfMapState_Fini(void)2502 PyAPI_FUNC(void) PyUnstable_PerfMapState_Fini(void) {
2503 #ifndef MS_WINDOWS
2504     if (perf_map_state.perf_map != NULL) {
2505         // close the file
2506         PyThread_acquire_lock(perf_map_state.map_lock, 1);
2507         fclose(perf_map_state.perf_map);
2508         PyThread_release_lock(perf_map_state.map_lock);
2509 
2510         // clean up the lock and state
2511         PyThread_free_lock(perf_map_state.map_lock);
2512         perf_map_state.perf_map = NULL;
2513     }
2514 #endif
2515 }
2516 
PyUnstable_CopyPerfMapFile(const char * parent_filename)2517 PyAPI_FUNC(int) PyUnstable_CopyPerfMapFile(const char* parent_filename) {
2518 #ifndef MS_WINDOWS
2519     FILE* from = fopen(parent_filename, "r");
2520     if (!from) {
2521         return -1;
2522     }
2523     if (perf_map_state.perf_map == NULL) {
2524         int ret = PyUnstable_PerfMapState_Init();
2525         if (ret != 0) {
2526             return ret;
2527         }
2528     }
2529     char buf[4096];
2530     PyThread_acquire_lock(perf_map_state.map_lock, 1);
2531     int fflush_result = 0, result = 0;
2532     while (1) {
2533         size_t bytes_read = fread(buf, 1, sizeof(buf), from);
2534         size_t bytes_written = fwrite(buf, 1, bytes_read, perf_map_state.perf_map);
2535         fflush_result = fflush(perf_map_state.perf_map);
2536         if (fflush_result != 0 || bytes_read == 0 || bytes_written < bytes_read) {
2537             result = -1;
2538             goto close_and_release;
2539         }
2540         if (bytes_read < sizeof(buf) && feof(from)) {
2541             goto close_and_release;
2542         }
2543     }
2544 close_and_release:
2545     fclose(from);
2546     PyThread_release_lock(perf_map_state.map_lock);
2547     return result;
2548 #endif
2549     return 0;
2550 }
2551 
2552 
2553 static PyMethodDef sys_methods[] = {
2554     /* Might as well keep this in alphabetic order */
2555     SYS_ADDAUDITHOOK_METHODDEF
2556     {"audit", _PyCFunction_CAST(sys_audit), METH_FASTCALL, audit_doc },
2557     {"breakpointhook", _PyCFunction_CAST(sys_breakpointhook),
2558      METH_FASTCALL | METH_KEYWORDS, breakpointhook_doc},
2559     SYS__CLEAR_INTERNAL_CACHES_METHODDEF
2560     SYS__CLEAR_TYPE_CACHE_METHODDEF
2561     SYS__CURRENT_FRAMES_METHODDEF
2562     SYS__CURRENT_EXCEPTIONS_METHODDEF
2563     SYS_DISPLAYHOOK_METHODDEF
2564     SYS_EXCEPTION_METHODDEF
2565     SYS_EXC_INFO_METHODDEF
2566     SYS_EXCEPTHOOK_METHODDEF
2567     SYS_EXIT_METHODDEF
2568     SYS_GETDEFAULTENCODING_METHODDEF
2569     SYS_GETDLOPENFLAGS_METHODDEF
2570     SYS_GETALLOCATEDBLOCKS_METHODDEF
2571     SYS_GETUNICODEINTERNEDSIZE_METHODDEF
2572     SYS_GETFILESYSTEMENCODING_METHODDEF
2573     SYS_GETFILESYSTEMENCODEERRORS_METHODDEF
2574 #ifdef Py_TRACE_REFS
2575     {"getobjects", _Py_GetObjects, METH_VARARGS},
2576 #endif
2577     SYS_GETTOTALREFCOUNT_METHODDEF
2578     SYS_GETREFCOUNT_METHODDEF
2579     SYS_GETRECURSIONLIMIT_METHODDEF
2580     {"getsizeof", _PyCFunction_CAST(sys_getsizeof),
2581      METH_VARARGS | METH_KEYWORDS, getsizeof_doc},
2582     SYS__GETFRAME_METHODDEF
2583     SYS__GETFRAMEMODULENAME_METHODDEF
2584     SYS_GETWINDOWSVERSION_METHODDEF
2585     SYS__ENABLELEGACYWINDOWSFSENCODING_METHODDEF
2586     SYS_INTERN_METHODDEF
2587     SYS__IS_INTERNED_METHODDEF
2588     SYS_IS_FINALIZING_METHODDEF
2589     SYS_MDEBUG_METHODDEF
2590     SYS_SETSWITCHINTERVAL_METHODDEF
2591     SYS_GETSWITCHINTERVAL_METHODDEF
2592     SYS_SETDLOPENFLAGS_METHODDEF
2593     SYS_SETPROFILE_METHODDEF
2594     SYS__SETPROFILEALLTHREADS_METHODDEF
2595     SYS_GETPROFILE_METHODDEF
2596     SYS_SETRECURSIONLIMIT_METHODDEF
2597     SYS_SETTRACE_METHODDEF
2598     SYS__SETTRACEALLTHREADS_METHODDEF
2599     SYS_GETTRACE_METHODDEF
2600     SYS_CALL_TRACING_METHODDEF
2601     SYS__DEBUGMALLOCSTATS_METHODDEF
2602     SYS_SET_COROUTINE_ORIGIN_TRACKING_DEPTH_METHODDEF
2603     SYS_GET_COROUTINE_ORIGIN_TRACKING_DEPTH_METHODDEF
2604     {"set_asyncgen_hooks", _PyCFunction_CAST(sys_set_asyncgen_hooks),
2605      METH_VARARGS | METH_KEYWORDS, set_asyncgen_hooks_doc},
2606     SYS_GET_ASYNCGEN_HOOKS_METHODDEF
2607     SYS_GETANDROIDAPILEVEL_METHODDEF
2608     SYS_ACTIVATE_STACK_TRAMPOLINE_METHODDEF
2609     SYS_DEACTIVATE_STACK_TRAMPOLINE_METHODDEF
2610     SYS_IS_STACK_TRAMPOLINE_ACTIVE_METHODDEF
2611     SYS_UNRAISABLEHOOK_METHODDEF
2612     SYS_GET_INT_MAX_STR_DIGITS_METHODDEF
2613     SYS_SET_INT_MAX_STR_DIGITS_METHODDEF
2614     SYS__BASEREPL_METHODDEF
2615 #ifdef Py_STATS
2616     SYS__STATS_ON_METHODDEF
2617     SYS__STATS_OFF_METHODDEF
2618     SYS__STATS_CLEAR_METHODDEF
2619     SYS__STATS_DUMP_METHODDEF
2620 #endif
2621     SYS__GET_CPU_COUNT_CONFIG_METHODDEF
2622     SYS__IS_GIL_ENABLED_METHODDEF
2623     {NULL, NULL}  // sentinel
2624 };
2625 
2626 
2627 static PyObject *
list_builtin_module_names(void)2628 list_builtin_module_names(void)
2629 {
2630     PyObject *list = _PyImport_GetBuiltinModuleNames();
2631     if (list == NULL) {
2632         return NULL;
2633     }
2634     if (PyList_Sort(list) != 0) {
2635         goto error;
2636     }
2637     PyObject *tuple = PyList_AsTuple(list);
2638     Py_DECREF(list);
2639     return tuple;
2640 
2641 error:
2642     Py_DECREF(list);
2643     return NULL;
2644 }
2645 
2646 
2647 static PyObject *
list_stdlib_module_names(void)2648 list_stdlib_module_names(void)
2649 {
2650     Py_ssize_t len = Py_ARRAY_LENGTH(_Py_stdlib_module_names);
2651     PyObject *names = PyTuple_New(len);
2652     if (names == NULL) {
2653         return NULL;
2654     }
2655 
2656     for (Py_ssize_t i = 0; i < len; i++) {
2657         PyObject *name = PyUnicode_FromString(_Py_stdlib_module_names[i]);
2658         if (name == NULL) {
2659             Py_DECREF(names);
2660             return NULL;
2661         }
2662         PyTuple_SET_ITEM(names, i, name);
2663     }
2664 
2665     PyObject *set = PyObject_CallFunction((PyObject *)&PyFrozenSet_Type,
2666                                           "(O)", names);
2667     Py_DECREF(names);
2668     return set;
2669 }
2670 
2671 
2672 /* Pre-initialization support for sys.warnoptions and sys._xoptions
2673  *
2674  * Modern internal code paths:
2675  *   These APIs get called after _Py_InitializeCore and get to use the
2676  *   regular CPython list, dict, and unicode APIs.
2677  *
2678  * Legacy embedding code paths:
2679  *   The multi-phase initialization API isn't public yet, so embedding
2680  *   apps still need to be able configure sys.warnoptions and sys._xoptions
2681  *   before they call Py_Initialize. To support this, we stash copies of
2682  *   the supplied wchar * sequences in linked lists, and then migrate the
2683  *   contents of those lists to the sys module in _PyInitializeCore.
2684  *
2685  */
2686 
2687 struct _preinit_entry {
2688     wchar_t *value;
2689     struct _preinit_entry *next;
2690 };
2691 
2692 typedef struct _preinit_entry *_Py_PreInitEntry;
2693 
2694 static _Py_PreInitEntry _preinit_warnoptions = NULL;
2695 static _Py_PreInitEntry _preinit_xoptions = NULL;
2696 
2697 static _Py_PreInitEntry
_alloc_preinit_entry(const wchar_t * value)2698 _alloc_preinit_entry(const wchar_t *value)
2699 {
2700     /* To get this to work, we have to initialize the runtime implicitly */
2701     _PyRuntime_Initialize();
2702 
2703     /* Force default allocator, so we can ensure that it also gets used to
2704      * destroy the linked list in _clear_preinit_entries.
2705      */
2706     PyMemAllocatorEx old_alloc;
2707     _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
2708 
2709     _Py_PreInitEntry node = PyMem_RawCalloc(1, sizeof(*node));
2710     if (node != NULL) {
2711         node->value = _PyMem_RawWcsdup(value);
2712         if (node->value == NULL) {
2713             PyMem_RawFree(node);
2714             node = NULL;
2715         };
2716     };
2717 
2718     PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
2719     return node;
2720 }
2721 
2722 static int
_append_preinit_entry(_Py_PreInitEntry * optionlist,const wchar_t * value)2723 _append_preinit_entry(_Py_PreInitEntry *optionlist, const wchar_t *value)
2724 {
2725     _Py_PreInitEntry new_entry = _alloc_preinit_entry(value);
2726     if (new_entry == NULL) {
2727         return -1;
2728     }
2729     /* We maintain the linked list in this order so it's easy to play back
2730      * the add commands in the same order later on in _Py_InitializeCore
2731      */
2732     _Py_PreInitEntry last_entry = *optionlist;
2733     if (last_entry == NULL) {
2734         *optionlist = new_entry;
2735     } else {
2736         while (last_entry->next != NULL) {
2737             last_entry = last_entry->next;
2738         }
2739         last_entry->next = new_entry;
2740     }
2741     return 0;
2742 }
2743 
2744 static void
_clear_preinit_entries(_Py_PreInitEntry * optionlist)2745 _clear_preinit_entries(_Py_PreInitEntry *optionlist)
2746 {
2747     _Py_PreInitEntry current = *optionlist;
2748     *optionlist = NULL;
2749     /* Deallocate the nodes and their contents using the default allocator */
2750     PyMemAllocatorEx old_alloc;
2751     _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
2752     while (current != NULL) {
2753         _Py_PreInitEntry next = current->next;
2754         PyMem_RawFree(current->value);
2755         PyMem_RawFree(current);
2756         current = next;
2757     }
2758     PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
2759 }
2760 
2761 
2762 PyStatus
_PySys_ReadPreinitWarnOptions(PyWideStringList * options)2763 _PySys_ReadPreinitWarnOptions(PyWideStringList *options)
2764 {
2765     PyStatus status;
2766     _Py_PreInitEntry entry;
2767 
2768     for (entry = _preinit_warnoptions; entry != NULL; entry = entry->next) {
2769         status = PyWideStringList_Append(options, entry->value);
2770         if (_PyStatus_EXCEPTION(status)) {
2771             return status;
2772         }
2773     }
2774 
2775     _clear_preinit_entries(&_preinit_warnoptions);
2776     return _PyStatus_OK();
2777 }
2778 
2779 
2780 PyStatus
_PySys_ReadPreinitXOptions(PyConfig * config)2781 _PySys_ReadPreinitXOptions(PyConfig *config)
2782 {
2783     PyStatus status;
2784     _Py_PreInitEntry entry;
2785 
2786     for (entry = _preinit_xoptions; entry != NULL; entry = entry->next) {
2787         status = PyWideStringList_Append(&config->xoptions, entry->value);
2788         if (_PyStatus_EXCEPTION(status)) {
2789             return status;
2790         }
2791     }
2792 
2793     _clear_preinit_entries(&_preinit_xoptions);
2794     return _PyStatus_OK();
2795 }
2796 
2797 
2798 static PyObject *
get_warnoptions(PyThreadState * tstate)2799 get_warnoptions(PyThreadState *tstate)
2800 {
2801     PyObject *warnoptions = _PySys_GetAttr(tstate, &_Py_ID(warnoptions));
2802     if (warnoptions == NULL || !PyList_Check(warnoptions)) {
2803         /* PEP432 TODO: we can reach this if warnoptions is NULL in the main
2804         *  interpreter config. When that happens, we need to properly set
2805          * the `warnoptions` reference in the main interpreter config as well.
2806          *
2807          * For Python 3.7, we shouldn't be able to get here due to the
2808          * combination of how _PyMainInterpreter_ReadConfig and _PySys_EndInit
2809          * work, but we expect 3.8+ to make the _PyMainInterpreter_ReadConfig
2810          * call optional for embedding applications, thus making this
2811          * reachable again.
2812          */
2813         warnoptions = PyList_New(0);
2814         if (warnoptions == NULL) {
2815             return NULL;
2816         }
2817         if (sys_set_object(tstate->interp, &_Py_ID(warnoptions), warnoptions)) {
2818             Py_DECREF(warnoptions);
2819             return NULL;
2820         }
2821         Py_DECREF(warnoptions);
2822     }
2823     return warnoptions;
2824 }
2825 
2826 void
PySys_ResetWarnOptions(void)2827 PySys_ResetWarnOptions(void)
2828 {
2829     PyThreadState *tstate = _PyThreadState_GET();
2830     if (tstate == NULL) {
2831         _clear_preinit_entries(&_preinit_warnoptions);
2832         return;
2833     }
2834 
2835     PyObject *warnoptions = _PySys_GetAttr(tstate, &_Py_ID(warnoptions));
2836     if (warnoptions == NULL || !PyList_Check(warnoptions))
2837         return;
2838     PyList_SetSlice(warnoptions, 0, PyList_GET_SIZE(warnoptions), NULL);
2839 }
2840 
2841 static int
_PySys_AddWarnOptionWithError(PyThreadState * tstate,PyObject * option)2842 _PySys_AddWarnOptionWithError(PyThreadState *tstate, PyObject *option)
2843 {
2844     PyObject *warnoptions = get_warnoptions(tstate);
2845     if (warnoptions == NULL) {
2846         return -1;
2847     }
2848     if (PyList_Append(warnoptions, option)) {
2849         return -1;
2850     }
2851     return 0;
2852 }
2853 
2854 // Removed in Python 3.13 API, but kept for the stable ABI
2855 PyAPI_FUNC(void)
PySys_AddWarnOptionUnicode(PyObject * option)2856 PySys_AddWarnOptionUnicode(PyObject *option)
2857 {
2858     PyThreadState *tstate = _PyThreadState_GET();
2859     if (_PySys_AddWarnOptionWithError(tstate, option) < 0) {
2860         /* No return value, therefore clear error state if possible */
2861         if (tstate) {
2862             _PyErr_Clear(tstate);
2863         }
2864     }
2865 }
2866 
2867 // Removed in Python 3.13 API, but kept for the stable ABI
2868 PyAPI_FUNC(void)
PySys_AddWarnOption(const wchar_t * s)2869 PySys_AddWarnOption(const wchar_t *s)
2870 {
2871     PyThreadState *tstate = _PyThreadState_GET();
2872     if (tstate == NULL) {
2873         _append_preinit_entry(&_preinit_warnoptions, s);
2874         return;
2875     }
2876     PyObject *unicode;
2877     unicode = PyUnicode_FromWideChar(s, -1);
2878     if (unicode == NULL)
2879         return;
2880 _Py_COMP_DIAG_PUSH
2881 _Py_COMP_DIAG_IGNORE_DEPR_DECLS
2882     PySys_AddWarnOptionUnicode(unicode);
2883 _Py_COMP_DIAG_POP
2884     Py_DECREF(unicode);
2885 }
2886 
2887 // Removed in Python 3.13 API, but kept for the stable ABI
2888 PyAPI_FUNC(int)
PySys_HasWarnOptions(void)2889 PySys_HasWarnOptions(void)
2890 {
2891     PyThreadState *tstate = _PyThreadState_GET();
2892     PyObject *warnoptions = _PySys_GetAttr(tstate, &_Py_ID(warnoptions));
2893     return (warnoptions != NULL && PyList_Check(warnoptions)
2894             && PyList_GET_SIZE(warnoptions) > 0);
2895 }
2896 
2897 static PyObject *
get_xoptions(PyThreadState * tstate)2898 get_xoptions(PyThreadState *tstate)
2899 {
2900     PyObject *xoptions = _PySys_GetAttr(tstate, &_Py_ID(_xoptions));
2901     if (xoptions == NULL || !PyDict_Check(xoptions)) {
2902         /* PEP432 TODO: we can reach this if xoptions is NULL in the main
2903         *  interpreter config. When that happens, we need to properly set
2904          * the `xoptions` reference in the main interpreter config as well.
2905          *
2906          * For Python 3.7, we shouldn't be able to get here due to the
2907          * combination of how _PyMainInterpreter_ReadConfig and _PySys_EndInit
2908          * work, but we expect 3.8+ to make the _PyMainInterpreter_ReadConfig
2909          * call optional for embedding applications, thus making this
2910          * reachable again.
2911          */
2912         xoptions = PyDict_New();
2913         if (xoptions == NULL) {
2914             return NULL;
2915         }
2916         if (sys_set_object(tstate->interp, &_Py_ID(_xoptions), xoptions)) {
2917             Py_DECREF(xoptions);
2918             return NULL;
2919         }
2920         Py_DECREF(xoptions);
2921     }
2922     return xoptions;
2923 }
2924 
2925 static int
_PySys_AddXOptionWithError(const wchar_t * s)2926 _PySys_AddXOptionWithError(const wchar_t *s)
2927 {
2928     PyObject *name = NULL, *value = NULL;
2929 
2930     PyThreadState *tstate = _PyThreadState_GET();
2931     PyObject *opts = get_xoptions(tstate);
2932     if (opts == NULL) {
2933         goto error;
2934     }
2935 
2936     const wchar_t *name_end = wcschr(s, L'=');
2937     if (!name_end) {
2938         name = PyUnicode_FromWideChar(s, -1);
2939         if (name == NULL) {
2940             goto error;
2941         }
2942         value = Py_NewRef(Py_True);
2943     }
2944     else {
2945         name = PyUnicode_FromWideChar(s, name_end - s);
2946         if (name == NULL) {
2947             goto error;
2948         }
2949         value = PyUnicode_FromWideChar(name_end + 1, -1);
2950         if (value == NULL) {
2951             goto error;
2952         }
2953     }
2954     if (PyDict_SetItem(opts, name, value) < 0) {
2955         goto error;
2956     }
2957     Py_DECREF(name);
2958     Py_DECREF(value);
2959     return 0;
2960 
2961 error:
2962     Py_XDECREF(name);
2963     Py_XDECREF(value);
2964     return -1;
2965 }
2966 
2967 // Removed in Python 3.13 API, but kept for the stable ABI
2968 PyAPI_FUNC(void)
PySys_AddXOption(const wchar_t * s)2969 PySys_AddXOption(const wchar_t *s)
2970 {
2971     PyThreadState *tstate = _PyThreadState_GET();
2972     if (tstate == NULL) {
2973         _append_preinit_entry(&_preinit_xoptions, s);
2974         return;
2975     }
2976     if (_PySys_AddXOptionWithError(s) < 0) {
2977         /* No return value, therefore clear error state if possible */
2978         _PyErr_Clear(tstate);
2979     }
2980 }
2981 
2982 PyObject *
PySys_GetXOptions(void)2983 PySys_GetXOptions(void)
2984 {
2985     PyThreadState *tstate = _PyThreadState_GET();
2986     return get_xoptions(tstate);
2987 }
2988 
2989 /* XXX This doc string is too long to be a single string literal in VC++ 5.0.
2990    Two literals concatenated works just fine.  If you have a K&R compiler
2991    or other abomination that however *does* understand longer strings,
2992    get rid of the !!! comment in the middle and the quotes that surround it. */
2993 PyDoc_VAR(sys_doc) =
2994 PyDoc_STR(
2995 "This module provides access to some objects used or maintained by the\n\
2996 interpreter and to functions that interact strongly with the interpreter.\n\
2997 \n\
2998 Dynamic objects:\n\
2999 \n\
3000 argv -- command line arguments; argv[0] is the script pathname if known\n\
3001 path -- module search path; path[0] is the script directory, else ''\n\
3002 modules -- dictionary of loaded modules\n\
3003 \n\
3004 displayhook -- called to show results in an interactive session\n\
3005 excepthook -- called to handle any uncaught exception other than SystemExit\n\
3006   To customize printing in an interactive session or to install a custom\n\
3007   top-level exception handler, assign other functions to replace these.\n\
3008 \n\
3009 stdin -- standard input file object; used by input()\n\
3010 stdout -- standard output file object; used by print()\n\
3011 stderr -- standard error object; used for error messages\n\
3012   By assigning other file objects (or objects that behave like files)\n\
3013   to these, it is possible to redirect all of the interpreter's I/O.\n\
3014 \n\
3015 last_exc - the last uncaught exception\n\
3016   Only available in an interactive session after a\n\
3017   traceback has been printed.\n\
3018 last_type -- type of last uncaught exception\n\
3019 last_value -- value of last uncaught exception\n\
3020 last_traceback -- traceback of last uncaught exception\n\
3021   These three are the (deprecated) legacy representation of last_exc.\n\
3022 "
3023 )
3024 /* concatenating string here */
3025 PyDoc_STR(
3026 "\n\
3027 Static objects:\n\
3028 \n\
3029 builtin_module_names -- tuple of module names built into this interpreter\n\
3030 copyright -- copyright notice pertaining to this interpreter\n\
3031 exec_prefix -- prefix used to find the machine-specific Python library\n\
3032 executable -- absolute path of the executable binary of the Python interpreter\n\
3033 float_info -- a named tuple with information about the float implementation.\n\
3034 float_repr_style -- string indicating the style of repr() output for floats\n\
3035 hash_info -- a named tuple with information about the hash algorithm.\n\
3036 hexversion -- version information encoded as a single integer\n\
3037 implementation -- Python implementation information.\n\
3038 int_info -- a named tuple with information about the int implementation.\n\
3039 maxsize -- the largest supported length of containers.\n\
3040 maxunicode -- the value of the largest Unicode code point\n\
3041 platform -- platform identifier\n\
3042 prefix -- prefix used to find the Python library\n\
3043 thread_info -- a named tuple with information about the thread implementation.\n\
3044 version -- the version of this interpreter as a string\n\
3045 version_info -- version information as a named tuple\n\
3046 "
3047 )
3048 #ifdef MS_COREDLL
3049 /* concatenating string here */
3050 PyDoc_STR(
3051 "dllhandle -- [Windows only] integer handle of the Python DLL\n\
3052 winver -- [Windows only] version number of the Python DLL\n\
3053 "
3054 )
3055 #endif /* MS_COREDLL */
3056 #ifdef MS_WINDOWS
3057 /* concatenating string here */
3058 PyDoc_STR(
3059 "_enablelegacywindowsfsencoding -- [Windows only]\n\
3060 "
3061 )
3062 #endif
3063 PyDoc_STR(
3064 "__stdin__ -- the original stdin; don't touch!\n\
3065 __stdout__ -- the original stdout; don't touch!\n\
3066 __stderr__ -- the original stderr; don't touch!\n\
3067 __displayhook__ -- the original displayhook; don't touch!\n\
3068 __excepthook__ -- the original excepthook; don't touch!\n\
3069 \n\
3070 Functions:\n\
3071 \n\
3072 displayhook() -- print an object to the screen, and save it in builtins._\n\
3073 excepthook() -- print an exception and its traceback to sys.stderr\n\
3074 exception() -- return the current thread's active exception\n\
3075 exc_info() -- return information about the current thread's active exception\n\
3076 exit() -- exit the interpreter by raising SystemExit\n\
3077 getdlopenflags() -- returns flags to be used for dlopen() calls\n\
3078 getprofile() -- get the global profiling function\n\
3079 getrefcount() -- return the reference count for an object (plus one :-)\n\
3080 getrecursionlimit() -- return the max recursion depth for the interpreter\n\
3081 getsizeof() -- return the size of an object in bytes\n\
3082 gettrace() -- get the global debug tracing function\n\
3083 setdlopenflags() -- set the flags to be used for dlopen() calls\n\
3084 setprofile() -- set the global profiling function\n\
3085 setrecursionlimit() -- set the max recursion depth for the interpreter\n\
3086 settrace() -- set the global debug tracing function\n\
3087 "
3088 )
3089 /* end of sys_doc */ ;
3090 
3091 
3092 PyDoc_STRVAR(flags__doc__,
3093 "sys.flags\n\
3094 \n\
3095 Flags provided through command line arguments or environment vars.");
3096 
3097 static PyTypeObject FlagsType;
3098 
3099 static PyStructSequence_Field flags_fields[] = {
3100     {"debug",                   "-d"},
3101     {"inspect",                 "-i"},
3102     {"interactive",             "-i"},
3103     {"optimize",                "-O or -OO"},
3104     {"dont_write_bytecode",     "-B"},
3105     {"no_user_site",            "-s"},
3106     {"no_site",                 "-S"},
3107     {"ignore_environment",      "-E"},
3108     {"verbose",                 "-v"},
3109     {"bytes_warning",           "-b"},
3110     {"quiet",                   "-q"},
3111     {"hash_randomization",      "-R"},
3112     {"isolated",                "-I"},
3113     {"dev_mode",                "-X dev"},
3114     {"utf8_mode",               "-X utf8"},
3115     {"warn_default_encoding",   "-X warn_default_encoding"},
3116     {"safe_path", "-P"},
3117     {"int_max_str_digits",      "-X int_max_str_digits"},
3118     {"gil",                     "-X gil"},
3119     {0}
3120 };
3121 
3122 static PyStructSequence_Desc flags_desc = {
3123     "sys.flags",        /* name */
3124     flags__doc__,       /* doc */
3125     flags_fields,       /* fields */
3126     18
3127 };
3128 
3129 static int
set_flags_from_config(PyInterpreterState * interp,PyObject * flags)3130 set_flags_from_config(PyInterpreterState *interp, PyObject *flags)
3131 {
3132     const PyPreConfig *preconfig = &interp->runtime->preconfig;
3133     const PyConfig *config = _PyInterpreterState_GetConfig(interp);
3134 
3135     // _PySys_UpdateConfig() modifies sys.flags in-place:
3136     // Py_XDECREF() is needed in this case.
3137     Py_ssize_t pos = 0;
3138 #define SetFlagObj(expr) \
3139     do { \
3140         PyObject *value = (expr); \
3141         if (value == NULL) { \
3142             return -1; \
3143         } \
3144         Py_XDECREF(PyStructSequence_GET_ITEM(flags, pos)); \
3145         PyStructSequence_SET_ITEM(flags, pos, value); \
3146         pos++; \
3147     } while (0)
3148 #define SetFlag(expr) SetFlagObj(PyLong_FromLong(expr))
3149 
3150     SetFlag(config->parser_debug);
3151     SetFlag(config->inspect);
3152     SetFlag(config->interactive);
3153     SetFlag(config->optimization_level);
3154     SetFlag(!config->write_bytecode);
3155     SetFlag(!config->user_site_directory);
3156     SetFlag(!config->site_import);
3157     SetFlag(!config->use_environment);
3158     SetFlag(config->verbose);
3159     SetFlag(config->bytes_warning);
3160     SetFlag(config->quiet);
3161     SetFlag(config->use_hash_seed == 0 || config->hash_seed != 0);
3162     SetFlag(config->isolated);
3163     SetFlagObj(PyBool_FromLong(config->dev_mode));
3164     SetFlag(preconfig->utf8_mode);
3165     SetFlag(config->warn_default_encoding);
3166     SetFlagObj(PyBool_FromLong(config->safe_path));
3167     SetFlag(config->int_max_str_digits);
3168 #ifdef Py_GIL_DISABLED
3169     if (config->enable_gil == _PyConfig_GIL_DEFAULT) {
3170         SetFlagObj(Py_NewRef(Py_None));
3171     }
3172     else {
3173         SetFlag(config->enable_gil);
3174     }
3175 #else
3176     SetFlagObj(PyLong_FromLong(1));
3177 #endif
3178 #undef SetFlagObj
3179 #undef SetFlag
3180     return 0;
3181 }
3182 
3183 
3184 static PyObject*
make_flags(PyInterpreterState * interp)3185 make_flags(PyInterpreterState *interp)
3186 {
3187     PyObject *flags = PyStructSequence_New(&FlagsType);
3188     if (flags == NULL) {
3189         return NULL;
3190     }
3191 
3192     if (set_flags_from_config(interp, flags) < 0) {
3193         Py_DECREF(flags);
3194         return NULL;
3195     }
3196     return flags;
3197 }
3198 
3199 
3200 PyDoc_STRVAR(version_info__doc__,
3201 "sys.version_info\n\
3202 \n\
3203 Version information as a named tuple.");
3204 
3205 static PyTypeObject VersionInfoType;
3206 
3207 static PyStructSequence_Field version_info_fields[] = {
3208     {"major", "Major release number"},
3209     {"minor", "Minor release number"},
3210     {"micro", "Patch release number"},
3211     {"releaselevel", "'alpha', 'beta', 'candidate', or 'final'"},
3212     {"serial", "Serial release number"},
3213     {0}
3214 };
3215 
3216 static PyStructSequence_Desc version_info_desc = {
3217     "sys.version_info",     /* name */
3218     version_info__doc__,    /* doc */
3219     version_info_fields,    /* fields */
3220     5
3221 };
3222 
3223 static PyObject *
make_version_info(PyThreadState * tstate)3224 make_version_info(PyThreadState *tstate)
3225 {
3226     PyObject *version_info;
3227     char *s;
3228     int pos = 0;
3229 
3230     version_info = PyStructSequence_New(&VersionInfoType);
3231     if (version_info == NULL) {
3232         return NULL;
3233     }
3234 
3235     /*
3236      * These release level checks are mutually exclusive and cover
3237      * the field, so don't get too fancy with the pre-processor!
3238      */
3239 #if PY_RELEASE_LEVEL == PY_RELEASE_LEVEL_ALPHA
3240     s = "alpha";
3241 #elif PY_RELEASE_LEVEL == PY_RELEASE_LEVEL_BETA
3242     s = "beta";
3243 #elif PY_RELEASE_LEVEL == PY_RELEASE_LEVEL_GAMMA
3244     s = "candidate";
3245 #elif PY_RELEASE_LEVEL == PY_RELEASE_LEVEL_FINAL
3246     s = "final";
3247 #endif
3248 
3249 #define SetIntItem(flag) \
3250     PyStructSequence_SET_ITEM(version_info, pos++, PyLong_FromLong(flag))
3251 #define SetStrItem(flag) \
3252     PyStructSequence_SET_ITEM(version_info, pos++, PyUnicode_FromString(flag))
3253 
3254     SetIntItem(PY_MAJOR_VERSION);
3255     SetIntItem(PY_MINOR_VERSION);
3256     SetIntItem(PY_MICRO_VERSION);
3257     SetStrItem(s);
3258     SetIntItem(PY_RELEASE_SERIAL);
3259 #undef SetIntItem
3260 #undef SetStrItem
3261 
3262     if (_PyErr_Occurred(tstate)) {
3263         Py_CLEAR(version_info);
3264         return NULL;
3265     }
3266     return version_info;
3267 }
3268 
3269 /* sys.implementation values */
3270 #define NAME "cpython"
3271 const char *_PySys_ImplName = NAME;
3272 #define MAJOR Py_STRINGIFY(PY_MAJOR_VERSION)
3273 #define MINOR Py_STRINGIFY(PY_MINOR_VERSION)
3274 #define TAG NAME "-" MAJOR MINOR
3275 const char *_PySys_ImplCacheTag = TAG;
3276 #undef NAME
3277 #undef MAJOR
3278 #undef MINOR
3279 #undef TAG
3280 
3281 static PyObject *
make_impl_info(PyObject * version_info)3282 make_impl_info(PyObject *version_info)
3283 {
3284     int res;
3285     PyObject *impl_info, *value, *ns;
3286 
3287     impl_info = PyDict_New();
3288     if (impl_info == NULL)
3289         return NULL;
3290 
3291     /* populate the dict */
3292 
3293     value = PyUnicode_FromString(_PySys_ImplName);
3294     if (value == NULL)
3295         goto error;
3296     res = PyDict_SetItemString(impl_info, "name", value);
3297     Py_DECREF(value);
3298     if (res < 0)
3299         goto error;
3300 
3301     value = PyUnicode_FromString(_PySys_ImplCacheTag);
3302     if (value == NULL)
3303         goto error;
3304     res = PyDict_SetItemString(impl_info, "cache_tag", value);
3305     Py_DECREF(value);
3306     if (res < 0)
3307         goto error;
3308 
3309     res = PyDict_SetItemString(impl_info, "version", version_info);
3310     if (res < 0)
3311         goto error;
3312 
3313     value = PyLong_FromLong(PY_VERSION_HEX);
3314     if (value == NULL)
3315         goto error;
3316     res = PyDict_SetItemString(impl_info, "hexversion", value);
3317     Py_DECREF(value);
3318     if (res < 0)
3319         goto error;
3320 
3321 #ifdef MULTIARCH
3322     value = PyUnicode_FromString(MULTIARCH);
3323     if (value == NULL)
3324         goto error;
3325     res = PyDict_SetItemString(impl_info, "_multiarch", value);
3326     Py_DECREF(value);
3327     if (res < 0)
3328         goto error;
3329 #endif
3330 
3331     /* dict ready */
3332 
3333     ns = _PyNamespace_New(impl_info);
3334     Py_DECREF(impl_info);
3335     return ns;
3336 
3337 error:
3338     Py_CLEAR(impl_info);
3339     return NULL;
3340 }
3341 
3342 #ifdef __EMSCRIPTEN__
3343 
3344 PyDoc_STRVAR(emscripten_info__doc__,
3345 "sys._emscripten_info\n\
3346 \n\
3347 WebAssembly Emscripten platform information.");
3348 
3349 static PyTypeObject *EmscriptenInfoType;
3350 
3351 static PyStructSequence_Field emscripten_info_fields[] = {
3352     {"emscripten_version", "Emscripten version (major, minor, micro)"},
3353     {"runtime", "Runtime (Node.JS version, browser user agent)"},
3354     {"pthreads", "pthread support"},
3355     {"shared_memory", "shared memory support"},
3356     {0}
3357 };
3358 
3359 static PyStructSequence_Desc emscripten_info_desc = {
3360     "sys._emscripten_info",     /* name */
3361     emscripten_info__doc__ ,    /* doc */
3362     emscripten_info_fields,     /* fields */
3363     4
3364 };
3365 
3366 EM_JS(char *, _Py_emscripten_runtime, (void), {
3367     var info;
3368     if (typeof navigator == 'object') {
3369         info = navigator.userAgent;
3370     } else if (typeof process == 'object') {
3371         info = "Node.js ".concat(process.version);
3372     } else {
3373         info = "UNKNOWN";
3374     }
3375     var len = lengthBytesUTF8(info) + 1;
3376     var res = _malloc(len);
3377     if (res) stringToUTF8(info, res, len);
3378 #if __wasm64__
3379     return BigInt(res);
3380 #else
3381     return res;
3382 #endif
3383 });
3384 
3385 static PyObject *
make_emscripten_info(void)3386 make_emscripten_info(void)
3387 {
3388     PyObject *emscripten_info = NULL;
3389     PyObject *version = NULL;
3390     char *ua;
3391     int pos = 0;
3392 
3393     emscripten_info = PyStructSequence_New(EmscriptenInfoType);
3394     if (emscripten_info == NULL) {
3395         return NULL;
3396     }
3397 
3398     version = Py_BuildValue("(iii)",
3399         __EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__);
3400     if (version == NULL) {
3401         goto error;
3402     }
3403     PyStructSequence_SET_ITEM(emscripten_info, pos++, version);
3404 
3405     ua = _Py_emscripten_runtime();
3406     if (ua != NULL) {
3407         PyObject *oua = PyUnicode_DecodeUTF8(ua, strlen(ua), "strict");
3408         free(ua);
3409         if (oua == NULL) {
3410             goto error;
3411         }
3412         PyStructSequence_SET_ITEM(emscripten_info, pos++, oua);
3413     } else {
3414         PyStructSequence_SET_ITEM(emscripten_info, pos++, Py_NewRef(Py_None));
3415     }
3416 
3417 #define SetBoolItem(flag) \
3418     PyStructSequence_SET_ITEM(emscripten_info, pos++, PyBool_FromLong(flag))
3419 
3420 #ifdef __EMSCRIPTEN_PTHREADS__
3421     SetBoolItem(1);
3422 #else
3423     SetBoolItem(0);
3424 #endif
3425 
3426 #ifdef __EMSCRIPTEN_SHARED_MEMORY__
3427     SetBoolItem(1);
3428 #else
3429     SetBoolItem(0);
3430 #endif
3431 
3432 #undef SetBoolItem
3433 
3434     if (PyErr_Occurred()) {
3435         goto error;
3436     }
3437     return emscripten_info;
3438 
3439   error:
3440     Py_CLEAR(emscripten_info);
3441     return NULL;
3442 }
3443 
3444 #endif // __EMSCRIPTEN__
3445 
3446 static struct PyModuleDef sysmodule = {
3447     PyModuleDef_HEAD_INIT,
3448     "sys",
3449     sys_doc,
3450     -1, /* multiple "initialization" just copies the module dict. */
3451     sys_methods,
3452     NULL,
3453     NULL,
3454     NULL,
3455     NULL
3456 };
3457 
3458 /* Updating the sys namespace, returning NULL pointer on error */
3459 #define SET_SYS(key, value)                                \
3460     do {                                                   \
3461         PyObject *v = (value);                             \
3462         if (v == NULL) {                                   \
3463             goto err_occurred;                             \
3464         }                                                  \
3465         res = PyDict_SetItemString(sysdict, key, v);       \
3466         Py_DECREF(v);                                      \
3467         if (res < 0) {                                     \
3468             goto err_occurred;                             \
3469         }                                                  \
3470     } while (0)
3471 
3472 #define SET_SYS_FROM_STRING(key, value) \
3473         SET_SYS(key, PyUnicode_FromString(value))
3474 
3475 static PyStatus
_PySys_InitCore(PyThreadState * tstate,PyObject * sysdict)3476 _PySys_InitCore(PyThreadState *tstate, PyObject *sysdict)
3477 {
3478     PyObject *version_info;
3479     int res;
3480     PyInterpreterState *interp = tstate->interp;
3481 
3482     /* stdin/stdout/stderr are set in pylifecycle.c */
3483 
3484 #define COPY_SYS_ATTR(tokey, fromkey) \
3485         SET_SYS(tokey, PyMapping_GetItemString(sysdict, fromkey))
3486 
3487     COPY_SYS_ATTR("__displayhook__", "displayhook");
3488     COPY_SYS_ATTR("__excepthook__", "excepthook");
3489     COPY_SYS_ATTR("__breakpointhook__", "breakpointhook");
3490     COPY_SYS_ATTR("__unraisablehook__", "unraisablehook");
3491 
3492 #undef COPY_SYS_ATTR
3493 
3494     SET_SYS_FROM_STRING("version", Py_GetVersion());
3495     SET_SYS("hexversion", PyLong_FromLong(PY_VERSION_HEX));
3496     SET_SYS("_git", Py_BuildValue("(szz)", "CPython", _Py_gitidentifier(),
3497                                   _Py_gitversion()));
3498     SET_SYS_FROM_STRING("_framework", _PYTHONFRAMEWORK);
3499     SET_SYS("api_version", PyLong_FromLong(PYTHON_API_VERSION));
3500     SET_SYS_FROM_STRING("copyright", Py_GetCopyright());
3501     SET_SYS_FROM_STRING("platform", Py_GetPlatform());
3502     SET_SYS("maxsize", PyLong_FromSsize_t(PY_SSIZE_T_MAX));
3503     SET_SYS("float_info", PyFloat_GetInfo());
3504     SET_SYS("int_info", PyLong_GetInfo());
3505     /* initialize hash_info */
3506     if (_PyStructSequence_InitBuiltin(interp, &Hash_InfoType,
3507                                       &hash_info_desc) < 0)
3508     {
3509         goto type_init_failed;
3510     }
3511     SET_SYS("hash_info", get_hash_info(tstate));
3512     SET_SYS("maxunicode", PyLong_FromLong(0x10FFFF));
3513     SET_SYS("builtin_module_names", list_builtin_module_names());
3514     SET_SYS("stdlib_module_names", list_stdlib_module_names());
3515 #if PY_BIG_ENDIAN
3516     SET_SYS_FROM_STRING("byteorder", "big");
3517 #else
3518     SET_SYS_FROM_STRING("byteorder", "little");
3519 #endif
3520 
3521 #ifdef MS_COREDLL
3522     SET_SYS("dllhandle", PyLong_FromVoidPtr(PyWin_DLLhModule));
3523     SET_SYS_FROM_STRING("winver", PyWin_DLLVersionString);
3524 #endif
3525 #ifdef ABIFLAGS
3526     SET_SYS_FROM_STRING("abiflags", ABIFLAGS);
3527 #endif
3528 
3529 #define ENSURE_INFO_TYPE(TYPE, DESC) \
3530     do { \
3531         if (_PyStructSequence_InitBuiltinWithFlags( \
3532                 interp, &TYPE, &DESC, Py_TPFLAGS_DISALLOW_INSTANTIATION) < 0) { \
3533             goto type_init_failed; \
3534         } \
3535     } while (0)
3536 
3537     /* version_info */
3538     ENSURE_INFO_TYPE(VersionInfoType, version_info_desc);
3539     version_info = make_version_info(tstate);
3540     SET_SYS("version_info", version_info);
3541 
3542     /* implementation */
3543     SET_SYS("implementation", make_impl_info(version_info));
3544 
3545     // sys.flags: updated in-place later by _PySys_UpdateConfig()
3546     ENSURE_INFO_TYPE(FlagsType, flags_desc);
3547     SET_SYS("flags", make_flags(tstate->interp));
3548 
3549 #if defined(MS_WINDOWS)
3550     /* getwindowsversion */
3551     ENSURE_INFO_TYPE(WindowsVersionType, windows_version_desc);
3552 
3553     SET_SYS_FROM_STRING("_vpath", VPATH);
3554 #endif
3555 
3556 #undef ENSURE_INFO_TYPE
3557 
3558     /* float repr style: 0.03 (short) vs 0.029999999999999999 (legacy) */
3559 #if _PY_SHORT_FLOAT_REPR == 1
3560     SET_SYS_FROM_STRING("float_repr_style", "short");
3561 #else
3562     SET_SYS_FROM_STRING("float_repr_style", "legacy");
3563 #endif
3564 
3565     SET_SYS("thread_info", PyThread_GetInfo());
3566 
3567     /* initialize asyncgen_hooks */
3568     if (_PyStructSequence_InitBuiltin(interp, &AsyncGenHooksType,
3569                                       &asyncgen_hooks_desc) < 0)
3570     {
3571         goto type_init_failed;
3572     }
3573 
3574 #ifdef __EMSCRIPTEN__
3575     if (EmscriptenInfoType == NULL) {
3576         EmscriptenInfoType = PyStructSequence_NewType(&emscripten_info_desc);
3577         if (EmscriptenInfoType == NULL) {
3578             goto type_init_failed;
3579         }
3580     }
3581     SET_SYS("_emscripten_info", make_emscripten_info());
3582 #endif
3583 
3584     /* adding sys.path_hooks and sys.path_importer_cache */
3585     SET_SYS("meta_path", PyList_New(0));
3586     SET_SYS("path_importer_cache", PyDict_New());
3587     SET_SYS("path_hooks", PyList_New(0));
3588 
3589     if (_PyErr_Occurred(tstate)) {
3590         goto err_occurred;
3591     }
3592     return _PyStatus_OK();
3593 
3594 type_init_failed:
3595     return _PyStatus_ERR("failed to initialize a type");
3596 
3597 err_occurred:
3598     return _PyStatus_ERR("can't initialize sys module");
3599 }
3600 
3601 static int
sys_add_xoption(PyObject * opts,const wchar_t * s)3602 sys_add_xoption(PyObject *opts, const wchar_t *s)
3603 {
3604     PyObject *name, *value = NULL;
3605 
3606     const wchar_t *name_end = wcschr(s, L'=');
3607     if (!name_end) {
3608         name = PyUnicode_FromWideChar(s, -1);
3609         if (name == NULL) {
3610             goto error;
3611         }
3612         value = Py_NewRef(Py_True);
3613     }
3614     else {
3615         name = PyUnicode_FromWideChar(s, name_end - s);
3616         if (name == NULL) {
3617             goto error;
3618         }
3619         value = PyUnicode_FromWideChar(name_end + 1, -1);
3620         if (value == NULL) {
3621             goto error;
3622         }
3623     }
3624     if (PyDict_SetItem(opts, name, value) < 0) {
3625         goto error;
3626     }
3627     Py_DECREF(name);
3628     Py_DECREF(value);
3629     return 0;
3630 
3631 error:
3632     Py_XDECREF(name);
3633     Py_XDECREF(value);
3634     return -1;
3635 }
3636 
3637 
3638 static PyObject*
sys_create_xoptions_dict(const PyConfig * config)3639 sys_create_xoptions_dict(const PyConfig *config)
3640 {
3641     Py_ssize_t nxoption = config->xoptions.length;
3642     wchar_t * const * xoptions = config->xoptions.items;
3643     PyObject *dict = PyDict_New();
3644     if (dict == NULL) {
3645         return NULL;
3646     }
3647 
3648     for (Py_ssize_t i=0; i < nxoption; i++) {
3649         const wchar_t *option = xoptions[i];
3650         if (sys_add_xoption(dict, option) < 0) {
3651             Py_DECREF(dict);
3652             return NULL;
3653         }
3654     }
3655 
3656     return dict;
3657 }
3658 
3659 
3660 // Update sys attributes for a new PyConfig configuration.
3661 // This function also adds attributes that _PySys_InitCore() didn't add.
3662 int
_PySys_UpdateConfig(PyThreadState * tstate)3663 _PySys_UpdateConfig(PyThreadState *tstate)
3664 {
3665     PyInterpreterState *interp = tstate->interp;
3666     PyObject *sysdict = interp->sysdict;
3667     const PyConfig *config = _PyInterpreterState_GetConfig(interp);
3668     int res;
3669 
3670 #define COPY_LIST(KEY, VALUE) \
3671         SET_SYS(KEY, _PyWideStringList_AsList(&(VALUE)));
3672 
3673 #define SET_SYS_FROM_WSTR(KEY, VALUE) \
3674         SET_SYS(KEY, PyUnicode_FromWideChar(VALUE, -1));
3675 
3676 #define COPY_WSTR(SYS_ATTR, WSTR) \
3677     if (WSTR != NULL) { \
3678         SET_SYS_FROM_WSTR(SYS_ATTR, WSTR); \
3679     }
3680 
3681     if (config->module_search_paths_set) {
3682         COPY_LIST("path", config->module_search_paths);
3683     }
3684 
3685     COPY_WSTR("executable", config->executable);
3686     COPY_WSTR("_base_executable", config->base_executable);
3687     COPY_WSTR("prefix", config->prefix);
3688     COPY_WSTR("base_prefix", config->base_prefix);
3689     COPY_WSTR("exec_prefix", config->exec_prefix);
3690     COPY_WSTR("base_exec_prefix", config->base_exec_prefix);
3691     COPY_WSTR("platlibdir", config->platlibdir);
3692 
3693     if (config->pycache_prefix != NULL) {
3694         SET_SYS_FROM_WSTR("pycache_prefix", config->pycache_prefix);
3695     } else {
3696         if (PyDict_SetItemString(sysdict, "pycache_prefix", Py_None) < 0) {
3697             return -1;
3698         }
3699     }
3700 
3701     COPY_LIST("argv", config->argv);
3702     COPY_LIST("orig_argv", config->orig_argv);
3703     COPY_LIST("warnoptions", config->warnoptions);
3704 
3705     SET_SYS("_xoptions", sys_create_xoptions_dict(config));
3706 
3707     const wchar_t *stdlibdir = _Py_GetStdlibDir();
3708     if (stdlibdir != NULL) {
3709         SET_SYS_FROM_WSTR("_stdlib_dir", stdlibdir);
3710     }
3711     else {
3712         if (PyDict_SetItemString(sysdict, "_stdlib_dir", Py_None) < 0) {
3713             return -1;
3714         }
3715     }
3716 
3717 #undef SET_SYS_FROM_WSTR
3718 #undef COPY_LIST
3719 #undef COPY_WSTR
3720 
3721     // sys.flags
3722     PyObject *flags = _PySys_GetObject(interp, "flags"); // borrowed ref
3723     if (flags == NULL) {
3724         if (!_PyErr_Occurred(tstate)) {
3725             _PyErr_SetString(tstate, PyExc_RuntimeError, "lost sys.flags");
3726         }
3727         return -1;
3728     }
3729     if (set_flags_from_config(interp, flags) < 0) {
3730         return -1;
3731     }
3732 
3733     SET_SYS("dont_write_bytecode", PyBool_FromLong(!config->write_bytecode));
3734 
3735     if (_PyErr_Occurred(tstate)) {
3736         goto err_occurred;
3737     }
3738 
3739     return 0;
3740 
3741 err_occurred:
3742     return -1;
3743 }
3744 
3745 #undef SET_SYS
3746 #undef SET_SYS_FROM_STRING
3747 
3748 
3749 /* Set up a preliminary stderr printer until we have enough
3750    infrastructure for the io module in place.
3751 
3752    Use UTF-8/backslashreplace and ignore EAGAIN errors. */
3753 static PyStatus
_PySys_SetPreliminaryStderr(PyObject * sysdict)3754 _PySys_SetPreliminaryStderr(PyObject *sysdict)
3755 {
3756     PyObject *pstderr = PyFile_NewStdPrinter(fileno(stderr));
3757     if (pstderr == NULL) {
3758         goto error;
3759     }
3760     if (PyDict_SetItem(sysdict, &_Py_ID(stderr), pstderr) < 0) {
3761         goto error;
3762     }
3763     if (PyDict_SetItemString(sysdict, "__stderr__", pstderr) < 0) {
3764         goto error;
3765     }
3766     Py_DECREF(pstderr);
3767     return _PyStatus_OK();
3768 
3769 error:
3770     Py_XDECREF(pstderr);
3771     return _PyStatus_ERR("can't set preliminary stderr");
3772 }
3773 
3774 PyObject *_Py_CreateMonitoringObject(void);
3775 
3776 /* Create sys module without all attributes.
3777    _PySys_UpdateConfig() should be called later to add remaining attributes. */
3778 PyStatus
_PySys_Create(PyThreadState * tstate,PyObject ** sysmod_p)3779 _PySys_Create(PyThreadState *tstate, PyObject **sysmod_p)
3780 {
3781     assert(!_PyErr_Occurred(tstate));
3782 
3783     PyInterpreterState *interp = tstate->interp;
3784 
3785     PyObject *modules = _PyImport_InitModules(interp);
3786     if (modules == NULL) {
3787         goto error;
3788     }
3789 
3790     PyObject *sysmod = _PyModule_CreateInitialized(&sysmodule, PYTHON_API_VERSION);
3791     if (sysmod == NULL) {
3792         return _PyStatus_ERR("failed to create a module object");
3793     }
3794 #ifdef Py_GIL_DISABLED
3795     PyUnstable_Module_SetGIL(sysmod, Py_MOD_GIL_NOT_USED);
3796 #endif
3797 
3798     PyObject *sysdict = PyModule_GetDict(sysmod);
3799     if (sysdict == NULL) {
3800         goto error;
3801     }
3802     interp->sysdict = Py_NewRef(sysdict);
3803 
3804     interp->sysdict_copy = PyDict_Copy(sysdict);
3805     if (interp->sysdict_copy == NULL) {
3806         goto error;
3807     }
3808 
3809     if (PyDict_SetItemString(sysdict, "modules", modules) < 0) {
3810         goto error;
3811     }
3812 
3813     PyStatus status = _PySys_SetPreliminaryStderr(sysdict);
3814     if (_PyStatus_EXCEPTION(status)) {
3815         return status;
3816     }
3817 
3818     status = _PySys_InitCore(tstate, sysdict);
3819     if (_PyStatus_EXCEPTION(status)) {
3820         return status;
3821     }
3822 
3823     if (_PyImport_FixupBuiltin(tstate, sysmod, "sys", modules) < 0) {
3824         goto error;
3825     }
3826 
3827     PyObject *monitoring = _Py_CreateMonitoringObject();
3828     if (monitoring == NULL) {
3829         goto error;
3830     }
3831     int err = PyDict_SetItemString(sysdict, "monitoring", monitoring);
3832     Py_DECREF(monitoring);
3833     if (err < 0) {
3834         goto error;
3835     }
3836 
3837     assert(!_PyErr_Occurred(tstate));
3838 
3839     *sysmod_p = sysmod;
3840     return _PyStatus_OK();
3841 
3842 error:
3843     return _PyStatus_ERR("can't initialize sys module");
3844 }
3845 
3846 
3847 void
_PySys_FiniTypes(PyInterpreterState * interp)3848 _PySys_FiniTypes(PyInterpreterState *interp)
3849 {
3850     _PyStructSequence_FiniBuiltin(interp, &VersionInfoType);
3851     _PyStructSequence_FiniBuiltin(interp, &FlagsType);
3852 #if defined(MS_WINDOWS)
3853     _PyStructSequence_FiniBuiltin(interp, &WindowsVersionType);
3854 #endif
3855     _PyStructSequence_FiniBuiltin(interp, &Hash_InfoType);
3856     _PyStructSequence_FiniBuiltin(interp, &AsyncGenHooksType);
3857 #ifdef __EMSCRIPTEN__
3858     if (_Py_IsMainInterpreter(interp)) {
3859         Py_CLEAR(EmscriptenInfoType);
3860     }
3861 #endif
3862 }
3863 
3864 
3865 static PyObject *
makepathobject(const wchar_t * path,wchar_t delim)3866 makepathobject(const wchar_t *path, wchar_t delim)
3867 {
3868     int i, n;
3869     const wchar_t *p;
3870     PyObject *v, *w;
3871 
3872     n = 1;
3873     p = path;
3874     while ((p = wcschr(p, delim)) != NULL) {
3875         n++;
3876         p++;
3877     }
3878     v = PyList_New(n);
3879     if (v == NULL)
3880         return NULL;
3881     for (i = 0; ; i++) {
3882         p = wcschr(path, delim);
3883         if (p == NULL)
3884             p = path + wcslen(path); /* End of string */
3885         w = PyUnicode_FromWideChar(path, (Py_ssize_t)(p - path));
3886         if (w == NULL) {
3887             Py_DECREF(v);
3888             return NULL;
3889         }
3890         PyList_SET_ITEM(v, i, w);
3891         if (*p == '\0')
3892             break;
3893         path = p+1;
3894     }
3895     return v;
3896 }
3897 
3898 // Removed in Python 3.13 API, but kept for the stable ABI
3899 PyAPI_FUNC(void)
PySys_SetPath(const wchar_t * path)3900 PySys_SetPath(const wchar_t *path)
3901 {
3902     PyObject *v;
3903     if ((v = makepathobject(path, DELIM)) == NULL)
3904         Py_FatalError("can't create sys.path");
3905     PyInterpreterState *interp = _PyInterpreterState_GET();
3906     if (sys_set_object(interp, &_Py_ID(path), v) != 0) {
3907         Py_FatalError("can't assign sys.path");
3908     }
3909     Py_DECREF(v);
3910 }
3911 
3912 static PyObject *
make_sys_argv(int argc,wchar_t * const * argv)3913 make_sys_argv(int argc, wchar_t * const * argv)
3914 {
3915     PyObject *list = PyList_New(argc);
3916     if (list == NULL) {
3917         return NULL;
3918     }
3919 
3920     for (Py_ssize_t i = 0; i < argc; i++) {
3921         PyObject *v = PyUnicode_FromWideChar(argv[i], -1);
3922         if (v == NULL) {
3923             Py_DECREF(list);
3924             return NULL;
3925         }
3926         PyList_SET_ITEM(list, i, v);
3927     }
3928     return list;
3929 }
3930 
3931 void
PySys_SetArgvEx(int argc,wchar_t ** argv,int updatepath)3932 PySys_SetArgvEx(int argc, wchar_t **argv, int updatepath)
3933 {
3934     wchar_t* empty_argv[1] = {L""};
3935     PyThreadState *tstate = _PyThreadState_GET();
3936 
3937     if (argc < 1 || argv == NULL) {
3938         /* Ensure at least one (empty) argument is seen */
3939         argv = empty_argv;
3940         argc = 1;
3941     }
3942 
3943     PyObject *av = make_sys_argv(argc, argv);
3944     if (av == NULL) {
3945         Py_FatalError("no mem for sys.argv");
3946     }
3947     if (sys_set_object_str(tstate->interp, "argv", av) != 0) {
3948         Py_DECREF(av);
3949         Py_FatalError("can't assign sys.argv");
3950     }
3951     Py_DECREF(av);
3952 
3953     if (updatepath) {
3954         /* If argv[0] is not '-c' nor '-m', prepend argv[0] to sys.path.
3955            If argv[0] is a symlink, use the real path. */
3956         const PyWideStringList argv_list = {.length = argc, .items = argv};
3957         PyObject *path0 = NULL;
3958         if (_PyPathConfig_ComputeSysPath0(&argv_list, &path0)) {
3959             if (path0 == NULL) {
3960                 Py_FatalError("can't compute path0 from argv");
3961             }
3962 
3963             PyObject *sys_path = _PySys_GetAttr(tstate, &_Py_ID(path));
3964             if (sys_path != NULL) {
3965                 if (PyList_Insert(sys_path, 0, path0) < 0) {
3966                     Py_DECREF(path0);
3967                     Py_FatalError("can't prepend path0 to sys.path");
3968                 }
3969             }
3970             Py_DECREF(path0);
3971         }
3972     }
3973 }
3974 
3975 void
PySys_SetArgv(int argc,wchar_t ** argv)3976 PySys_SetArgv(int argc, wchar_t **argv)
3977 {
3978 _Py_COMP_DIAG_PUSH
3979 _Py_COMP_DIAG_IGNORE_DEPR_DECLS
3980     PySys_SetArgvEx(argc, argv, Py_IsolatedFlag == 0);
3981 _Py_COMP_DIAG_POP
3982 }
3983 
3984 /* Reimplementation of PyFile_WriteString() no calling indirectly
3985    PyErr_CheckSignals(): avoid the call to PyObject_Str(). */
3986 
3987 static int
sys_pyfile_write_unicode(PyObject * unicode,PyObject * file)3988 sys_pyfile_write_unicode(PyObject *unicode, PyObject *file)
3989 {
3990     if (file == NULL)
3991         return -1;
3992     assert(unicode != NULL);
3993     PyObject *result = PyObject_CallMethodOneArg(file, &_Py_ID(write), unicode);
3994     if (result == NULL) {
3995         return -1;
3996     }
3997     Py_DECREF(result);
3998     return 0;
3999 }
4000 
4001 static int
sys_pyfile_write(const char * text,PyObject * file)4002 sys_pyfile_write(const char *text, PyObject *file)
4003 {
4004     PyObject *unicode = NULL;
4005     int err;
4006 
4007     if (file == NULL)
4008         return -1;
4009 
4010     unicode = PyUnicode_FromString(text);
4011     if (unicode == NULL)
4012         return -1;
4013 
4014     err = sys_pyfile_write_unicode(unicode, file);
4015     Py_DECREF(unicode);
4016     return err;
4017 }
4018 
4019 /* APIs to write to sys.stdout or sys.stderr using a printf-like interface.
4020    Adapted from code submitted by Just van Rossum.
4021 
4022    PySys_WriteStdout(format, ...)
4023    PySys_WriteStderr(format, ...)
4024 
4025       The first function writes to sys.stdout; the second to sys.stderr.  When
4026       there is a problem, they write to the real (C level) stdout or stderr;
4027       no exceptions are raised.
4028 
4029       PyErr_CheckSignals() is not called to avoid the execution of the Python
4030       signal handlers: they may raise a new exception whereas sys_write()
4031       ignores all exceptions.
4032 
4033       Both take a printf-style format string as their first argument followed
4034       by a variable length argument list determined by the format string.
4035 
4036       *** WARNING ***
4037 
4038       The format should limit the total size of the formatted output string to
4039       1000 bytes.  In particular, this means that no unrestricted "%s" formats
4040       should occur; these should be limited using "%.<N>s where <N> is a
4041       decimal number calculated so that <N> plus the maximum size of other
4042       formatted text does not exceed 1000 bytes.  Also watch out for "%f",
4043       which can print hundreds of digits for very large numbers.
4044 
4045  */
4046 
4047 static void
sys_write(PyObject * key,FILE * fp,const char * format,va_list va)4048 sys_write(PyObject *key, FILE *fp, const char *format, va_list va)
4049 {
4050     PyObject *file;
4051     char buffer[1001];
4052     int written;
4053     PyThreadState *tstate = _PyThreadState_GET();
4054 
4055     PyObject *exc = _PyErr_GetRaisedException(tstate);
4056     file = _PySys_GetAttr(tstate, key);
4057     written = PyOS_vsnprintf(buffer, sizeof(buffer), format, va);
4058     if (sys_pyfile_write(buffer, file) != 0) {
4059         _PyErr_Clear(tstate);
4060         fputs(buffer, fp);
4061     }
4062     if (written < 0 || (size_t)written >= sizeof(buffer)) {
4063         const char *truncated = "... truncated";
4064         if (sys_pyfile_write(truncated, file) != 0)
4065             fputs(truncated, fp);
4066     }
4067     _PyErr_SetRaisedException(tstate, exc);
4068 }
4069 
4070 void
PySys_WriteStdout(const char * format,...)4071 PySys_WriteStdout(const char *format, ...)
4072 {
4073     va_list va;
4074 
4075     va_start(va, format);
4076     sys_write(&_Py_ID(stdout), stdout, format, va);
4077     va_end(va);
4078 }
4079 
4080 void
PySys_WriteStderr(const char * format,...)4081 PySys_WriteStderr(const char *format, ...)
4082 {
4083     va_list va;
4084 
4085     va_start(va, format);
4086     sys_write(&_Py_ID(stderr), stderr, format, va);
4087     va_end(va);
4088 }
4089 
4090 static void
sys_format(PyObject * key,FILE * fp,const char * format,va_list va)4091 sys_format(PyObject *key, FILE *fp, const char *format, va_list va)
4092 {
4093     PyObject *file, *message;
4094     const char *utf8;
4095     PyThreadState *tstate = _PyThreadState_GET();
4096 
4097     PyObject *exc = _PyErr_GetRaisedException(tstate);
4098     file = _PySys_GetAttr(tstate, key);
4099     message = PyUnicode_FromFormatV(format, va);
4100     if (message != NULL) {
4101         if (sys_pyfile_write_unicode(message, file) != 0) {
4102             _PyErr_Clear(tstate);
4103             utf8 = PyUnicode_AsUTF8(message);
4104             if (utf8 != NULL)
4105                 fputs(utf8, fp);
4106         }
4107         Py_DECREF(message);
4108     }
4109     _PyErr_SetRaisedException(tstate, exc);
4110 }
4111 
4112 void
PySys_FormatStdout(const char * format,...)4113 PySys_FormatStdout(const char *format, ...)
4114 {
4115     va_list va;
4116 
4117     va_start(va, format);
4118     sys_format(&_Py_ID(stdout), stdout, format, va);
4119     va_end(va);
4120 }
4121 
4122 void
PySys_FormatStderr(const char * format,...)4123 PySys_FormatStderr(const char *format, ...)
4124 {
4125     va_list va;
4126 
4127     va_start(va, format);
4128     sys_format(&_Py_ID(stderr), stderr, format, va);
4129     va_end(va);
4130 }
4131