Coverage Report

Created: 2026-04-12 06:54

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