Coverage Report

Created: 2026-06-14 06:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/Python-3.8.3/Objects/moduleobject.c
Line
Count
Source
1
2
/* Module object implementation */
3
4
#include "Python.h"
5
#include "pycore_pystate.h"
6
#include "structmember.h"
7
8
static Py_ssize_t max_module_number;
9
10
typedef struct {
11
    PyObject_HEAD
12
    PyObject *md_dict;
13
    struct PyModuleDef *md_def;
14
    void *md_state;
15
    PyObject *md_weaklist;
16
    PyObject *md_name;  /* for logging purposes after md_dict is cleared */
17
} PyModuleObject;
18
19
static PyMemberDef module_members[] = {
20
    {"__dict__", T_OBJECT, offsetof(PyModuleObject, md_dict), READONLY},
21
    {0}
22
};
23
24
25
/* Helper for sanity check for traverse not handling m_state == NULL
26
 * Issue #32374 */
27
#ifdef Py_DEBUG
28
static int
29
bad_traverse_test(PyObject *self, void *arg) {
30
    assert(self != NULL);
31
    return 0;
32
}
33
#endif
34
35
PyTypeObject PyModuleDef_Type = {
36
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
37
    "moduledef",                                /* tp_name */
38
    sizeof(struct PyModuleDef),                 /* tp_basicsize */
39
    0,                                          /* tp_itemsize */
40
};
41
42
43
PyObject*
44
PyModuleDef_Init(struct PyModuleDef* def)
45
204
{
46
204
    if (PyType_Ready(&PyModuleDef_Type) < 0)
47
0
         return NULL;
48
204
    if (def->m_base.m_index == 0) {
49
190
        max_module_number++;
50
190
        Py_REFCNT(def) = 1;
51
190
        Py_TYPE(def) = &PyModuleDef_Type;
52
190
        def->m_base.m_index = max_module_number;
53
190
    }
54
204
    return (PyObject*)def;
55
204
}
56
57
static int
58
module_init_dict(PyModuleObject *mod, PyObject *md_dict,
59
                 PyObject *name, PyObject *doc)
60
475
{
61
475
    _Py_IDENTIFIER(__name__);
62
475
    _Py_IDENTIFIER(__doc__);
63
475
    _Py_IDENTIFIER(__package__);
64
475
    _Py_IDENTIFIER(__loader__);
65
475
    _Py_IDENTIFIER(__spec__);
66
67
475
    if (md_dict == NULL)
68
0
        return -1;
69
475
    if (doc == NULL)
70
229
        doc = Py_None;
71
72
475
    if (_PyDict_SetItemId(md_dict, &PyId___name__, name) != 0)
73
0
        return -1;
74
475
    if (_PyDict_SetItemId(md_dict, &PyId___doc__, doc) != 0)
75
0
        return -1;
76
475
    if (_PyDict_SetItemId(md_dict, &PyId___package__, Py_None) != 0)
77
0
        return -1;
78
475
    if (_PyDict_SetItemId(md_dict, &PyId___loader__, Py_None) != 0)
79
0
        return -1;
80
475
    if (_PyDict_SetItemId(md_dict, &PyId___spec__, Py_None) != 0)
81
0
        return -1;
82
475
    if (PyUnicode_CheckExact(name)) {
83
475
        Py_INCREF(name);
84
475
        Py_XSETREF(mod->md_name, name);
85
475
    }
86
87
475
    return 0;
88
475
}
89
90
91
PyObject *
92
PyModule_NewObject(PyObject *name)
93
229
{
94
229
    PyModuleObject *m;
95
229
    m = PyObject_GC_New(PyModuleObject, &PyModule_Type);
96
229
    if (m == NULL)
97
0
        return NULL;
98
229
    m->md_def = NULL;
99
229
    m->md_state = NULL;
100
229
    m->md_weaklist = NULL;
101
229
    m->md_name = NULL;
102
229
    m->md_dict = PyDict_New();
103
229
    if (module_init_dict(m, m->md_dict, name, NULL) != 0)
104
0
        goto fail;
105
229
    PyObject_GC_Track(m);
106
229
    return (PyObject *)m;
107
108
0
 fail:
109
0
    Py_DECREF(m);
110
0
    return NULL;
111
229
}
112
113
PyObject *
114
PyModule_New(const char *name)
115
202
{
116
202
    PyObject *nameobj, *module;
117
202
    nameobj = PyUnicode_FromString(name);
118
202
    if (nameobj == NULL)
119
0
        return NULL;
120
202
    module = PyModule_NewObject(nameobj);
121
202
    Py_DECREF(nameobj);
122
202
    return module;
123
202
}
124
125
/* Check API/ABI version
126
 * Issues a warning on mismatch, which is usually not fatal.
127
 * Returns 0 if an exception is raised.
128
 */
