this repo has no description
at trunk 724 lines 26 kB view raw
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) 2#include <unistd.h> 3 4#include <cerrno> 5#include <cstdarg> 6 7#include "cpython-data.h" 8#include "cpython-func.h" 9 10#include "api-handle.h" 11#include "dict-builtins.h" 12#include "exception-builtins.h" 13#include "fileutils.h" 14#include "runtime.h" 15#include "sys-module.h" 16#include "thread.h" 17#include "traceback-builtins.h" 18#include "type-builtins.h" 19 20namespace py { 21 22PY_EXPORT void PyErr_SetString(PyObject* exc, const char* msg) { 23 PyObject* value = PyUnicode_FromString(msg); 24 PyErr_SetObject(exc, value); 25 Py_XDECREF(value); 26} 27 28PY_EXPORT PyObject* PyErr_Occurred() { 29 Thread* thread = Thread::current(); 30 if (!thread->hasPendingException()) { 31 return nullptr; 32 } 33 return ApiHandle::borrowedReference(thread->runtime(), 34 thread->pendingExceptionType()); 35} 36 37PY_EXPORT PyObject* PyErr_Format(PyObject* exception, const char* format, ...) { 38 va_list vargs; 39 va_start(vargs, format); 40 PyErr_FormatV(exception, format, vargs); 41 va_end(vargs); 42 return nullptr; 43} 44 45PY_EXPORT void PyErr_Clear() { Thread::current()->clearPendingException(); } 46 47PY_EXPORT int PyErr_BadArgument() { 48 Thread* thread = Thread::current(); 49 thread->raiseBadArgument(); 50 return 0; 51} 52 53PY_EXPORT PyObject* PyErr_NoMemory() { 54 Thread* thread = Thread::current(); 55 thread->raiseMemoryError(); 56 return nullptr; 57} 58 59PY_EXPORT PyObject* _PyErr_FormatFromCause(PyObject* exception, 60 const char* format, ...) { 61 CHECK(PyErr_Occurred(), 62 "_PyErr_FormatFromCause must be called with an exception set"); 63 PyObject* exc = nullptr; 64 PyObject* val = nullptr; 65 PyObject* tb = nullptr; 66 PyErr_Fetch(&exc, &val, &tb); 67 PyErr_NormalizeException(&exc, &val, &tb); 68 if (tb != nullptr) { 69 PyException_SetTraceback(val, tb); 70 Py_DECREF(tb); 71 } 72 Py_DECREF(exc); 73 DCHECK(!PyErr_Occurred(), "error must not have occurred"); 74 75 va_list vargs; 76 va_start(vargs, format); 77 PyErr_FormatV(exception, format, vargs); 78 va_end(vargs); 79 80 PyObject* val2 = nullptr; 81 PyErr_Fetch(&exc, &val2, &tb); 82 PyErr_NormalizeException(&exc, &val2, &tb); 83 Py_INCREF(val); 84 PyException_SetCause(val2, val); 85 PyException_SetContext(val2, val); 86 PyErr_Restore(exc, val2, tb); 87 88 return nullptr; 89} 90 91// Remove the preprocessor macro for PyErr_BadInternalCall() so that we can 92// export the entry point for existing object code: 93#pragma push_macro("PyErr_BadInternalCall") 94#undef PyErr_BadInternalCall 95PY_EXPORT void PyErr_BadInternalCall() { 96 Thread* thread = Thread::current(); 97 thread->raiseBadInternalCall(); 98} 99#pragma pop_macro("PyErr_BadInternalCall") 100 101PY_EXPORT int PyErr_ExceptionMatches(PyObject* exc) { 102 return PyErr_GivenExceptionMatches(PyErr_Occurred(), exc); 103} 104 105PY_EXPORT void PyErr_Fetch(PyObject** pexc, PyObject** pval, PyObject** ptb) { 106 Thread* thread = Thread::current(); 107 Runtime* runtime = thread->runtime(); 108 DCHECK(pexc != nullptr, "pexc is null"); 109 if (thread->pendingExceptionType().isNoneType()) { 110 *pexc = nullptr; 111 } else { 112 *pexc = ApiHandle::newReference(runtime, thread->pendingExceptionType()); 113 } 114 DCHECK(pval != nullptr, "pval is null"); 115 if (thread->pendingExceptionValue().isNoneType()) { 116 *pval = nullptr; 117 } else { 118 *pval = ApiHandle::newReference(runtime, thread->pendingExceptionValue()); 119 } 120 DCHECK(ptb != nullptr, "ptb is null"); 121 if (thread->pendingExceptionTraceback().isNoneType()) { 122 *ptb = nullptr; 123 } else { 124 *ptb = 125 ApiHandle::newReference(runtime, thread->pendingExceptionTraceback()); 126 } 127 thread->clearPendingException(); 128} 129 130PY_EXPORT PyObject* PyErr_FormatV(PyObject* exception, const char* format, 131 va_list vargs) { 132 PyErr_Clear(); // Cannot call PyUnicode_FromFormatV with an exception set 133 134 PyObject* string = PyUnicode_FromFormatV(format, vargs); 135 PyErr_SetObject(exception, string); 136 Py_XDECREF(string); 137 return nullptr; 138} 139 140PY_EXPORT void PyErr_GetExcInfo(PyObject** p_type, PyObject** p_value, 141 PyObject** p_traceback) { 142 Thread* thread = Thread::current(); 143 HandleScope scope(thread); 144 Object caught_exc_state_obj(&scope, thread->topmostCaughtExceptionState()); 145 if (caught_exc_state_obj.isNoneType()) { 146 *p_type = nullptr; 147 *p_value = nullptr; 148 *p_traceback = nullptr; 149 return; 150 } 151 Runtime* runtime = thread->runtime(); 152 ExceptionState caught_exc_state(&scope, *caught_exc_state_obj); 153 *p_type = ApiHandle::newReference(runtime, caught_exc_state.type()); 154 *p_value = ApiHandle::newReference(runtime, caught_exc_state.value()); 155 *p_traceback = ApiHandle::newReference(runtime, caught_exc_state.traceback()); 156} 157 158PY_EXPORT int PyErr_GivenExceptionMatches(PyObject* given, PyObject* exc) { 159 if (given == nullptr || exc == nullptr) { 160 return 0; 161 } 162 Thread* thread = Thread::current(); 163 HandleScope scope(thread); 164 Object given_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(given))); 165 Object exc_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(exc))); 166 return givenExceptionMatches(thread, given_obj, exc_obj) ? 1 : 0; 167} 168 169PY_EXPORT PyObject* PyErr_NewException(const char* name, PyObject* base_or_null, 170 PyObject* dict_or_null) { 171 Thread* thread = Thread::current(); 172 const char* dot = std::strrchr(name, '.'); 173 if (dot == nullptr) { 174 thread->raiseWithFmt(LayoutId::kSystemError, 175 "PyErr_NewException: name must be module.class"); 176 return nullptr; 177 } 178 179 Runtime* runtime = thread->runtime(); 180 HandleScope scope(thread); 181 word mod_name_len = dot - name; 182 Object mod_name(&scope, 183 runtime->newStrWithAll( 184 {reinterpret_cast<const byte*>(name), mod_name_len})); 185 Object exc_name(&scope, runtime->newStrFromCStr(dot + 1)); 186 Object base(&scope, base_or_null == nullptr 187 ? runtime->typeAt(LayoutId::kException) 188 : ApiHandle::asObject(ApiHandle::fromPyObject(base_or_null))); 189 Object dict(&scope, dict_or_null == nullptr 190 ? runtime->newDict() 191 : ApiHandle::asObject(ApiHandle::fromPyObject(dict_or_null))); 192 Object type(&scope, thread->invokeFunction4(ID(builtins), ID(_exception_new), 193 mod_name, exc_name, base, dict)); 194 if (type.isError()) { 195 DCHECK(!type.isErrorNotFound(), "missing _exception_new"); 196 return nullptr; 197 } 198 return ApiHandle::newReference(runtime, *type); 199} 200 201PY_EXPORT PyObject* PyErr_NewExceptionWithDoc(const char* name, const char* doc, 202 PyObject* base_or_null, 203 PyObject* dict_or_null) { 204 Thread* thread = Thread::current(); 205 HandleScope scope(thread); 206 Runtime* runtime = thread->runtime(); 207 Object dict_obj(&scope, 208 dict_or_null == nullptr 209 ? runtime->newDict() 210 : ApiHandle::asObject(ApiHandle::fromPyObject(dict_or_null))); 211 if (doc != nullptr) { 212 if (!runtime->isInstanceOfDict(*dict_obj)) { 213 thread->raiseBadInternalCall(); 214 return nullptr; 215 } 216 Dict dict(&scope, *dict_obj); 217 Object doc_str(&scope, runtime->newStrFromCStr(doc)); 218 dictAtPutById(thread, dict, ID(__doc__), doc_str); 219 } 220 221 const char* dot = std::strrchr(name, '.'); 222 if (dot == nullptr) { 223 thread->raiseWithFmt(LayoutId::kSystemError, 224 "PyErr_NewException: name must be module.class"); 225 return nullptr; 226 } 227 228 word mod_name_len = dot - name; 229 Object mod_name(&scope, 230 runtime->newStrWithAll( 231 {reinterpret_cast<const byte*>(name), mod_name_len})); 232 Object exc_name(&scope, runtime->newStrFromCStr(dot + 1)); 233 Object base(&scope, base_or_null == nullptr 234 ? runtime->typeAt(LayoutId::kException) 235 : ApiHandle::asObject(ApiHandle::fromPyObject(base_or_null))); 236 Object type(&scope, 237 thread->invokeFunction4(ID(builtins), ID(_exception_new), 238 mod_name, exc_name, base, dict_obj)); 239 if (type.isError()) { 240 DCHECK(!type.isErrorNotFound(), "missing _exception_new"); 241 return nullptr; 242 } 243 return ApiHandle::newReference(runtime, *type); 244} 245 246PY_EXPORT void PyErr_NormalizeException(PyObject** exc, PyObject** val, 247 PyObject** tb) { 248 Thread* thread = Thread::current(); 249 HandleScope scope(thread); 250 251 Object exc_obj(&scope, *exc ? ApiHandle::asObject(ApiHandle::fromPyObject(*exc)) 252 : NoneType::object()); 253 Object exc_orig(&scope, *exc_obj); 254 Object val_obj(&scope, *val ? ApiHandle::asObject(ApiHandle::fromPyObject(*val)) 255 : NoneType::object()); 256 Object val_orig(&scope, *val_obj); 257 Object tb_obj(&scope, *tb ? ApiHandle::asObject(ApiHandle::fromPyObject(*tb)) 258 : NoneType::object()); 259 Object tb_orig(&scope, *tb_obj); 260 normalizeException(thread, &exc_obj, &val_obj, &tb_obj); 261 Runtime* runtime = thread->runtime(); 262 if (*exc_obj != *exc_orig) { 263 PyObject* tmp = *exc; 264 *exc = ApiHandle::newReference(runtime, *exc_obj); 265 Py_XDECREF(tmp); 266 } 267 if (*val_obj != *val_orig) { 268 PyObject* tmp = *val; 269 *val = ApiHandle::newReference(runtime, *val_obj); 270 Py_XDECREF(tmp); 271 } 272 if (*tb_obj != *tb_orig) { 273 PyObject* tmp = *tb; 274 *tb = ApiHandle::newReference(runtime, *tb_obj); 275 Py_XDECREF(tmp); 276 } 277} 278 279PY_EXPORT PyObject* PyErr_ProgramText(const char* /* e */, int /* o */) { 280 UNIMPLEMENTED("PyErr_ProgramText"); 281} 282 283PY_EXPORT PyObject* PyErr_SetExcFromWindowsErr(PyObject* /* c */, int /* r */) { 284 UNIMPLEMENTED("PyErr_SetExcFromWindowsErr"); 285} 286 287PY_EXPORT PyObject* PyErr_SetExcFromWindowsErrWithFilename( 288 PyObject* /* c */, int /* r */, const char* /* e */) { 289 UNIMPLEMENTED("PyErr_SetExcFromWindowsErrWithFilename"); 290} 291 292PY_EXPORT PyObject* PyErr_SetExcFromWindowsErrWithFilenameObject( 293 PyObject* /* c */, int /* r */, PyObject* /* t */) { 294 UNIMPLEMENTED("PyErr_SetExcFromWindowsErrWithFilenameObject"); 295} 296 297PY_EXPORT PyObject* PyErr_SetExcFromWindowsErrWithFilenameObjects( 298 PyObject* /* c */, int /* r */, PyObject* /* t */, PyObject* /* 2 */) { 299 UNIMPLEMENTED("PyErr_SetExcFromWindowsErrWithFilenameObjects"); 300} 301 302PY_EXPORT void PyErr_SetExcInfo(PyObject* type, PyObject* value, 303 PyObject* traceback) { 304 Thread* thread = Thread::current(); 305 HandleScope scope(thread); 306 Object type_obj(&scope, type == nullptr ? NoneType::object() 307 : ApiHandle::stealReference(type)); 308 thread->setCaughtExceptionType(*type_obj); 309 Object value_obj(&scope, value == nullptr ? NoneType::object() 310 : ApiHandle::stealReference(value)); 311 thread->setCaughtExceptionValue(*value_obj); 312 Object traceback_obj(&scope, traceback == nullptr 313 ? NoneType::object() 314 : ApiHandle::stealReference(traceback)); 315 thread->setCaughtExceptionTraceback(*traceback_obj); 316} 317 318PY_EXPORT PyObject* PyErr_SetFromErrno(PyObject* type) { 319 int errno_value = errno; 320 Thread* thread = Thread::current(); 321 HandleScope scope(thread); 322 Object type_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(type))); 323 Object none(&scope, NoneType::object()); 324 thread->raiseFromErrnoWithFilenames(type_obj, errno_value, none, none); 325 return nullptr; 326} 327 328PY_EXPORT PyObject* PyErr_SetFromErrnoWithFilename(PyObject* type, 329 const char* filename) { 330 int errno_value = errno; 331 Thread* thread = Thread::current(); 332 HandleScope scope(thread); 333 Object type_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(type))); 334 Object filename_obj(&scope, thread->runtime()->newStrFromCStr(filename)); 335 Object none(&scope, NoneType::object()); 336 thread->raiseFromErrnoWithFilenames(type_obj, errno_value, filename_obj, 337 none); 338 return nullptr; 339} 340 341PY_EXPORT PyObject* PyErr_SetFromErrnoWithFilenameObject(PyObject* type, 342 PyObject* filename) { 343 int errno_value = errno; 344 Thread* thread = Thread::current(); 345 HandleScope scope(thread); 346 Object type_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(type))); 347 Object filename_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(filename))); 348 Object none(&scope, NoneType::object()); 349 thread->raiseFromErrnoWithFilenames(type_obj, errno_value, filename_obj, 350 none); 351 return nullptr; 352} 353 354PY_EXPORT PyObject* PyErr_SetFromErrnoWithFilenameObjects(PyObject* type, 355 PyObject* filename0, 356 PyObject* filename1) { 357 int errno_value = errno; 358 Thread* thread = Thread::current(); 359 HandleScope scope(thread); 360 Object type_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(type))); 361 Object filename0_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(filename0))); 362 Object filename1_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(filename1))); 363 thread->raiseFromErrnoWithFilenames(type_obj, errno_value, filename0_obj, 364 filename1_obj); 365 return nullptr; 366} 367 368PY_EXPORT PyObject* PyErr_SetFromWindowsErr(int /* r */) { 369 UNIMPLEMENTED("PyErr_SetFromWindowsErr"); 370} 371 372PY_EXPORT PyObject* PyErr_SetFromWindowsErrWithFilename(int /* r */, 373 const char* /* e */) { 374 UNIMPLEMENTED("PyErr_SetFromWindowsErrWithFilename"); 375} 376 377PY_EXPORT PyObject* PyErr_SetImportError(PyObject* /* g */, PyObject* /* e */, 378 PyObject* /* h */) { 379 UNIMPLEMENTED("PyErr_SetImportError"); 380} 381 382PY_EXPORT PyObject* PyErr_SetImportErrorSubclass(PyObject* /* n */, 383 PyObject* /* g */, 384 PyObject* /* e */, 385 PyObject* /* h */) { 386 UNIMPLEMENTED("PyErr_SetImportErrorSubclass"); 387} 388 389PY_EXPORT void PyErr_SetNone(PyObject* type) { PyErr_SetObject(type, nullptr); } 390 391PY_EXPORT void PyErr_SetObject(PyObject* exc, PyObject* val) { 392 Thread* thread = Thread::current(); 393 if (exc == nullptr) { 394 DCHECK(val == nullptr, "nullptr exc with non-nullptr val"); 395 thread->clearPendingException(); 396 return; 397 } 398 399 HandleScope scope(thread); 400 Object exc_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(exc))); 401 402 Runtime* runtime = thread->runtime(); 403 if (!runtime->isInstanceOfType(*exc_obj) || 404 !Type(&scope, *exc_obj).isBaseExceptionSubclass()) { 405 Object exc_repr(&scope, 406 thread->invokeFunction1(ID(builtins), ID(repr), exc_obj)); 407 if (exc_repr.isErrorException()) return; 408 thread->raiseWithFmt(LayoutId::kSystemError, 409 "exception %S not a BaseException subclass", 410 &exc_repr); 411 return; 412 } 413 414 Type exc_type(&scope, *exc_obj); 415 Object val_obj(&scope, val == nullptr 416 ? NoneType::object() 417 : ApiHandle::asObject(ApiHandle::fromPyObject(val))); 418 val_obj = thread->chainExceptionContext(exc_type, val_obj); 419 if (val_obj.isError()) return; 420 thread->setPendingExceptionType(*exc_obj); 421 thread->setPendingExceptionValue(*val_obj); 422 if (runtime->isInstanceOfBaseException(*val_obj)) { 423 BaseException val_exc(&scope, *val_obj); 424 thread->setPendingExceptionTraceback(val_exc.traceback()); 425 } 426} 427 428PY_EXPORT void PyErr_SyntaxLocation(const char* /* e */, int /* o */) { 429 UNIMPLEMENTED("PyErr_SyntaxLocation"); 430} 431 432PY_EXPORT void PyErr_SyntaxLocationEx(const char* filename, int lineno, 433 int col_offset) { 434 PyObject* fileobj; 435 if (filename != nullptr) { 436 fileobj = PyUnicode_DecodeFSDefault(filename); 437 if (fileobj == nullptr) { 438 PyErr_Clear(); 439 } 440 } else { 441 fileobj = nullptr; 442 } 443 PyErr_SyntaxLocationObject(fileobj, lineno, col_offset); 444 Py_XDECREF(fileobj); 445} 446 447PY_EXPORT void PyErr_SyntaxLocationObject(PyObject* filename, int lineno, 448 int col_offset) { 449 PyObject *exc, *val, *tb; 450 // Add attributes for the line number and filename for the error 451 PyErr_Fetch(&exc, &val, &tb); 452 PyErr_NormalizeException(&exc, &val, &tb); 453 // XXX check that it is, indeed, a syntax error. It might not be, though. 454 PyObject* lineno_obj = PyLong_FromLong(lineno); 455 if (lineno_obj == nullptr) { 456 PyErr_Clear(); 457 } else { 458 if (PyObject_SetAttrString(val, "lineno", lineno_obj)) { 459 PyErr_Clear(); 460 } 461 Py_DECREF(lineno_obj); 462 } 463 PyObject* col_obj = nullptr; 464 if (col_offset >= 0) { 465 col_obj = PyLong_FromLong(col_offset); 466 if (col_obj == nullptr) { 467 PyErr_Clear(); 468 } 469 } 470 if (PyObject_SetAttrString(val, "offset", col_obj ? col_obj : Py_None)) { 471 PyErr_Clear(); 472 } 473 Py_XDECREF(col_obj); 474 if (filename != nullptr) { 475 if (PyObject_SetAttrString(val, "filename", filename)) { 476 PyErr_Clear(); 477 } 478 479 PyObject* text_obj = PyErr_ProgramTextObject(filename, lineno); 480 if (text_obj) { 481 if (PyObject_SetAttrString(val, "text", text_obj)) { 482 PyErr_Clear(); 483 } 484 Py_DECREF(text_obj); 485 } 486 } 487 if (exc != PyExc_SyntaxError) { 488 if (!PyObject_HasAttrString(val, "msg")) { 489 PyObject* msg_obj = PyObject_Str(val); 490 if (msg_obj) { 491 if (PyObject_SetAttrString(val, "msg", msg_obj)) { 492 PyErr_Clear(); 493 } 494 Py_DECREF(msg_obj); 495 } else { 496 PyErr_Clear(); 497 } 498 } 499 if (!PyObject_HasAttrString(val, "print_file_and_line")) { 500 if (PyObject_SetAttrString(val, "print_file_and_line", Py_None)) { 501 PyErr_Clear(); 502 } 503 } 504 } 505 PyErr_Restore(exc, val, tb); 506} 507 508static RawObject fileWriteObjectStrUnraisable(Thread* thread, 509 const Object& file, 510 const Object& obj) { 511 HandleScope scope(thread); 512 Object obj_str(&scope, thread->invokeFunction1(ID(builtins), ID(str), obj)); 513 if (obj_str.isError()) { 514 thread->clearPendingException(); 515 return *obj_str; 516 } 517 RawObject result = thread->invokeMethod2(file, ID(write), obj_str); 518 thread->clearPendingException(); 519 return result; 520} 521 522static RawObject fileWriteObjectReprUnraisable(Thread* thread, 523 const Object& file, 524 const Object& obj) { 525 HandleScope scope(thread); 526 Object obj_repr(&scope, thread->invokeFunction1(ID(builtins), ID(repr), obj)); 527 if (obj_repr.isError()) { 528 thread->clearPendingException(); 529 return *obj_repr; 530 } 531 RawObject result = thread->invokeMethod2(file, ID(write), obj_repr); 532 thread->clearPendingException(); 533 return result; 534} 535 536static RawObject fileWriteCStrUnraisable(Thread* thread, const Object& file, 537 const char* c_str) { 538 HandleScope scope(thread); 539 Object str(&scope, thread->runtime()->newStrFromFmt(c_str)); 540 RawObject result = thread->invokeMethod2(file, ID(write), str); 541 thread->clearPendingException(); 542 return result; 543} 544 545PY_EXPORT void PyErr_WriteUnraisable(PyObject* obj) { 546 Thread* thread = Thread::current(); 547 HandleScope scope(thread); 548 Object exc(&scope, thread->pendingExceptionType()); 549 Object val(&scope, thread->pendingExceptionValue()); 550 Object tb(&scope, thread->pendingExceptionTraceback()); 551 thread->clearPendingException(); 552 553 Runtime* runtime = thread->runtime(); 554 Object sys_stderr(&scope, 555 runtime->lookupNameInModule(thread, ID(sys), ID(stderr))); 556 if (obj != nullptr) { 557 if (fileWriteCStrUnraisable(thread, sys_stderr, "Exception ignored in: ") 558 .isError()) { 559 return; 560 } 561 Object object(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(obj))); 562 if (fileWriteObjectReprUnraisable(thread, sys_stderr, object).isError()) { 563 if (fileWriteCStrUnraisable(thread, sys_stderr, "<object repr() failed>") 564 .isError()) { 565 return; 566 } 567 } 568 if (fileWriteCStrUnraisable(thread, sys_stderr, "\n").isError()) { 569 return; 570 } 571 } 572 573 if (tb.isTraceback()) { 574 Traceback traceback(&scope, *tb); 575 Object err(&scope, tracebackWrite(thread, traceback, sys_stderr)); 576 DCHECK(!err.isErrorException(), "failed to write traceback"); 577 } 578 579 if (exc.isNoneType()) { 580 thread->clearPendingException(); 581 return; 582 } 583 584 DCHECK(runtime->isInstanceOfType(*exc), "exc must be a type"); 585 Type exc_type(&scope, *exc); 586 DCHECK(exc_type.isBaseExceptionSubclass(), 587 "exc must be a subclass of BaseException"); 588 // TODO(T42602623): If exc_type.name() is None, Remove dotted components of 589 // name, eg A.B.C => C 590 591 Object module_name_obj( 592 &scope, runtime->attributeAtById(thread, exc_type, ID(__module__))); 593 if (!runtime->isInstanceOfStr(*module_name_obj)) { 594 thread->clearPendingException(); 595 if (fileWriteCStrUnraisable(thread, sys_stderr, "<unknown>").isError()) { 596 return; 597 } 598 } else { 599 Str module_name(&scope, *module_name_obj); 600 if (!module_name.equalsCStr("builtins")) { 601 if (fileWriteObjectStrUnraisable(thread, sys_stderr, module_name) 602 .isError()) { 603 return; 604 } 605 if (fileWriteCStrUnraisable(thread, sys_stderr, ".").isError()) { 606 return; 607 } 608 } 609 } 610 611 if (exc_type.name().isNoneType()) { 612 if (fileWriteCStrUnraisable(thread, sys_stderr, "<unknown>").isError()) { 613 return; 614 } 615 } else { 616 Str exc_type_name(&scope, exc_type.name()); 617 if (fileWriteObjectStrUnraisable(thread, sys_stderr, exc_type_name) 618 .isError()) { 619 return; 620 } 621 } 622 623 if (!val.isNoneType()) { 624 if (fileWriteCStrUnraisable(thread, sys_stderr, ": ").isError()) { 625 return; 626 } 627 if (fileWriteObjectStrUnraisable(thread, sys_stderr, val).isError()) { 628 if (fileWriteCStrUnraisable(thread, sys_stderr, 629 "<exception str() failed>") 630 .isError()) { 631 return; 632 } 633 } 634 } 635 if (fileWriteCStrUnraisable(thread, sys_stderr, "\n").isError()) { 636 return; 637 } 638} 639 640PY_EXPORT void _PyErr_BadInternalCall(const char* filename, int lineno) { 641 Thread::current()->raiseWithFmt(LayoutId::kSystemError, 642 "%s:%d: bad argument to internal function", 643 filename, lineno); 644} 645 646PY_EXPORT PyObject* PyErr_ProgramTextObject(PyObject* filename, int lineno) { 647 if (filename == nullptr || lineno <= 0) { 648 return nullptr; 649 } 650 Thread* thread = Thread::current(); 651 HandleScope scope(thread); 652 Object filename_obj(&scope, ApiHandle::asObject(ApiHandle::fromPyObject(filename))); 653 Object lineno_obj(&scope, SmallInt::fromWord(lineno)); 654 Object result(&scope, 655 thread->invokeFunction2(ID(builtins), ID(_err_program_text), 656 filename_obj, lineno_obj)); 657 if (result.isErrorException()) { 658 thread->clearPendingException(); 659 return nullptr; 660 } 661 if (result == Str::empty()) { 662 return nullptr; 663 } 664 return ApiHandle::newReference(thread->runtime(), *result); 665} 666 667PY_EXPORT void PyErr_Restore(PyObject* type, PyObject* value, 668 PyObject* traceback) { 669 Thread* thread = Thread::current(); 670 if (type == nullptr) { 671 thread->setPendingExceptionType(NoneType::object()); 672 } else { 673 thread->setPendingExceptionType(ApiHandle::asObject(ApiHandle::fromPyObject(type))); 674 // This is a stolen reference, decrement the reference count 675 ApiHandle::decref(ApiHandle::fromPyObject(type)); 676 } 677 if (value == nullptr) { 678 thread->setPendingExceptionValue(NoneType::object()); 679 } else { 680 thread->setPendingExceptionValue( 681 ApiHandle::asObject(ApiHandle::fromPyObject(value))); 682 // This is a stolen reference, decrement the reference count 683 ApiHandle::decref(ApiHandle::fromPyObject(value)); 684 } 685 if (traceback != nullptr && 686 !ApiHandle::asObject(ApiHandle::fromPyObject(traceback)).isTraceback()) { 687 ApiHandle::decref(ApiHandle::fromPyObject(traceback)); 688 // Can only store traceback instances as the traceback 689 traceback = nullptr; 690 } 691 if (traceback == nullptr) { 692 thread->setPendingExceptionTraceback(NoneType::object()); 693 } else { 694 thread->setPendingExceptionTraceback( 695 ApiHandle::asObject(ApiHandle::fromPyObject(traceback))); 696 // This is a stolen reference, decrement the reference count 697 ApiHandle::decref(ApiHandle::fromPyObject(traceback)); 698 } 699} 700 701// Like PyErr_Restore(), but if an exception is already set, set the context 702// associated with it. 703PY_EXPORT void _PyErr_ChainExceptions(PyObject* exc, PyObject* val, 704 PyObject* tb) { 705 if (exc == nullptr) return; 706 707 if (PyErr_Occurred()) { 708 PyObject *exc2, *val2, *tb2; 709 PyErr_Fetch(&exc2, &val2, &tb2); 710 PyErr_NormalizeException(&exc, &val, &tb); 711 if (tb != nullptr) { 712 PyException_SetTraceback(val, tb); 713 Py_DECREF(tb); 714 } 715 Py_DECREF(exc); 716 PyErr_NormalizeException(&exc2, &val2, &tb2); 717 PyException_SetContext(val2, val); 718 PyErr_Restore(exc2, val2, tb2); 719 } else { 720 PyErr_Restore(exc, val, tb); 721 } 722} 723 724} // namespace py