this repo has no description
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com)
2#include "cpython-func.h"
3
4#include "api-handle.h"
5#include "dict-builtins.h"
6#include "int-builtins.h"
7#include "module-builtins.h"
8#include "object-builtins.h"
9#include "runtime.h"
10#include "under-imp-module.h"
11
12namespace py {
13
14PY_EXPORT PyObject* PyImport_GetModule(PyObject* name) {
15 DCHECK(name != nullptr, "name is expected to be non null");
16 Thread* thread = Thread::current();
17 HandleScope scope(thread);
18 Runtime* runtime = thread->runtime();
19 Object modules(&scope, runtime->modules());
20 Object name_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(name)));
21 if (modules.isDict()) {
22 Dict modules_dict(&scope, *modules);
23 Object hash_obj(&scope, Interpreter::hash(thread, name_obj));
24 if (hash_obj.isErrorException()) return nullptr;
25 word hash = SmallInt::cast(*hash_obj).value();
26 Object result(&scope, dictAt(thread, modules_dict, name_obj, hash));
27 if (result.isError()) {
28 return nullptr;
29 }
30 return ApiHandle::newReference(runtime, *result);
31 }
32 Object result(&scope, objectGetItem(thread, modules, name_obj));
33 if (result.isErrorException()) {
34 if (thread->pendingExceptionMatches(LayoutId::kKeyError)) {
35 thread->clearPendingException();
36 }
37 return nullptr;
38 }
39 return ApiHandle::newReference(runtime, *result);
40}
41
42PY_EXPORT PyObject* PyImport_GetModuleDict(void) {
43 Runtime* runtime = Thread::current()->runtime();
44 return ApiHandle::borrowedReference(runtime, runtime->modules());
45}
46
47PY_EXPORT PyObject* PyImport_ImportModuleLevelObject(PyObject* name,
48 PyObject* globals,
49 PyObject* locals,
50 PyObject* fromlist,
51 int level) {
52 Thread* thread = Thread::current();
53 if (name == nullptr) {
54 thread->raiseWithFmt(LayoutId::kValueError, "Empty module name");
55 return nullptr;
56 }
57 if (level < 0) {
58 thread->raiseWithFmt(LayoutId::kValueError, "level must be >= 0");
59 return nullptr;
60 }
61 if (globals == nullptr) {
62 thread->raiseWithFmt(LayoutId::kKeyError, "'__name__' not in globals");
63 return nullptr;
64 }
65 HandleScope scope(thread);
66 Object globals_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(globals)));
67 Runtime* runtime = thread->runtime();
68 if (!runtime->isInstanceOfDict(*globals_obj)) {
69 thread->raiseWithFmt(LayoutId::kTypeError, "globals must be a dict");
70 return nullptr;
71 }
72
73 Object level_obj(&scope, SmallInt::fromWord(level));
74 Object fromlist_obj(&scope,
75 fromlist == nullptr
76 ? runtime->emptyTuple()
77 : ApiHandle::asObject(ApiHandle::fromPyObject(fromlist)));
78
79 Object name_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(name)));
80 Object locals_obj(&scope, locals == nullptr
81 ? NoneType::object()
82 : ApiHandle::asObject(ApiHandle::fromPyObject(locals)));
83 Object result(&scope, thread->invokeFunction5(
84 ID(_frozen_importlib), ID(__import__), name_obj,
85 globals_obj, locals_obj, fromlist_obj, level_obj));
86 if (result.isError()) return nullptr;
87 return ApiHandle::newReference(runtime, *result);
88}
89
90PY_EXPORT PyObject* PyImport_AddModule(const char* name) {
91 PyObject* pyname = PyUnicode_FromString(name);
92 if (!pyname) return nullptr;
93 PyObject* module = PyImport_AddModuleObject(pyname);
94 Py_DECREF(pyname);
95 return module;
96}
97
98PY_EXPORT PyObject* PyImport_AddModuleObject(PyObject* name) {
99 Thread* thread = Thread::current();
100 Runtime* runtime = thread->runtime();
101 HandleScope scope(thread);
102
103 Dict modules_dict(&scope, runtime->modules());
104 Object name_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(name)));
105 Object hash_obj(&scope, Interpreter::hash(thread, name_obj));
106 if (hash_obj.isErrorException()) return nullptr;
107 word hash = SmallInt::cast(*hash_obj).value();
108 Object module(&scope, dictAt(thread, modules_dict, name_obj, hash));
109 if (!module.isErrorNotFound()) {
110 return ApiHandle::borrowedReference(runtime, *module);
111 }
112
113 Module new_module(&scope, runtime->newModule(name_obj));
114 Object modules(&scope, runtime->modules());
115 if (objectSetItem(thread, modules, name_obj, new_module).isErrorException()) {
116 return nullptr;
117 }
118 return ApiHandle::borrowedReference(runtime, *new_module);
119}
120
121PY_EXPORT void PyImport_Cleanup() { UNIMPLEMENTED("PyImport_Cleanup"); }
122
123PyObject* fixUpModule(PyObject* module_dict, PyObject* name) {
124 PyObject* importlib_external =
125 PyImport_ImportModule("_frozen_importlib_external");
126 if (importlib_external == nullptr) {
127 return nullptr;
128 }
129 PyObject* fix_up_module = PyUnicode_FromString("_fix_up_module");
130 if (fix_up_module == nullptr) {
131 Py_DECREF(importlib_external);
132 return nullptr;
133 }
134 PyObject* result = PyObject_CallMethodObjArgs(
135 importlib_external, fix_up_module, module_dict, name, name, nullptr);
136 PyErr_Print();
137 Py_DECREF(fix_up_module);
138 Py_DECREF(importlib_external);
139 return result;
140}
141
142void removeModule(const char* name) {
143 PyObject* modules_dict = PyImport_GetModuleDict();
144 Py_INCREF(modules_dict);
145 PyMapping_DelItemString(modules_dict, name);
146 Py_DECREF(modules_dict);
147}
148
149PY_EXPORT PyObject* PyImport_ExecCodeModule(const char* name, PyObject* code) {
150 PyObject* name_str = PyUnicode_FromString(name);
151 if (name_str == nullptr) {
152 return nullptr;
153 }
154 PyObject* module = PyImport_AddModuleObject(name_str);
155 if (module == nullptr) {
156 Py_DECREF(name_str);
157 return nullptr;
158 }
159 // PyImport_ExecCodeModule is supposed to return a new reference to the
160 // module.
161 Py_INCREF(module);
162 PyObject* module_dict = PyModule_GetDict(module);
163 if (module_dict == nullptr) {
164 Py_DECREF(name_str);
165 Py_DECREF(module);
166 return nullptr;
167 }
168
169 PyObject* result = fixUpModule(module_dict, name_str);
170 Py_DECREF(name_str);
171 if (result == nullptr) {
172 Py_DECREF(module);
173 PyErr_Clear();
174 removeModule(name);
175 return nullptr;
176 }
177
178 result = PyEval_EvalCode(code, /*globals=*/module_dict,
179 /*locals=*/module_dict);
180 if (result == nullptr) {
181 Py_DECREF(module);
182 PyErr_Clear();
183 removeModule(name);
184 return nullptr;
185 }
186 Py_DECREF(result);
187 return module;
188}
189
190PY_EXPORT PyObject* PyImport_ExecCodeModuleEx(const char* /* e */,
191 PyObject* /* o */,
192 const char* /* e */) {
193 UNIMPLEMENTED("PyImport_ExecCodeModuleEx");
194}
195
196PY_EXPORT PyObject* PyImport_ExecCodeModuleObject(PyObject* /* e */,
197 PyObject* /* o */,
198 PyObject* /* e */,
199 PyObject* /* e */) {
200 UNIMPLEMENTED("PyImport_ExecCodeModuleObject");
201}
202
203PY_EXPORT PyObject* PyImport_ExecCodeModuleWithPathnames(const char* /* e */,
204 PyObject* /* o */,
205 const char* /* e */,
206 const char* /* e */) {
207 UNIMPLEMENTED("PyImport_ExecCodeModuleWithPathnames");
208}
209
210PY_EXPORT long PyImport_GetMagicNumber() {
211 PyObject* importlib = PyImport_ImportModule("_frozen_importlib_external");
212 if (importlib == nullptr) return -1;
213 PyObject* pyc_magic = PyObject_GetAttrString(importlib, "_RAW_MAGIC_NUMBER");
214 Py_DECREF(importlib);
215 if (pyc_magic == nullptr) return -1;
216 long res = PyLong_AsLong(pyc_magic);
217 Py_DECREF(pyc_magic);
218 return res;
219}
220
221PY_EXPORT const char* PyImport_GetMagicTag() {
222 UNIMPLEMENTED("PyImport_GetMagicTag");
223}
224
225PY_EXPORT PyObject* PyImport_Import(PyObject* module_name) {
226 Thread* thread = Thread::current();
227 Runtime* runtime = thread->runtime();
228 HandleScope scope(thread);
229
230 Object name_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(module_name)));
231 Object globals_obj(&scope, NoneType::object());
232 Frame* current_frame = thread->currentFrame();
233 if (current_frame->isSentinel()) {
234 globals_obj = runtime->newDict();
235 } else {
236 Module module(&scope, current_frame->function().moduleObject());
237 globals_obj = module.moduleProxy();
238 }
239 Object fromlist_obj(&scope, runtime->emptyTuple());
240 Object level_obj(&scope, SmallInt::fromWord(0));
241 Object result(&scope, thread->invokeFunction5(
242 ID(builtins), ID(__import__), name_obj, globals_obj,
243 globals_obj, fromlist_obj, level_obj));
244 if (result.isError()) return nullptr;
245 // PyImport_GetModule, inlined
246 Object modules(&scope, thread->runtime()->modules());
247 if (modules.isDict()) {
248 Dict modules_dict(&scope, *modules);
249 Object hash_obj(&scope, Interpreter::hash(thread, name_obj));
250 if (hash_obj.isErrorException()) return nullptr;
251 word hash = SmallInt::cast(*hash_obj).value();
252 result = dictAt(thread, modules_dict, name_obj, hash);
253 // dictAt can return Error::notFound, and we should not raise an exception
254 // in that case
255 if (result.isError()) return nullptr;
256 return ApiHandle::newReference(runtime, *result);
257 }
258 result = objectGetItem(thread, modules, name_obj);
259 // Don't filter out KeyError; PyImport_GetModule clears them, but
260 // PyImport_Import re-raises
261 if (result.isErrorException()) return nullptr;
262 return ApiHandle::newReference(runtime, *result);
263}
264
265PY_EXPORT int PyImport_ImportFrozenModule(const char* name) {
266 // CPython's and Pyro's frozen modules do not match. Instead, just treat
267 // this C-API as PyImport_ImportModule
268 PyObject* result = PyImport_ImportModule(name);
269 Py_XDECREF(result);
270 return result == nullptr ? -1 : 0;
271}
272
273PY_EXPORT int PyImport_ImportFrozenModuleObject(PyObject* name) {
274 // CPython's and Pyro's frozen modules do not match. Instead, just treat
275 // this C-API as PyImport_ImportModule
276 PyObject* result = PyImport_Import(name);
277 Py_XDECREF(result);
278 return result == nullptr ? -1 : 0;
279}
280
281PY_EXPORT PyObject* PyImport_ImportModule(const char* name) {
282 PyObject* name_obj = PyUnicode_FromString(name);
283 if (name_obj == nullptr) return nullptr;
284 PyObject* result = PyImport_Import(name_obj);
285 Py_DECREF(name_obj);
286 return result;
287}
288
289PY_EXPORT PyObject* PyImport_ImportModuleLevel(const char* name,
290 PyObject* globals,
291 PyObject* locals,
292 PyObject* fromlist, int level) {
293 PyObject* name_obj = PyUnicode_FromString(name);
294 if (name_obj == nullptr) return nullptr;
295 PyObject* result = PyImport_ImportModuleLevelObject(name_obj, globals, locals,
296 fromlist, level);
297 Py_DECREF(name_obj);
298 return result;
299}
300
301PY_EXPORT PyObject* PyImport_ImportModuleNoBlock(const char* name) {
302 // Deprecated in favor of PyImport_ImportModule. From the docs:
303 // "Since Python 3.3, this function's special behaviour isn't needed anymore"
304 return PyImport_ImportModule(name);
305}
306
307PY_EXPORT PyObject* PyImport_ReloadModule(PyObject* /* m */) {
308 UNIMPLEMENTED("PyImport_ReloadModule");
309}
310
311PY_EXPORT void _PyImport_AcquireLock() { importAcquireLock(Thread::current()); }
312
313PY_EXPORT void _PyImport_ReInitLock() {
314 // TODO(T87097565): Implement instead of making it a noop
315}
316
317PY_EXPORT int _PyImport_ReleaseLock() {
318 return importReleaseLock(Thread::current()) ? 1 : -1;
319}
320
321} // namespace py