129
static int
130
check_api_version(const char *name, int module_api_version)
131
203
{
132
203
    if (module_api_version != PYTHON_API_VERSION && module_api_version != PYTHON_ABI_VERSION) {
133
0
        int err;
134
0
        err = PyErr_WarnFormat(PyExc_RuntimeWarning, 1,
135
0
            "Python C API version mismatch for module %.100s: "
136
0
            "This Python has API version %d, module %.100s has version %d.",
137
0
             name,
138
0
             PYTHON_API_VERSION, name, module_api_version);
139
0
        if (err)
140
0
            return 0;
141
0
    }
142
203
    return 1;
143
203
}
144
145
static int
146
_add_methods_to_object(PyObject *module, PyObject *name, PyMethodDef *functions)
147
203
{
148
203
    PyObject *func;
149
203
    PyMethodDef *fdef;
150
151
5.21k
    for (fdef = functions; fdef->ml_name != NULL; fdef++) {
152
5.00k
        if ((fdef->ml_flags & METH_CLASS) ||
153
5.00k
            (fdef->ml_flags & METH_STATIC)) {
154
0
            PyErr_SetString(PyExc_ValueError,
155
0
                            "module functions cannot set"
156
0
                            " METH_CLASS or METH_STATIC");
157
0
            return -1;
158
0
        }
159
5.00k
        func = PyCFunction_NewEx(fdef, (PyObject*)module, name);
160
5.00k
        if (func == NULL) {
161
0
            return -1;
162
0
        }
163
5.00k
        if (PyObject_SetAttrString(module, fdef->ml_name, func) != 0) {
164
0
            Py_DECREF(func);
165
0
            return -1;
166
0
        }
167
5.00k
        Py_DECREF(func);
168
5.00k
    }
169
170
203
    return 0;
171
203
}
172
173
PyObject *
174
PyModule_Create2(struct PyModuleDef* module, int module_api_version)
175
176
{
176
176
    if (!_PyImport_IsInitialized(_PyInterpreterState_Get()))
177
0
        Py_FatalError("Python import machinery not initialized");
178
176
    return _PyModule_CreateInitialized(module, module_api_version);
179
176
}
180
181
PyObject *
182
_PyModule_CreateInitialized(struct PyModuleDef* module, int module_api_version)
183
202
{
184
202
    const char* name;
185
202
    PyModuleObject *m;
186
187
202
    if (!PyModuleDef_Init(module))
188
0
        return NULL;
189
202
    name = module->m_name;
190
202
    if (!check_api_version(name, module_api_version)) {
191
0
        return NULL;
192
0
    }
193
202
    if (module->m_slots) {
194
0
        PyErr_Format(
195
0
            PyExc_SystemError,
196
0
            "module %s: PyModule_Create is incompatible with m_slots", name);
197
0
        return NULL;
198
0
    }
199
    /* Make sure name is fully qualified.
200
201
       This is a bit of a hack: when the shared library is loaded,
202
       the module name is "package.module", but the module calls
203
       PyModule_Create*() with just "module" for the name.  The shared
204
       library loader squirrels away the true name of the module in
205
       _Py_PackageContext, and PyModule_Create*() will substitute this
206
       (if the name actually matches).
207
    */
208
202
    if (_Py_PackageContext != NULL) {
209
0
        const char *p = strrchr(_Py_PackageContext, '.');
210
0
        if (p != NULL && strcmp(module->m_name, p+1) == 0) {
211
0
            name = _Py_PackageContext;
212
0
            _Py_PackageContext = NULL;
213
0
        }
214
0
    }
215
202
    if ((m = (PyModuleObject*)PyModule_New(name)) == NULL)
216
0
        return NULL;
217
218
202
    if (module->m_size > 0) {
219
13
        m->md_state = PyMem_MALLOC(module->m_size);
220
13
        if (!m->md_state) {
221
0
            PyErr_NoMemory();
222
0
            Py_DECREF(m);
223
0
            return NULL;
224
0
        }
225
13
        memset(m->md_state, 0, module->m_size);
226
13
    }
227
228
202
    if (module->m_methods != NULL) {
229
202
        if (PyModule_AddFunctions((PyObject *) m, module->m_methods) != 0) {
230
0
            Py_DECREF(m);
231
0
            return NULL;
232
0
        }
233
202
    }
234
202
    if (module->m_doc != NULL) {
235
188
        if (PyModule_SetDocString((PyObject *) m, module->m_doc) != 0) {
236
0
            Py_DECREF(m);
237
0
            return NULL;
238
0
        }
239
188
    }
240
202
    m->md_def = module;
241
202
    return (PyObject*)m;
242
202
}
243
244
PyObject *
245
PyModule_FromDefAndSpec2(struct PyModuleDef* def, PyObject *spec, int module_api_version)
246
1
{
247
1
    PyModuleDef_Slot* cur_slot;
248
1
    PyObject *(*create)(PyObject *, PyModuleDef*) = NULL;
249
1
    PyObject *nameobj;
250
1
    PyObject *m = NULL;
251
1
    int has_execution_slots = 0;
252
1
    const char *name;
253
1
    int ret;
254
255
1
    PyModuleDef_Init(def);
256
257
1
    nameobj = PyObject_GetAttrString(spec, "name");
258
1
    if (nameobj == NULL) {
259
0
        return NULL;
260
0
    }
261
1
    name = PyUnicode_AsUTF8(nameobj);
262
1
    if (name == NULL) {
263
0
        goto error;
264
0
    }
265
266
1
    if (!check_api_version(name, module_api_version)) {
267
0
        goto error;
268
0
    }
269
270
1
    if (def->m_size < 0) {
271
0
        PyErr_Format(
272
0
            PyExc_SystemError,
273
0
            "module %s: m_size may not be negative for multi-phase initialization",
274
0
            name);
275
0
        goto error;
276
0
    }
277
278
2
    for (cur_slot = def->m_slots; cur_slot && cur_slot->slot; cur_slot++) {
279
1
        if (cur_slot->slot == Py_mod_create) {
280
0
            if (create) {
281
0
                PyErr_Format(
282
0
                    PyExc_SystemError,
283
0
                    "module %s has multiple create slots",
284
0
                    name);
285
0
                goto error;
286
0
            }
287
0
            create = cur_slot->value;
288
1
        } else if (cur_slot->slot < 0 || cur_slot->slot > _Py_mod_LAST_SLOT) {
289
0
            PyErr_Format(
290
0
                PyExc_SystemError,
291
0
                "module %s uses unknown slot ID %i",
292
0
                name, cur_slot->slot);
293
0
            goto error;
294
1
        } else {
295
1
            has_execution_slots = 1;
296
1
        }
297
1
    }
298
299
1
    if (create) {
300
0
        m = create(spec, def);
301
0
        if (m == NULL) {
302
0
            if (!PyErr_Occurred()) {
303
0
                PyErr_Format(
304
0
                    PyExc_SystemError,
305
0
                    "creation of module %s failed without setting an exception",
306
0
                    name);
307
0
            }
308
0
            goto error;
309
0
        } else {
310
0
            if (PyErr_Occurred()) {
311
0
                PyErr_Format(PyExc_SystemError,
312
0
                            "creation of module %s raised unreported exception",
313
0
                            name);
314
0
                goto error;
315
0
            }
316
0
        }
317
1
    } else {
318
1
        m = PyModule_NewObject(nameobj);
319
1
        if (m == NULL) {
320
0
            goto error;
321
0
        }
322
1
    }
323
324
1
    if (PyModule_Check(m)) {
325
1
        ((PyModuleObject*)m)->md_state = NULL;
326
1
        ((PyModuleObject*)m)->md_def = def;
327
1
    } else {
328
0
        if (def->m_size > 0 || def->m_traverse || def->m_clear || def->m_free) {
329
0
            PyErr_Format(
330
0
                PyExc_SystemError,
331
0
                "module %s is not a module object, but requests module state",
332
0
                name);
333
0
            goto error;
334
0
        }
335
0
        if (has_execution_slots) {
336
0
            PyErr_Format(
337
0
                PyExc_SystemError,
338
0
                "module %s specifies execution slots, but did not create "
339
0
                    "a ModuleType instance",
340
0
                name);
341
0
            goto error;
342
0
        }
343
0
    }
344
345
1
    if (def->m_methods != NULL) {
346
1
        ret = _add_methods_to_object(m, nameobj, def->m_methods);
347
1
        if (ret != 0) {
348
0
            goto error;
349
0
        }
350
1
    }
351
352
1
    if (def->m_doc != NULL) {
353
1
        ret = PyModule_SetDocString(m, def->m_doc);
354
1
        if (ret != 0) {
355
0
            goto error;
356
0
        }
357
1
    }
358
359
    /* Sanity check for traverse not handling m_state == NULL
360
     * This doesn't catch all possible cases, but in many cases it should
361
     * make many cases of invalid code crash or raise Valgrind issues
362
     * sooner than they would otherwise.
363
     * Issue #32374 */
364
#ifdef Py_DEBUG
365
    if (def->m_traverse != NULL) {
366
        def->m_traverse(m, bad_traverse_test, NULL);
367
    }
368
#endif
369
1
    Py_DECREF(nameobj);
370
1
    return m;
371
372
0
error:
373
0
    Py_DECREF(nameobj);
374
0
    Py_XDECREF(m);
375
0
    return NULL;
376
1
}
377
378
int
379
PyModule_ExecDef(PyObject *module, PyModuleDef *def)
380
151
{
381
151
    PyModuleDef_Slot *cur_slot;
382
151
    const char *name;
383
151
    int ret;
384
385
151
    name = PyModule_GetName(module);
386
151
    if (name == NULL) {
387
0
        return -1;
388
0
    }
389
390
151
    if (def->m_size >= 0) {
391
28
        PyModuleObject *md = (PyModuleObject*)module;
392
28
        if (md->md_state == NULL) {
393
            /* Always set a state pointer; this serves as a marker to skip
394
             * multiple initialization (importlib.reload() is no-op) */
395
28
            md->md_state = PyMem_MALLOC(def->m_size);
396
28
            if (!md->md_state) {
397
0
                PyErr_NoMemory();
398
0
                return -1;
399
0
            }
400
28
            memset(md->md_state, 0, def->m_size);
401
28
        }
402
28
    }
403
404
151
    if (def->m_slots == NULL) {
405
150
        return 0;
406
150
    }
407
408
2
    for (cur_slot = def->m_slots; cur_slot && cur_slot->slot; cur_slot++) {
409
1
        switch (cur_slot->slot) {
410
0
            case Py_mod_create:
411
                /* handled in PyModule_FromDefAndSpec2 */
412
0
                break;
413
1
            case Py_mod_exec:
414
1
                ret = ((int (*)(PyObject *))cur_slot->value)(module);
415
1
                if (ret != 0) {
416
0
                    if (!PyErr_Occurred()) {
417
0
                        PyErr_Format(
418
0
                            PyExc_SystemError,
419
0
                            "execution of module %s failed without setting an exception",
420
0
                            name);
421
0
                    }
422
0
                    return -1;
423
0
                }
424
1
                if (PyErr_Occurred()) {
425
0
                    PyErr_Format(
426
0
                        PyExc_SystemError,
427
0
                        "execution of module %s raised unreported exception",
428
0
                        name);
429
0
                    return -1;
430
0
                }
431
1
                break;
432
1
            default:
433
0
                PyErr_Format(
434
0
                    PyExc_SystemError,
435
0
                    "module %s initialized with unknown slot %i",
436
0
                    name, cur_slot->slot);
437
0
                return -1;
438
1
        }
439
1
    }
440
1
    return 0;
441
1
}
442
443
int
444
PyModule_AddFunctions(PyObject *m, PyMethodDef *functions)
445
202
{
446
202
    int res;
447
202
    PyObject *name = PyModule_GetNameObject(m);
448
202
    if (name == NULL) {
449
0
        return -1;
450
0
    }
451
452
202
    res = _add_methods_to_object(m, name, functions);
453
202
    Py_DECREF(name);
454
202
    return res;
455
202
}
456
457
int
458
PyModule_SetDocString(PyObject *m, const char *doc)
459
189
{
460
189
    PyObject *v;
461
189
    _Py_IDENTIFIER(__doc__);
462
463
189
    v = PyUnicode_FromString(doc);
464
189
    if (v == NULL || _PyObject_SetAttrId(m, &PyId___doc__, v) != 0) {
465
0
        Py_XDECREF(v);
466
0
        return -1;
467
0
    }
468
189
    Py_DECREF(v);
469
189
    return 0;
470
189
}
471
472
PyObject *
473
PyModule_GetDict(PyObject *m)
474
6.00k
{
475
6.00k
    PyObject *d;
476
6.00k
    if (!PyModule_Check(m)) {
477
0
        PyErr_BadInternalCall();
478
0
        return NULL;
479
0
    }
480
6.00k
    d = ((PyModuleObject *)m) -> md_dict;
481
6.00k
    assert(d != NULL);
482
6.00k
    return d;
483
6.00k
}
484
485
PyObject*
486
PyModule_GetNameObject(PyObject *m)
487
353
{
488
353
    _Py_IDENTIFIER(__name__);
489
353
    PyObject *d;
490
353
    PyObject *name;
491
353
    if (!PyModule_Check(m)) {
492
0
        PyErr_BadArgument();
493
0
        return NULL;
494
0
    }
495
353
    d = ((PyModuleObject *)m)->md_dict;
496
353
    if (d == NULL ||
497
353
        (name = _PyDict_GetItemId(d, &PyId___name__)) == NULL ||
498
353
        !PyUnicode_Check(name))
499
0
    {
500
0
        PyErr_SetString(PyExc_SystemError, "nameless module");
501
0
        return NULL;
502
0
    }
503
353
    Py_INCREF(name);
504
353
    return name;
505
353
}
506
507
const char *
508
PyModule_GetName(PyObject *m)
509
151
{
510
151
    PyObject *name = PyModule_GetNameObject(m);
511
151
    if (name == NULL)
512
0
        return NULL;
513
151
    Py_DECREF(name);   /* module dict has still a reference */
514
151
    return PyUnicode_AsUTF8(name);
515
151
}
516
517
PyObject*
518
PyModule_GetFilenameObject(PyObject *m)
519
13
{
520
13
    _Py_IDENTIFIER(__file__);
521
13
    PyObject *d;
522
13
    PyObject *fileobj;
523
13
    if (!PyModule_Check(m)) {
524
0
        PyErr_BadArgument();
525
0
        return NULL;
526
0
    }
527
13
    d = ((PyModuleObject *)m)->md_dict;
528
13
    if (d == NULL ||
529
13
        (fileobj = _PyDict_GetItemId(d, &PyId___file__)) == NULL ||
530
0
        !PyUnicode_Check(fileobj))
531
13
    {
532
13
        PyErr_SetString(PyExc_SystemError, "module filename missing");
533
13
        return NULL;
534
13
    }
535
0
    Py_INCREF(fileobj);
536
0
    return fileobj;
537
13
}
538
539
const char *
540
PyModule_GetFilename(PyObject *m)
541
0
{
542
0
    PyObject *fileobj;
543
0
    const char *utf8;
544
0
    fileobj = PyModule_GetFilenameObject(m);
545
0
    if (fileobj == NULL)
546
0
        return NULL;
547
0
    utf8 = PyUnicode_AsUTF8(fileobj);
548
0
    Py_DECREF(fileobj);   /* module dict has still a reference */
549
0
    return utf8;
550
0
}
551
552
PyModuleDef*
553
PyModule_GetDef(PyObject* m)
554
464
{
555
464
    if (!PyModule_Check(m)) {
556
0
        PyErr_BadArgument();
557
0
        return NULL;
558
0
    }
559
464
    return ((PyModuleObject *)m)->md_def;
560
464
}
561
562
void*
563
PyModule_GetState(PyObject* m)
564
207
{
565
207
    if (!PyModule_Check(m)) {
566
0
        PyErr_BadArgument();
567
0
        return NULL;
568
0
    }
569
207
    return ((PyModuleObject *)m)->md_state;
570
207
}
571
572
void
573
_PyModule_Clear(PyObject *m)
574
0
{
575
0
    PyObject *d = ((PyModuleObject *)m)->md_dict;
576
0
    if (d != NULL)
577
0
        _PyModule_ClearDict(d);
578
0
}
579
580
void
581
_PyModule_ClearDict(PyObject *d)
582
0
{
583
    /* To make the execution order of destructors for global
584
       objects a bit more predictable, we first zap all objects
585
       whose name starts with a single underscore, before we clear
586
       the entire dictionary.  We zap them by replacing them with
587
       None, rather than deleting them from the dictionary, to
588
       avoid rehashing the dictionary (to some extent). */
589
590
0
    Py_ssize_t pos;
591
0
    PyObject *key, *value;
592
593
0
    int verbose = _PyInterpreterState_GET_UNSAFE()->config.verbose;
594
595
    /* First, clear only names starting with a single underscore */
596
0
    pos = 0;
597
0
    while (PyDict_Next(d, &pos, &key, &value)) {
598
0
        if (value != Py_None && PyUnicode_Check(key)) {
599
0
            if (PyUnicode_READ_CHAR(key, 0) == '_' &&
600
0
                PyUnicode_READ_CHAR(key, 1) != '_') {
601
0
                if (verbose > 1) {
602
0
                    const char *s = PyUnicode_AsUTF8(key);
603
0
                    if (s != NULL)
604
0
                        PySys_WriteStderr("#   clear[1] %s\n", s);
605
0
                    else
606
0
                        PyErr_Clear();
607
0
                }
608
0
                if (PyDict_SetItem(d, key, Py_None) != 0) {
609
0
                    PyErr_WriteUnraisable(NULL);
610
0
                }
611
0
            }
612
0
        }
613
0
    }
614
615
    /* Next, clear all names except for __builtins__ */
616
0
    pos = 0;
617
0
    while (PyDict_Next(d, &pos, &key, &value)) {
618
0
        if (value != Py_None && PyUnicode_Check(key)) {
619
0
            if (PyUnicode_READ_CHAR(key, 0) != '_' ||
620
0
                !_PyUnicode_EqualToASCIIString(key, "__builtins__"))
621
0
            {
622
0
                if (verbose > 1) {
623
0
                    const char *s = PyUnicode_AsUTF8(key);
624
0
                    if (s != NULL)
625
0
                        PySys_WriteStderr("#   clear[2] %s\n", s);
626
0
                    else
627
0
                        PyErr_Clear();
628
0
                }
629
0
                if (PyDict_SetItem(d, key, Py_None) != 0) {
630
0
                    PyErr_WriteUnraisable(NULL);
631
0
                }
632
0
            }
633
0
        }
634
0
    }
635
636
    /* Note: we leave __builtins__ in place, so that destructors
637
       of non-global objects defined in this module can still use
638
       builtins, in particularly 'None'. */
639
640
0
}
641
642
/*[clinic input]
643
class module "PyModuleObject *" "&PyModule_Type"
644
[clinic start generated code]*/
645
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=3e35d4f708ecb6af]*/
646
647
#include "clinic/moduleobject.c.h"
648
649
/* Methods */
650
651
/*[clinic input]
652
module.__init__
653
    name: unicode
654
    doc: object = None
655
656
Create a module object.
657
658
The name must be a string; the optional doc argument can have any type.
659
[clinic start generated code]*/
660
661
static int
662
module___init___impl(PyModuleObject *self, PyObject *name, PyObject *doc)
663
/*[clinic end generated code: output=e7e721c26ce7aad7 input=57f9e177401e5e1e]*/
664
246
{
665
246
    PyObject *dict = self->md_dict;
666
246
    if (dict == NULL) {
667
246
        dict = PyDict_New();
668
246
        if (dict == NULL)
669
0
            return -1;
670
246
        self->md_dict = dict;
671
246
    }
672
246
    if (module_init_dict(self, dict, name, doc) < 0)
673
0
        return -1;
674
246
    return 0;
675
246
}
676
677
static void
678
module_dealloc(PyModuleObject *m)
679
0
{
680
0
    int verbose = _PyInterpreterState_GET_UNSAFE()->config.verbose;
681
682
0
    PyObject_GC_UnTrack(m);
683
0
    if (verbose && m->md_name) {
684
0
        PySys_FormatStderr("# destroy %S\n", m->md_name);
685
0
    }
686
0
    if (m->md_weaklist != NULL)
687
0
        PyObject_ClearWeakRefs((PyObject *) m);
688
0
    if (m->md_def && m->md_def->m_free)
689
0
        m->md_def->m_free(m);
690
0
    Py_XDECREF(m->md_dict);
691
0
    Py_XDECREF(m->md_name);
692
0
    if (m->md_state != NULL)
693
0
        PyMem_FREE(m->md_state);
694
0
    Py_TYPE(m)->tp_free((PyObject *)m);
695
0
}
696
697
static PyObject *
698
module_repr(PyModuleObject *m)
699
0
{
700
0
    PyInterpreterState *interp = _PyInterpreterState_Get();
701
702
0
    return PyObject_CallMethod(interp->importlib, "_module_repr", "O", m);
703
0
}
704
705
/* Check if the "_initializing" attribute of the module spec is set to true.
706
   Clear the exception and return 0 if spec is NULL.
707
 */
