Skip to content

Commit 0fd8ddd

Browse files
committed
feat(api/c): PyImport_GetModule
1 parent c26d768 commit 0fd8ddd

File tree

1 file changed

+68
-1
lines changed

1 file changed

+68
-1
lines changed

Python/pyimport/utils.nim

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,19 @@ import ../[
33
sysmodule_instance,
44
]
55
import ../../Objects/[pyobject,
6+
exceptions,
7+
noneobject,
68
stringobject,
79
dictobject,
810
moduleobject,
11+
boolobjectImpl,
912
]
13+
import ../../Objects/pyobject_apis/attrs
14+
import ../../Include/internal/pycore_global_strings
15+
const HasImportLib = defined(npythonHasImportLib) #TODO:imp
16+
when HasImportLib:
17+
import ../../Objects/abstract/call
18+
import ../coreconfig
1019

1120
template import_add_moduleImpl(alreadyInAsgn): untyped{.dirty.} =
1221
var modu = sys.modules.getOptionalItem(name)
@@ -37,4 +46,62 @@ proc PyImport_AddModuleRef*(name: string): PyObject =
3746
let name_obj = newPyStr name
3847
PyImport_AddModuleRef name_obj
3948

40-
proc import_get_module*(name: PyStrObject): PyObject = sys.modules.getOptionalItem name
49+
using name: PyStrObject
50+
proc import_get_module(name): PyObject = sys.modules.getOptionalItem name
51+
52+
proc PyModuleSpec_IsInitializing*(spec: PyObject; res: var bool): PyBaseErrorObject =
53+
## Check if the "_initializing" attribute of the module spec is set to true.
54+
res = false
55+
if spec.isNil: return
56+
var value: PyObject
57+
var rc = PyObject_GetOptionalAttr(spec, pyId"_initializing", value)
58+
if rc == Error:
59+
return PyBaseErrorObject value
60+
PyObject_IsTrue(value, res)
61+
62+
proc import_ensure_initialized(modu: PyObject, name): PyBaseErrorObject =
63+
#[ Optimization: only call _bootstrap._lock_unlock_module() if
64+
__spec__._initializing is true.
65+
NOTE: because of this, initializing must be set *before*
66+
stuffing the new module in sys.modules.
67+
]#
68+
#[ When -X importtime=2, print an import time entry even if an
69+
imported module has already been loaded.
70+
]#
71+
72+
proc done =
73+
when HasImportLib:
74+
if Py_GetConfig().import_time == 2:
75+
IMPORT_TIME_HEADER(interp)
76+
let import_level = FIND_AND_LOAD(interp).import_level
77+
let s = name.asUTF8.align(import_level * 2)
78+
errEchoCompat("import time: cached | cached | " & s)
79+
template goto_done =
80+
done()
81+
return
82+
var spec: PyObject
83+
var rc: bool
84+
let res = PyObject_GetOptionalAttr(modu, pyDUId(spec), spec)
85+
case res
86+
of Get:
87+
retIfExc PyModuleSpec_IsInitializing(spec, rc)
88+
if not rc: goto_done
89+
of Missing:
90+
goto_done
91+
else:
92+
return PyBaseErrorObject spec
93+
94+
# Wait until module is done importing.
95+
when HasImportLib:
96+
retIfExc callMethod(
97+
IMPORTLIB(interp), pyId"_lock_unlock_module", name)
98+
99+
goto_done
100+
101+
102+
proc PyImport_GetModule*(name; res: var PyObject): PyBaseErrorObject =
103+
res = import_get_module(name)
104+
if res.isNil: return
105+
retIfExc res
106+
if res.isPyNone: return
107+
retIfExc import_ensure_initialized(res, name)

0 commit comments

Comments
 (0)