Nuitka
The Python compiler
Loading...
Searching...
No Matches
HelpersImport.c
1// Copyright 2025, Kay Hayen, mailto:kay.hayen@gmail.com find license text at end of file
2
11// This file is included from another C file, help IDEs to still parse it on
12// its own.
13#ifdef __IDE_ONLY__
14#include "nuitka/prelude.h"
15#endif
16
17NUITKA_DEFINE_BUILTIN(__import__);
18
19PyObject *IMPORT_MODULE_KW(PyThreadState *tstate, PyObject *module_name, PyObject *globals, PyObject *locals,
20 PyObject *import_items, PyObject *level) {
21 CHECK_OBJECT_X(module_name);
22 CHECK_OBJECT_X(globals);
23 CHECK_OBJECT_X(locals);
24 CHECK_OBJECT_X(import_items);
25 CHECK_OBJECT_X(level);
26
27 PyObject *kw_pairs[5 * 2] = {const_str_plain_name, module_name, const_str_plain_globals, globals,
28 const_str_plain_locals, locals, const_str_plain_fromlist, import_items,
29 const_str_plain_level, level};
30 PyObject *kw_args = MAKE_DICT_X(kw_pairs, 5);
31
32 NUITKA_ASSIGN_BUILTIN(__import__);
33
34 PyObject *import_result = CALL_FUNCTION_WITH_KW_ARGS(tstate, NUITKA_ACCESS_BUILTIN(__import__), kw_args);
35
36 Py_DECREF(kw_args);
37
38 return import_result;
39}
40
41PyObject *IMPORT_MODULE1(PyThreadState *tstate, PyObject *module_name) {
42 CHECK_OBJECT(module_name);
43
44 NUITKA_ASSIGN_BUILTIN(__import__);
45
46 PyObject *import_result = CALL_FUNCTION_WITH_SINGLE_ARG(tstate, NUITKA_ACCESS_BUILTIN(__import__), module_name);
47
48 return import_result;
49}
50
51PyObject *IMPORT_MODULE2(PyThreadState *tstate, PyObject *module_name, PyObject *globals) {
52 CHECK_OBJECT(module_name);
53 CHECK_OBJECT(globals);
54
55 PyObject *pos_args[] = {module_name, globals};
56
57 NUITKA_ASSIGN_BUILTIN(__import__);
58
59 PyObject *import_result = CALL_FUNCTION_WITH_ARGS2(tstate, NUITKA_ACCESS_BUILTIN(__import__), pos_args);
60
61 return import_result;
62}
63
64PyObject *IMPORT_MODULE3(PyThreadState *tstate, PyObject *module_name, PyObject *globals, PyObject *locals) {
65 CHECK_OBJECT(module_name);
66 CHECK_OBJECT(globals);
67 CHECK_OBJECT(locals);
68
69 PyObject *pos_args[] = {module_name, globals, locals};
70
71 NUITKA_ASSIGN_BUILTIN(__import__);
72
73 PyObject *import_result = CALL_FUNCTION_WITH_ARGS3(tstate, NUITKA_ACCESS_BUILTIN(__import__), pos_args);
74
75 return import_result;
76}
77
78PyObject *IMPORT_MODULE4(PyThreadState *tstate, PyObject *module_name, PyObject *globals, PyObject *locals,
79 PyObject *import_items) {
80 CHECK_OBJECT(module_name);
81 CHECK_OBJECT(globals);
82 CHECK_OBJECT(locals);
83 CHECK_OBJECT(import_items);
84
85 PyObject *pos_args[] = {module_name, globals, locals, import_items};
86
87 NUITKA_ASSIGN_BUILTIN(__import__);
88
89 PyObject *import_result = CALL_FUNCTION_WITH_ARGS4(tstate, NUITKA_ACCESS_BUILTIN(__import__), pos_args);
90
91 return import_result;
92}
93
94PyObject *IMPORT_MODULE5(PyThreadState *tstate, PyObject *module_name, PyObject *globals, PyObject *locals,
95 PyObject *import_items, PyObject *level) {
96 CHECK_OBJECT(module_name);
97 CHECK_OBJECT(globals);
98 CHECK_OBJECT(locals);
99 CHECK_OBJECT(import_items);
100 CHECK_OBJECT(level);
101
102 PyObject *pos_args[] = {module_name, globals, locals, import_items, level};
103
104 NUITKA_ASSIGN_BUILTIN(__import__);
105 PyObject *import_function = NUITKA_ACCESS_BUILTIN(__import__);
106
107// TODO: This should be reserved for the import statements, but not for
108// the import built-in, we have to make a difference there with 3.10 to
109// be compatible.
110#if PYTHON_VERSION >= 0x3a0 && 0
111 // Fast path for default "__import__" avoids function call.
112 if (import_function == tstate->interp->import_func) {
113 int level_int = _PyLong_AsInt(level);
114
115 if (level_int == -1 && HAS_ERROR_OCCURRED(tstate)) {
116 return NULL;
117 }
118
119 return PyImport_ImportModuleLevelObject(module_name, globals, locals, import_items, level_int);
120 }
121#endif
122
123 PyObject *import_result = CALL_FUNCTION_WITH_ARGS5(tstate, import_function, pos_args);
124
125 return import_result;
126}
127
128bool IMPORT_MODULE_STAR(PyThreadState *tstate, PyObject *target, bool is_module, PyObject *module) {
129 // Check parameters.
130 CHECK_OBJECT(module);
131 CHECK_OBJECT(target);
132
133 PyObject *iter;
134 bool all_case;
135
136 PyObject *all = PyObject_GetAttr(module, const_str_plain___all__);
137 if (all != NULL) {
138 iter = MAKE_ITERATOR(tstate, all);
139 Py_DECREF(all);
140
141 if (unlikely(iter == NULL)) {
142 return false;
143 }
144
145 all_case = true;
146 } else {
147 assert(HAS_ERROR_OCCURRED(tstate));
148
149 if (EXCEPTION_MATCH_BOOL_SINGLE(tstate, GET_ERROR_OCCURRED(tstate), PyExc_AttributeError)) {
150 CLEAR_ERROR_OCCURRED(tstate);
151
152 iter = MAKE_ITERATOR(tstate, PyModule_GetDict(module));
153 CHECK_OBJECT(iter);
154
155 all_case = false;
156 } else {
157 return false;
158 }
159 }
160
161 for (;;) {
162 PyObject *item = ITERATOR_NEXT_ITERATOR(iter);
163 if (item == NULL) {
164 break;
165 }
166
167#if PYTHON_VERSION < 0x300
168 if (unlikely(PyString_Check(item) == false && PyUnicode_Check(item) == false))
169#else
170 if (unlikely(PyUnicode_Check(item) == false))
171#endif
172 {
173 PyErr_Format(PyExc_TypeError, "attribute name must be string, not '%s'", Py_TYPE(item)->tp_name);
174 break;
175 }
176
177 // When we are not using the "__all__", we should skip private variables.
178 if (all_case == false) {
179 PyObject *startswith_value;
180#if PYTHON_VERSION < 0x300
181 if (PyString_Check(item)) {
182 startswith_value = STR_STARTSWITH2(tstate, item, const_str_underscore);
183 } else {
184 startswith_value = UNICODE_STARTSWITH2(tstate, item, const_str_underscore);
185 }
186#else
187 startswith_value = UNICODE_STARTSWITH2(tstate, item, const_str_underscore);
188#endif
189
190 CHECK_OBJECT(startswith_value);
191 Py_DECREF(startswith_value);
192
193 if (startswith_value == Py_True) {
194 continue;
195 }
196 }
197
198 PyObject *value = LOOKUP_ATTRIBUTE(tstate, module, item);
199
200 // Might not exist, because of e.g. wrong "__all__" value.
201 if (unlikely(value == NULL)) {
202 Py_DECREF(item);
203 break;
204 }
205
206 // TODO: Check if the reference is handled correctly
207 if (is_module) {
208 SET_ATTRIBUTE(tstate, target, item, value);
209 } else {
210 SET_SUBSCRIPT(tstate, target, item, value);
211 }
212
213 Py_DECREF(value);
214 Py_DECREF(item);
215 }
216
217 Py_DECREF(iter);
218
219 return !HAS_ERROR_OCCURRED(tstate);
220}
221
222PyObject *IMPORT_NAME_FROM_MODULE(PyThreadState *tstate, PyObject *module, PyObject *import_name) {
223 CHECK_OBJECT(module);
224 CHECK_OBJECT(import_name);
225
226 PyObject *result = PyObject_GetAttr(module, import_name);
227
228 if (unlikely(result == NULL)) {
229 if (CHECK_AND_CLEAR_ATTRIBUTE_ERROR_OCCURRED(tstate)) {
230#if PYTHON_VERSION >= 0x370
231 PyObject *filename = Nuitka_GetFilenameObject(tstate, module);
232
233 PyObject *name = LOOKUP_ATTRIBUTE(tstate, module, const_str_plain___name__);
234 if (name == NULL) {
235 name = PyUnicode_FromString("<unknown module name>");
236 }
237
238 PyErr_Format(PyExc_ImportError, "cannot import name %R from %R (%S)", import_name, name, filename);
239
240 Py_DECREF(filename);
241 Py_DECREF(name);
242
243#elif PYTHON_VERSION >= 0x300 || !defined(_NUITKA_FULL_COMPAT)
244 PyErr_Format(PyExc_ImportError, "cannot import name '%s'", Nuitka_String_AsString(import_name));
245#else
246 PyErr_Format(PyExc_ImportError, "cannot import name %s", Nuitka_String_AsString(import_name));
247#endif
248 }
249
250 return NULL;
251 }
252
253 return result;
254}
255
256#if PYTHON_VERSION >= 0x350
257
258static PyObject *resolveParentModuleName(PyThreadState *tstate, PyObject *module, PyObject *name, int level) {
259 PyObject *globals = PyModule_GetDict(module);
260
261 CHECK_OBJECT(globals);
262
263 if (unlikely(!PyDict_Check(globals))) {
264 SET_CURRENT_EXCEPTION_TYPE0_STR(tstate, PyExc_TypeError, "globals must be a dict");
265 return NULL;
266 }
267
268 PyObject *package = DICT_GET_ITEM0(tstate, globals, const_str_plain___package__);
269
270 if (unlikely(package == NULL && HAS_ERROR_OCCURRED(tstate))) {
271 return NULL;
272 }
273
274 if (package == Py_None) {
275 package = NULL;
276 }
277
278 PyObject *spec = DICT_GET_ITEM0(tstate, globals, const_str_plain___spec__);
279
280 if (unlikely(spec == NULL && HAS_ERROR_OCCURRED(tstate))) {
281 return NULL;
282 }
283
284 if (package != NULL) {
285 if (!PyUnicode_Check(package)) {
286 SET_CURRENT_EXCEPTION_TYPE0_STR(tstate, PyExc_TypeError, "package must be a string");
287 return NULL;
288 }
289
290 // Compare with spec.
291 if (spec != NULL && spec != Py_None) {
292 PyObject *parent = PyObject_GetAttr(spec, const_str_plain_parent);
293
294 if (unlikely(parent == NULL)) {
295 return NULL;
296 }
297
298 nuitka_bool nbool_equal = RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(package, parent);
299
300 Py_DECREF(parent);
301
302 if (unlikely(nbool_equal == NUITKA_BOOL_EXCEPTION)) {
303 return NULL;
304 }
305
306 if (unlikely(nbool_equal == NUITKA_BOOL_FALSE)) {
307 if (PyErr_WarnEx(PyExc_ImportWarning, "__package__ != __spec__.parent", 1) < 0) {
308 return NULL;
309 }
310 }
311 }
312
313 Py_INCREF(package);
314 } else if (spec != NULL && spec != Py_None) {
315 package = PyObject_GetAttr(spec, const_str_plain_parent);
316
317 if (unlikely(package == NULL)) {
318 return NULL;
319 }
320
321 if (unlikely(!PyUnicode_Check(package))) {
322 SET_CURRENT_EXCEPTION_TYPE0_STR(tstate, PyExc_TypeError, "__spec__.parent must be a string");
323 return NULL;
324 }
325 } else {
326 if (PyErr_WarnEx(PyExc_ImportWarning,
327 "can't resolve package from __spec__ or __package__, "
328 "falling back on __name__ and __path__",
329 1) < 0) {
330 return NULL;
331 }
332
333 package = DICT_GET_ITEM0(tstate, globals, const_str_plain___name__);
334
335 if (unlikely(package == NULL && !HAS_ERROR_OCCURRED(tstate))) {
336 SET_CURRENT_EXCEPTION_TYPE0_STR(tstate, PyExc_KeyError, "'__name__' not in globals");
337 return NULL;
338 }
339
340 if (!PyUnicode_Check(package)) {
341 SET_CURRENT_EXCEPTION_TYPE0_STR(tstate, PyExc_TypeError, "__name__ must be a string");
342 return NULL;
343 }
344
345 // Detect package from __path__ presence.
346 if (DICT_HAS_ITEM(tstate, globals, const_str_plain___path__) == 1) {
347 Py_ssize_t dot = PyUnicode_FindChar(package, '.', 0, PyUnicode_GET_LENGTH(package), -1);
348
349 if (unlikely(dot == -2)) {
350 return NULL;
351 }
352
353 if (unlikely(dot == -1)) {
354 // NULL without error means it just didn't work.
355 return NULL;
356 }
357
358 PyObject *substr = PyUnicode_Substring(package, 0, dot);
359 if (unlikely(substr == NULL)) {
360 return NULL;
361 }
362
363 package = substr;
364 } else {
365 Py_INCREF(package);
366 }
367 }
368
369 Py_ssize_t last_dot = PyUnicode_GET_LENGTH(package);
370
371 if (unlikely(last_dot == 0)) {
372 Py_DECREF(package);
373
374 // NULL without error means it just didn't work.
375 return NULL;
376 }
377
378 for (int level_up = 1; level_up < level; level_up += 1) {
379 last_dot = PyUnicode_FindChar(package, '.', 0, last_dot, -1);
380 if (last_dot == -2) {
381 Py_DECREF(package);
382 return NULL;
383 } else if (last_dot == -1) {
384 Py_DECREF(package);
385 SET_CURRENT_EXCEPTION_TYPE0_STR(tstate, PyExc_ValueError,
386 "attempted relative import beyond top-level package");
387 return NULL;
388 }
389 }
390
391 PyObject *base = PyUnicode_Substring(package, 0, last_dot);
392
393 Py_DECREF(package);
394
395 if (unlikely(base == NULL || PyUnicode_GET_LENGTH(name) == 0)) {
396 return base;
397 }
398
399 PyObject *abs_name = PyUnicode_FromFormat("%U.%U", base, name);
400 Py_DECREF(base);
401
402 return abs_name;
403}
404
405PyObject *IMPORT_NAME_OR_MODULE(PyThreadState *tstate, PyObject *module, PyObject *globals, PyObject *import_name,
406 PyObject *level) {
407 CHECK_OBJECT(module);
408 CHECK_OBJECT(import_name);
409
410 PyObject *result = PyObject_GetAttr(module, import_name);
411
412 if (unlikely(result == NULL)) {
413 if (EXCEPTION_MATCH_BOOL_SINGLE(tstate, GET_ERROR_OCCURRED(tstate), PyExc_AttributeError)) {
414 CLEAR_ERROR_OCCURRED(tstate);
415
416 long level_int = PyLong_AsLong(level);
417
418 if (unlikely(level_int == -1 && HAS_ERROR_OCCURRED(tstate))) {
419 return NULL;
420 }
421
422 if (unlikely(level_int < 0)) {
423 SET_CURRENT_EXCEPTION_TYPE0_STR(tstate, PyExc_ValueError, "level must be >= 0");
424 return NULL;
425 }
426
427 if (level_int > 0) {
428 PyObject *fromlist = MAKE_TUPLE1(tstate, import_name);
429
430 result = IMPORT_MODULE5(tstate, const_str_empty, globals, globals, fromlist, level);
431
432 Py_DECREF(fromlist);
433
434 // Look up in "sys.modules", because we will have returned the
435 // package of it from IMPORT_MODULE5.
436 PyObject *name = PyUnicode_FromFormat("%s.%S", PyModule_GetName(result), import_name);
437
438 if (result != NULL) {
439 Py_DECREF(result);
440
441 result = Nuitka_GetModule(tstate, name);
442 }
443
444 Py_DECREF(name);
445 } else {
446 PyObject *name = resolveParentModuleName(tstate, module, import_name, level_int);
447
448 if (name == NULL) {
449 if (unlikely(HAS_ERROR_OCCURRED(tstate))) {
450 return NULL;
451 }
452 } else {
453 result = IMPORT_MODULE5(tstate, name, globals, globals, const_tuple_empty, level);
454
455 if (result != NULL) {
456 Py_DECREF(result);
457
458 // Look up in "sys.modules", because we will have returned the
459 result = Nuitka_GetModule(tstate, name);
460 Py_DECREF(name);
461 }
462 }
463 }
464
465 if (result == NULL) {
466 CLEAR_ERROR_OCCURRED(tstate);
467
468 result = IMPORT_NAME_FROM_MODULE(tstate, module, import_name);
469 }
470 }
471 }
472
473 CHECK_OBJECT(import_name);
474
475 return result;
476}
477#endif
478
479PyObject *IMPORT_MODULE_FIXED(PyThreadState *tstate, PyObject *module_name, PyObject *value_name) {
480 PyObject *import_result = IMPORT_MODULE1(tstate, module_name);
481
482 if (unlikely(import_result == NULL)) {
483 return import_result;
484 }
485
486 PyObject *result = Nuitka_GetModule(tstate, value_name);
487
488 Py_DECREF(import_result);
489
490 return result;
491}
492
493// Part of "Nuitka", an optimizing Python compiler that is compatible and
494// integrates with CPython, but also works on its own.
495//
496// Licensed under the Apache License, Version 2.0 (the "License");
497// you may not use this file except in compliance with the License.
498// You may obtain a copy of the License at
499//
500// http://www.apache.org/licenses/LICENSE-2.0
501//
502// Unless required by applicable law or agreed to in writing, software
503// distributed under the License is distributed on an "AS IS" BASIS,
504// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
505// See the License for the specific language governing permissions and
506// limitations under the License.