708
int
709
_PyModuleSpec_IsInitializing(PyObject *spec)
710
2.80k
{
711
2.80k
    if (spec != NULL) {
712
2.80k
        _Py_IDENTIFIER(_initializing);
713
2.80k
        PyObject *value = _PyObject_GetAttrId(spec, &PyId__initializing);
714
2.80k
        if (value != NULL) {
715
1.40k
            int initializing = PyObject_IsTrue(value);
716
1.40k
            Py_DECREF(value);
717
1.40k
            if (initializing >= 0) {
718
1.40k
                return initializing;
719
1.40k
            }
720
1.40k
        }
721
2.80k
    }
722
1.39k
    PyErr_Clear();
723
1.39k
    return 0;
724
2.80k
}
725
726
static PyObject*
727
module_getattro(PyModuleObject *m, PyObject *name)
728
41.3k
{
729
41.3k
    PyObject *attr, *mod_name, *getattr;
730
41.3k
    attr = PyObject_GenericGetAttr((PyObject *)m, name);
731
41.3k
    if (attr || !PyErr_ExceptionMatches(PyExc_AttributeError)) {
732
39.7k
        return attr;
733
39.7k
    }
734
1.60k
    PyErr_Clear();
735
1.60k
    if (m->md_dict) {
736
1.60k
        _Py_IDENTIFIER(__getattr__);
737
1.60k
        getattr = _PyDict_GetItemId(m->md_dict, &PyId___getattr__);
738
1.60k
        if (getattr) {
739
0
            PyObject* stack[1] = {name};
740
0
            return _PyObject_FastCall(getattr, stack, 1);
741
0
        }
742
1.60k
        _Py_IDENTIFIER(__name__);
743
1.60k
        mod_name = _PyDict_GetItemId(m->md_dict, &PyId___name__);
744
1.60k
        if (mod_name && PyUnicode_Check(mod_name)) {
745
1.60k
            _Py_IDENTIFIER(__spec__);
746
1.60k
            Py_INCREF(mod_name);
747
1.60k
            PyObject *spec = _PyDict_GetItemId(m->md_dict, &PyId___spec__);
748
1.60k
            Py_XINCREF(spec);
749
1.60k
            if (_PyModuleSpec_IsInitializing(spec)) {
750
13
                PyErr_Format(PyExc_AttributeError,
751
13
                             "partially initialized "
752
13
                             "module '%U' has no attribute '%U' "
753
13
                             "(most likely due to a circular import)",
754
13
                             mod_name, name);
755
13
            }
756
1.59k
            else {
757
1.59k
                PyErr_Format(PyExc_AttributeError,
758
1.59k
                             "module '%U' has no attribute '%U'",
759
1.59k
                             mod_name, name);
760
1.59k
            }
761
1.60k
            Py_XDECREF(spec);
762
1.60k
            Py_DECREF(mod_name);
763
1.60k
            return NULL;
764
1.60k
        }
765
1.60k
    }
766
0
    PyErr_Format(PyExc_AttributeError,
767
0
                "module has no attribute '%U'", name);
768
0
    return NULL;
769
1.60k
}
770
771
static int
772
module_traverse(PyModuleObject *m, visitproc visit, void *arg)
773
930
{
774
930
    if (m->md_def && m->md_def->m_traverse) {
775
28
        int res = m->md_def->m_traverse((PyObject*)m, visit, arg);
776
28
        if (res)
777
0
            return res;
778
28
    }
779
930
    Py_VISIT(m->md_dict);
780
930
    return 0;
781
930
}
782
783
static int
784
module_clear(PyModuleObject *m)
785
0
{
786
0
    if (m->md_def && m->md_def->m_clear) {
787
0
        int res = m->md_def->m_clear((PyObject*)m);
788
0
        if (res)
789
0
            return res;
790
0
    }
791
0
    Py_CLEAR(m->md_dict);
792
0
    return 0;
793
0
}
794
795
static PyObject *
796
module_dir(PyObject *self, PyObject *args)
797
13
{
798
13
    _Py_IDENTIFIER(__dict__);
799
13
    _Py_IDENTIFIER(__dir__);
800
13
    PyObject *result = NULL;
801
13
    PyObject *dict = _PyObject_GetAttrId(self, &PyId___dict__);
802
803
13
    if (dict != NULL) {
804
13
        if (PyDict_Check(dict)) {
805
13
            PyObject *dirfunc = _PyDict_GetItemIdWithError(dict, &PyId___dir__);
806
13
            if (dirfunc) {
807
0
                result = _PyObject_CallNoArg(dirfunc);
808
0
            }
809
13
            else if (!PyErr_Occurred()) {
810
13
                result = PyDict_Keys(dict);
811
13
            }
812
13
        }
813
0
        else {
814
0
            const char *name = PyModule_GetName(self);
815
0
            if (name)
816
0
                PyErr_Format(PyExc_TypeError,
817
0
                             "%.200s.__dict__ is not a dictionary",
818
0
                             name);
819
0
        }
820
13
    }
821
822
13
    Py_XDECREF(dict);
823
13
    return result;
824
13
}
825
826
static PyMethodDef module_methods[] = {
827
    {"__dir__", module_dir, METH_NOARGS,
828
     PyDoc_STR("__dir__() -> list\nspecialized dir() implementation")},
829
    {0}
830
};
831
832
PyTypeObject PyModule_Type = {
833
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
834
    "module",                                   /* tp_name */
835
    sizeof(PyModuleObject),                     /* tp_basicsize */
836
    0,                                          /* tp_itemsize */
837
    (destructor)module_dealloc,                 /* tp_dealloc */
838
    0,                                          /* tp_vectorcall_offset */
839
    0,                                          /* tp_getattr */
840
    0,                                          /* tp_setattr */
841
    0,                                          /* tp_as_async */
842
    (reprfunc)module_repr,                      /* tp_repr */
843
    0,                                          /* tp_as_number */
844
    0,                                          /* tp_as_sequence */
845
    0,                                          /* tp_as_mapping */
846
    0,                                          /* tp_hash */
847
    0,                                          /* tp_call */
848
    0,                                          /* tp_str */
849
    (getattrofunc)module_getattro,              /* tp_getattro */
850
    PyObject_GenericSetAttr,                    /* tp_setattro */
851
    0,                                          /* tp_as_buffer */
852
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
853
        Py_TPFLAGS_BASETYPE,                    /* tp_flags */
854
    module___init____doc__,                     /* tp_doc */
855
    (traverseproc)module_traverse,              /* tp_traverse */
856
    (inquiry)module_clear,                      /* tp_clear */
857
    0,                                          /* tp_richcompare */
858
    offsetof(PyModuleObject, md_weaklist),      /* tp_weaklistoffset */
859
    0,                                          /* tp_iter */
860
    0,                                          /* tp_iternext */
861
    module_methods,                             /* tp_methods */
862
    module_members,                             /* tp_members */
863
    0,                                          /* tp_getset */
864
    0,                                          /* tp_base */
865
    0,                                          /* tp_dict */
866
    0,                                          /* tp_descr_get */
867
    0,                                          /* tp_descr_set */
868
    offsetof(PyModuleObject, md_dict),          /* tp_dictoffset */
869
    module___init__,                            /* tp_init */
870
    PyType_GenericAlloc,                        /* tp_alloc */
871
    PyType_GenericNew,                          /* tp_new */
872
    PyObject_GC_Del,                            /* tp_free */
873
};