this repo has no description
at trunk 321 lines 12 kB view raw
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